妄想ジャッジメント

https://github.com/ryosaburo/dip-cup

Next.js

GitHub

TypeScript

React

TailwindCSS

妄想か現実かリアルタイム・タイマン型心理戦バトル

小山龍馬

近藤秀樹

taso

野﨑誠

推しアイデア

運ゲーと心理戦をうまい具合に合わせてひりつくことができる

作った背景

リアルタイムで双方向通信でできる心理戦を作ってみたいと思ったため

推し技術

Github Actions

プロジェクト詳細

概要

チェスや将棋ほどのガッツリ頭を使って心理戦を行うものとそんなに頭を使わずにすらすらできるゲームのちょうど中間に当たるようなゲームを今回のハッカソンのお題である妄想を題材として制作を行いました。

ルール

同時選択ではなく、攻撃側と防御側が交互に手番を持つターン制を採用している。

  1. 攻撃側は、現実カード12種類の中からそのターン用にランダムで配られた3種類のいずれか、または妄想カードを選ぶ(妄想の場合はその場で申告ダメージ量も入力する)。配られる3種類は攻守交代のたびに毎回引き直されるimage
  2. 防御側は攻撃側が確定させた申告ダメージor回復量を確認したうえで、それが「現実」か「妄想」かを予想する(現実カードのどれかまでは予想しない)image
  3. 判定して結果を防御側に通知し、次のターンは攻守交代する(先攻はランダムに決定)image
  • 防御側が攻撃側のカードの種類を見破った場合:カードの効果は攻撃側にそのまま返らず、ダメージ系カードは攻撃側への反動ダメージ回復系カードは見破った防御側自身がそのライフを回復するという形で処理される
    • 見破られたのが妄想カードだった場合:ダメージ申告なら申告量が攻撃側への反動ダメージになり、回復申告なら見破った防御側が申告量だけ回復する。いずれの場合も攻撃側の妄想ゲージが申告量だけ上がり、さらに見破られる直前の妄想ゲージ%を確率とした抽選があり、外れると即座に妄想ゲージが100%になる(=即敗北扱い)
    • 見破られたのが現実カードだった場合:ダメージ系カードは反動ダメージのみで妄想ゲージは変動しない(「疼く傷跡」は継続ダメージも含めて攻撃側自身が受ける)。回復系カード(休息・無理な回復・緩やかな回復)は見破った防御側がそのライフを回復し、攻撃側は回復できない。瞑想(ゲージ系)のみ例外的にゲージが反転して上がる
  • 見破られなかった場合:申告・計算どおりの効果が発生する

勝利条件

  1. 相手プレイヤーの残りライフを0にする
  2. 相手プレイヤーの妄想ゲージを爆発させる
  3. 妄想カードを5回見破られずに使用する

技術構成

フロントエンド

  • Nuxt.js(App Router)
  • React
  • TypeScript

役割:画面表示・ユーザー操作の受付。Socket.ioクライアントでサーバーと通信する

スタイリング

  • Tailwind CSS

役割:UIのスタイリング全般

リアルタイム通信(クライアント)

  • socket.io-client

役割:WSサーバーとの双方向通信(ルーム作成・攻撃/防御の送受信)

リアルタイム通信(サーバー)

  • Socket.io(Node.js + Express)

役割:ルーム管理・イベントの送受信の基盤

ゲームロジック・共通型

  • @battle/shared(TypeScriptパッケージ)

役割: フロントエンド・サーバー双方から参照する型定義とゲーム判定の純粋関数(resolveTurnevaluateMatchOutcomeなど)。ロジックの二重実装を防ぐ

ゲーム状態管理

  • RoomManager(サーバー側、in-memoryクラス)

役割:ルームごとのプレイヤー・ライフ・妄想ゲージ・攻守などの状態を保持。永続化はせず、サーバー再起動で消える

認証

  • Supabase Auth

役割:メール・パスワードによる任意ログイン。未ログインでもゲストとしてプレイ可能

データ永続化

  • Supabase(Postgres)

役割: ログインユーザーのプロフィール・対戦履歴の保存(supabase/migrations/でスキーマ管理)。未設定でも動作する(ログイン関連機能のみ無効化)

フロントエンドホスティング

  • Vercel

役割: Next.jsアプリの本番・プレビューデプロイ。

WSサーバーホスティング

  • Render(Web Service)

役割: Socket.ioサーバーの常時稼働ホスティング。

VercelはWebSocketの常時接続ホスティングに不向きなため分離

CI

  • GitHub Actions(.github/workflows/ci.yml

役割: 後述

Github Actions

今回の開発ではPush -> marge の間にGithub Actionsを採用しました。 Github Actionsで

  • devmain宛PRで自動実行。sharedのビルド
  • server・frontendの型チェック
  • frontendのLint
  • serverのユニットテスト
  • frontendの本番ビルドを検証 を自動で全部行ってくれました。今回の開発のMVPは間違いなくGithub Actionsです。

詰まったところ

今回もともと考えていたものと方向性を変更せざるを得ないことになったのでチームのみんなで1から構想を考えて一気に実装まで持っていきました。もともと使用していた技術スタックはそのまま使用できて実装することができたのでなんとかなりました。

感想

  • いきなりの方向変換でデプロイまでできるかどうかわからなかったが無事にデプロイまでできてよかった。
  • 1からゲーム性を練って形にすることができてよかった
  • Githubの使い方がぐだぐだすぎてフロントエンドとして機能できなくなって悔しかった。次の機会は絶対にフロントエンドを書く。

小山龍馬

@490f244affb16b4f