Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Termfront: Ruby標準ライブラリだけで作るFPS
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
S.H.
May 31, 2026
84
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Termfront: Ruby標準ライブラリだけで作るFPS
関ケ原Ruby会議01
S.H.
May 31, 2026
More Decks by S.H.
See All by S.H.
Ruby on Bare Metal
gamelinks007
0
100
Ecosystem on parse.y
gamelinks007
0
420
ゆるゆるMastodon 鯖缶生活
gamelinks007
0
790
1週間で作るActivityPubリレーサーバ
gamelinks007
0
180
Rails 8で作るActivityPub リレーサーバ
gamelinks007
0
630
Developing an ActivityPub Relay with Rails 8
gamelinks007
0
110
Mastodon on Ruby master
gamelinks007
0
200
Trying to Make Ruby's Parser Available as a Gem
gamelinks007
1
690
ユーザーから見たLrama
gamelinks007
0
260
Featured
See All Featured
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
390
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
560
Writing Fast Ruby
sferik
630
63k
How to Talk to Developers About Accessibility
jct
2
230
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Done Done
chrislema
186
16k
Darren the Foodie - Storyboard
khoart
PRO
3
3.4k
Become a Pro
speakerdeck
PRO
31
6k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
Building AI with AI
inesmontani
PRO
1
1.1k
Skip the Path - Find Your Career Trail
mkilby
1
150
Transcript
Termfront Ruby標準ライブラリ だけで作るFPS S.H.
はじめに Termfrontをインストールしてください あとで合戦するのに使います gem install termfront
自己紹介 S.H. 平毛利石見守八郎秀穎 株式会社永和システムマネジメント Hamada.rb(石見国) FPS(First Person Shooter)が好きなRubyist 一番好きなFPSシリーズはHalo
関ケ原
合戦
FPS
Termfrontについて Terminal(端末)のFrontline(前線)から名付けた ターミナル上で遊べるFPSゲーム Rubyの標準ライブラリのみで実装している
標準ライブラリの一覧 io/consoleで描画やキー入力 json、socket、opensslをネットワーク周りに使って いる そのほかtimeoutなど諸々を使っている
FPSをプレイするタイミング 隙間時間にゲームを良くプレイしている 特にCIの待ち時間にプレイしている RubyのパッチのCIの待ち時間やMastodonのテストを 流しているときなど そうした時間にHaloを遊んでいた
プレイするタイミングがなくなってきた 最近はLLMを使い、ローカルでテストなどを実行でき る テストの修正などを随時確認する必要が出てきた インターバルが短くなり、Haloのミッションをこな すのは厳しい MarathonやDoomのように一区切りが短いFPSを作 ればよいのでは?
個人的な要望 昔のMarathonやDoomくらいのサッと遊べるサイズ ターミナル上でプレイ出来るとうれしい Ruby製の自作エディタで開発しているので、Rubyで 作ると使いやすそう
ライブラリなどに課題がある Rubyでゲームを作るとなると専用のライブラリが必 要になる あまりメンテナンスされていないことも多い ライブラリを使うのは簡単で、面白さに欠ける
出雲Ruby会議01でのアイディア 武将系プログラマーのa_matsudaさんのキーノート Ruby x Terminal io/consoleでテトリスを作られていた テトリスが動くなら、FPSも作れるはず 標準ライブラリだけでFPSを作れると面白そう
仕様を考える やりたいことはたくさんある キャンペーン機能 オンライン対戦モード トレーニングモード 全部を一度に作ることはできない 実現できるかどうかも不透明なまま
出来ないことを考える ターミナル上で動かすためフル3Dは難しい マウスでの上下左右のカメラ移動もできない 多分それ以外はなんとかなる
水平思考で考える 制限を逆手にとってやることを考える 疑似的な3Dを再現しよう 上下のカメラ移動はなくす 左右のカメラ移動は方向転換用に対応する かなりシンプルにできそう
初期実装の方針 疑似3Dでの移動とカメラ移動 敵などは無し これでオールドスクールなFPSが実現できれば良し
疑似3Dの手法を考える DoomやMarathonは2.5Dで高低差を付けるマップ Wolfensteinなどでは2Dマップに壁を描画する方法 今回はWolfensteinの手法を採用
疑似3Dのイメージ レイキャストとDDA (Digital Differential Analyzer) 左右の壁と床を描画し、立体的に見せる
レイキャストの手法 プレイヤーがいる位置から壁に向かって光を投げる 光が返ってくる距離で敵や壁の距離が算出できる それを使い、敵の大きさや壁の明暗を調整する
DDAの手法 レイキャストではピクセル単位で光を投げて距離を計 算する DDAでは格子状のマップを通る光を元に計算する レイキャストより高速に処理できる
レイキャスト vs DDA レイキャスト(毎ピクセル) DDA(格子境界だけ) +---+---+---+---+ +---+---+---+---+ | | |
|###| | | | |###| ### = 壁 +---+---+--*+---+ +---+---+---X---+ | | |** | | | | | /| | +---+--*+---+---+ +---+---X---+---+ | |** | | | | | /| | | +--*+---+---+---+ +---X---+---+---+ | P*| | | | | P/| | | | +---+---+---+---+ +---+---+---+---+ * を全部判定 → 遅い X(格子線)だけ → 速い
計算した距離から明暗を算出 相対距離が遠ければ暗くする 近い場合は明るくする def wall_brightness(dist, side) b = 255 -
[[(dist * 2.5).to_i, 0].max, 19].min b -= 3 if side == 1 b.clamp(233, 255) end
マップの実装 #が壁、.が床、*が敵スポーンの位置 壁判定は grid[iy][ix] == "#" の1行で済む [ "####################", "#........#.........#",
"#...........*......#", "####################" ]
入力処理 io/consoleで処理 矢印キーはESCシーケンス、WASDはバイトコードで パースしている STDIN.raw do |stdin| while IO.select([stdin], nil,
nil, 0) @pending << stdin.read_nonblock(64) end # ESC[A → :up, 119 → :w ... end
カメラ移動 上下のカメラ移動は実装しない 向きを変えるための左右のカメラ移動は必要 矢印キーで向きを変更できるように対応
初期実装
ゲームとして作りこむ 敵を表示させる HUDの表示
敵の描画について ターミナル上で画像を表示させるのは辛そう ゲーム内で敵の描画をさせたほうが良さそう
敵は楕円の式で描いてる 円より楕円のほうがセル比に乗りやすいため 楕円の式の組み合わせで目や体を描く def crawler(nx, ny) return "255;240;100" if ((nx-0.36)/0.063)**2
+ ((ny-0.28)/0.063)**2 <= 1 return "255;240;100" if ((nx-0.64)/0.063)**2 + ((ny-0.28)/0.063)**2 <= 1 return "220;140;30" if ((nx-0.5) /0.40)**2 + ((ny-0.40)/0.40)**2 <= 1 ... end
楕円でこの敵が出る
HUD FPSでは色々な情報をHUDから確認できる シールドや敵の位置などが分かるレーダーなどを追加
Rubyの標準ライブラリのみの限界 Rubyの標準ライブラリのみでは音の再生はできない 外部ライブラリを使うと「標準ライブラリのみ」の縛 りが崩れる 音の再生だけは外部ツールに任せた
BGMの再生 音声ファイル再生コマンドをPATHから自動検出 見つかったコマンドに Process.spawn で投げる 実装自体はRubyと標準ライブラリのみ @bgm_player = detect_player( %w[ffplay
afplay paplay aplay], prefer_loop: true ) Process.spawn(*command, pgroup: true, out: File::NULL, err: File::NULL)
使用させていただいた音源 SRG774 — Dark Sci-Fi Audio Pack rubberduck — 50/60
CC0 Sci-Fi SFX StumpyStrust — UI Sounds すべて opengameart.org の CC0 素材
ゲームっぽくなってきた
メニュー画面 タイトル画面自体が疑似3Dエンジンを動かしている PvPなどのモードをキーで選択
モードを追加する トレーニングモード キャンペーンモード オンライン対戦モード オンライン協力モード
トレーニングモード 武器による当たり判定 プレイヤーと敵のライフ管理
当たり判定の実装 キャンペーンモードなどでは目標がセンターに入れば 当たる仕組み 壁越しでは弾が当たらないようにしている
シールドとライフ Haloライクなシールドとライフの組み合わせ シールドが切れてからライフが削れ、暫く経つと自動 再生
キャンペーンモード Haloにあるミッション選択式のキャンペーン
キャンペーンモードの実装 トレーニングモードをベースにミッション単位でマッ プなどの情報を用意 難易度の選択などを実装 ミッション開始時にダイアログを差し込む
オンライン対戦モード よくあるマルチプレイヤー
オンライン対戦モードの実装 json, socket, opensslを使っている クライアントからプレイヤーの位置情報などをサー バーへ送る それを用いて当たり判定などを管理している 1vs1, 2vs2, 4vs4などの複数の部屋が作れるように
なっている
サーバーのTLS通信について Let’s Encryptで証明書を発行 VERIFY_PEERとホスト名の検証を行っている ctx = OpenSSL::SSL::SSLContext.new ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.verify_hostname = true ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION ctx.cert_store.set_default_paths @sock.hostname = host @sock.connect @sock.post_connection_check(host)
オンライン協力モード Haloでいうところのファイヤファイト AIの敵をどんどん倒していき、ウェーブをクリアしてい くゲーム
デモという名の合戦 ただデモをやるのも面白くないのでみんなで合戦をや りましょう できれば壇上の僕と会場の皆さんで合戦をしたいので ぜひ参加してください gem install termfront
合戦ルール マッチメイクは4v4 敵を全滅させたほうが勝ち 操作方法はWASDキーで移動、左右の矢印キーでカメ ラ移動、スペースで攻撃 発表の時間の関係上、できるだけ速やかに敵を倒して ください
合戦
さいごに 工夫すればRubyの標準ライブラリだけでもゲームを 作れる これをベースにFPSゲームエンジンを作りたいと考え ている 皆さんと合戦ができ、関ケ原ならではの発表ができて 楽しかったです