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
全てGoで作るP2P対戦ゲーム入門
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ponyo877
September 27, 2025
Technology
2.1k
3
Share
全てGoで作るP2P対戦ゲーム入門
2025-09-27 | Go Conference 2025
ponyo877
September 27, 2025
More Decks by ponyo877
See All by ponyo877
フルスタックGoでスコア改ざんを防いだ話
ponyo877
0
780
filesystem風チャットchatsh開発で学んだGoの便利package紹介
ponyo877
1
380
Go言語の2Dゲームエンジン Ebitengineの紹介
ponyo877
2
180
OGPer あなたのサイトに簡単にOGPを付けよう
ponyo877
0
67
ISUCON14感想戦で85万点まで頑張ってみた
ponyo877
1
1.2k
Goのwasmで笑い男に挑戦してみた
ponyo877
1
230
GoのWasmでのWebRTC P2Pの検証+α
ponyo877
0
150
Ebitengineの1vs1ゲーム WebRTCの活用
ponyo877
0
770
GoのWasmでWebRTC P2Pで通信する
ponyo877
0
560
Other Decks in Technology
See All in Technology
カオナビに Suspenseを導入するまで / The Road to Suspense at kaonavi
kaonavi
1
440
AI時代に、 データアナリストがデータエンジニアに異動して
jackojacko_
0
580
Shiny New Tools Won't Fix Your Problem
trishagee
1
120
全社統制を維持しながら現場負担をどう減らすか〜プラットフォームチームとセキュリティチームで進めたSecurity Hub活用によるAWS統制の見直し〜/secjaws-security-hub-custom-insights
mhrtech
1
180
「背中を見て育て」からの卒業 〜専門技術としてのテスト設計を軸に、品質保証のバトンを繋ぐ〜 #genda_tech_talk
nihonbuson
PRO
1
910
いつの間にかデータエンジニア以外の業務も増えていたけど、意外と経験が役に立ってる
zozotech
PRO
0
340
みんなの考えた最強のデータ基盤アーキテクチャ'26前期〜前夜祭〜ルーキーズ_資料_遠藤な
endonanana
0
160
Purview 勉強会報告 Microsoft Purview 入門しようとしてみた
masakichixo
1
200
【技術書典20】OpenFOAM(自宅で深める流体解析)流れと熱移動(2)
kamakiri1225
0
380
AIの揺らぎに“コシ”を与える階層化品質設計
ickx
0
270
AI駆動開発で生産性を追いかけたら、行き着いたのは品質とシフトレフトだった
littlehands
0
470
毎日の作業を Claude Code 経由にしたら、 ノウハウがコードになった
kossykinto
1
1.2k
Featured
See All Featured
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
130
The Mindset for Success: Future Career Progression
greggifford
PRO
0
330
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
WENDY [Excerpt]
tessaabrams
10
37k
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.5k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
140
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
65
54k
Done Done
chrislema
186
16k
The SEO identity crisis: Don't let AI make you average
varn
0
460
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.8k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
1
370
BBQ
matthewcrist
89
10k
Transcript
全てGoで作るP2P対戦ゲーム入門 2025-09-27 | Go Conference 2025 ぽにょ / ponyo877
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 自己紹介 2
/ 29 ぽにょ / ponyo877 • GoでSaaSを作るエンジニア • X:@ponyo877 • GitHub:@ponyo877 • 好きなもの:映画館のポップコーン • 趣味:個人開発
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 本発表の得られること 全てGoで作るP2P対戦ゲームの実装例を知ることができる
3 / 29 かんぜんにりかいした
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 作ったゲーム Hit
& Blow 1対1で相手の選んだ数を相手より早く当てるゲーム プレイヤーはランダムに長さ3の数列が選ばれる(0~9, 重複なし) プレイヤーは相手の数列を推測する 毎回の推測に対して正解との近さが返るので、それをもとに推測の精度を高めてゆく... 例:推測 053 に対して 正解との近さ 1H 2B*が返ってきたら 035, 350, 503 のどれか 4 / 29 *H / Hit : 数字と位置が一致 *B / Blow : 数字は含むが位置は違う
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 通信要件 •
マッチングはインターネットを介してやりたい • 自分と対戦相手のターン制 • プレイヤーの操作は以下の形式のリクエストのみ ◦ 入力: 数列の推測 (例: 052, 193 etc...) ◦ 出力: 推測に対する近さ (例: 1H2B, 0H3B etc...) プレイヤー1 プレイヤー2 1 9 2 3 6 1 ① 推測: 306 ②近さ: 1H1B 両プレイヤーでクライアントと サーバの役割を交互に行え ば出来そう... 例: プレイヤー1からプレイヤー2への推測 5 / 29
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 デモ 6
/ 29
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 ゲーム開始までの流れ 1.
画面描画 2. マッチング 3. P2P接続 4. ゲーム開始 7 / 29 プレイヤー クライアント Ebitengine matchmaking signaling (Ayame) 相手 クライアント
画面描画 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 画面描画 画面はGo+Wasmで描画
HTML/JS/CSSは不使用 9 / 29 画面描画 マッチング ゲーム開始 P2P通信 制限時間タ イマー 数字キー ボード 推測の履 歴表示 推理対象の 数列 レート 入力中の 数列 マッチング開始
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 画面描画 |
Ebitengine 10 / 29 Opening Sessionにて SNKRDUNKさんのブースにて 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 画面描画 |
Ebitengine Go製の2Dゲームライブラリ 11 / 29 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 画面描画 |
Ebitengine 12 / 29 // 操作や時間経過によって起こる状態の更新 func (g *Game) Update() error { if IsButtonPressed(ButtonLeft) { g.gopher.Jump() } g.gopher.Drop() } // ゲーム画面の描画 func (g *Game) Draw(screen *ebiten.Image) { g.gopher.Draw() } 画面描画 マッチング ゲーム開始 P2P通信
マッチング 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 マッチング 1vs1なら以下だけで動作
• シンプルなQueue管理 • golang.org/x/net/websocket • goroutineで並行処理 14 / 29 for { if len(queue) >= 2 { roomID := entity.NewHash(now) p1, p2 := queue.Deq(), queue.Deq() // WebSocketでマッチしたことを送信 write(p1.Conn(), roomID, p2.ID()) write(p2.Conn(), roomID, p1.ID()) } } matching! 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 マッチング |
WebSocket クライアント/サーバ間で双方向通信ができる方式 15 / 29 WebSocket要求 WebSocket接続確立 双方向リアルタイム通信 画面描画 マッチング ゲーム開始 P2P通信
P2P通信 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 P2P接続 17
/ 29 従来のサーバ経由 • 遅延大 • サーバ運用コスト大 P2P (WebRTCなど) • サーバを介さないため遅延小 • サーバコスト0 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 P2P接続 |
WebRTC using pion/webrtc 18 / 29 画面描画 マッチング ゲーム開始 P2P通信 Web Real-Time Communication • ブラウザ間でのP2P通信できる、ビデオ通話が代表的 • WebRTC DataChannelで任意のデータ通信可能 • Goではpion/webrtcが有名 • 通信確立には接続用の情報交換が必要
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 P2P通信のための接続用の情報交換を仲介し、双方のブラウザが互いを 見つけて通信を始められるようにすること
signalingサーバのOSSとして時雨堂さんのWebRTC Signaling Server Ayameがある(Go製) P2P接続 | signalingサーバ using Ayame 19 / 29 画面描画 マッチング ゲーム開始 P2P通信
ゲーム開始 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 ゲームプレイ |
Hit&Blowのプレイデータ 5種類のJSONメッセージ 21 / 29 // ① ゲーム開始 {"type": "start", "first": true} // ② 推測送信 {"type": "guess", "data": [1,2,3]} // ③ 近さ返答 {"type": "answer", "hit": 1, "blow": 1} // ④ タイムアウト {"type": "timeout"} // ⑤ 手札公開 {"type": "expose", "hand": [4,5,6]} 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 ゲームプレイ |
channelによるデータ連携 Ebitengineとゲームロジックの橋渡しにchannelを使う 22 / 29 connectedCh chan bool // 接続完了通知 handCh chan [3]int // 手札情報 guessCh chan [3]int // 推測送信 historyCh chan History // 履歴更新 turnCh chan bool // ターン切替 resultCh chan Result // 勝敗判定 ratingCh chan RatingData // レート timerCh chan int // タイマー更新 画面描画 マッチング ゲーム開始 P2P通信 制限時間 タイマー 数字キー ボード 推測の履 歴表示 推理対象の 数列 レート 入力中の 数列
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 ゲームプレイ |
channelによるデータ連携 23 / 29 Ebitengine ゲームロジック 更新された データのみ 再描画 推測を送信 推測を受信 近さを送信 勝敗判定 操作をゲー ムロジックに 伝播 描画用 データ更新 Draw() Update() 推測ch 履歴ch 勝敗ch channel群 WebRTCでP2P通信 相手 クライアント 近さを受信 履歴ch ゲームデータ 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 ゲームプレイ |
channelによるデータ連携 24 / 29 if IsEnterKeyPushed() { guessCh <- numbers enterKey.Disable() return nil } select { case guess := <-guessCh: send(dc, guess) turnCh <- false } Ebitengine Draw() WebRTC データ受付 Ebitengine Update() 推測の送信 画面描画 マッチング ゲーム開始 P2P通信
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 Ebitengine Draw()
ゲームプレイ | channelによるデータ連携 25 / 29 select { case guess := <-guessCh: // 推測を受信 UpdateBoard(guess) case turn := <-turnCh: // ターン切替 ChangeTurn(turn) case time := <-timerCh: // タイマー更新 timer.Set(time) } switch message.Type { case "guess": // 推測を受信 guess := NewGuess(message.GuessData) guessCh <- guess case "turn_change": // ターン切替 turnCh <- isMyTurn timerCh <- 60 case "timer_update": // タイマー更新 remaining := message.TimeRemaining timerCh <- remaining } WebRTC データ受付 Ebitengine Update() 相手からのリクエスト受付やターン・タイマー管理 画面描画 マッチング ゲーム開始 P2P通信
おまけ
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 ゲームプレイ |
レーティングサーバ レーティングを計算・管理するGo製の単純なCRUDのAPIサーバ • なりすまし:ゲーム開始時に発行するハッシュ認証で防止 • 結果改ざん:両者の報告照合で防止 • 重複報告 :同一試合IDチェックで防止 ELO レーティング:チェスやeスポーツなどに使われるシステム 27 / 29
全てGoで作るP2P対戦ゲーム入門 | ponyo877 2025-09-27 | Go Conference 2025 まとめ 1.
GoでP2P対戦ゲームが作れる ◦ Wasm + WebRTCでサーバ負荷最小限 2. channelでゲームイベント管理 ◦ 複数channelで管理、並行処理が直感的 3. フルスタックGoの可能性 ◦ 言語統一によるスイッチコスト削減 28 / 29 かんぜんにりかいした 👈 Hit & Blowのリンク 👈 hit-and-blow.pages.dev/go/
ご清聴ありがとうございました