Skip to content

游戏阶段流程

TuringHunt 基于**阿瓦隆(Avalon)**规则,游戏通过 phase 字段驱动 UI 切换。

阶段状态机

waiting
  └─► speaking
        └─► team_select
              └─► team_vote
                    ├─► (approved) mission
                    │       ├─► (未决) team_select (下一任务)
                    │       └─► (邪恶 3 胜) assassin
                    │                 └─► game_over
                    └─► (rejected × 5) game_over

好人方完成 3 次任务且进入 assassin 阶段后,若刺客猜中梅林,邪恶方仍可翻盘。

各阶段说明

waiting — 等待房间

组件WaitingRoom.tsx

玩家列表实时展示所有已加入的玩家。房主(或任意玩家)点击"开始游戏"后,服务端分配角色并广播 ROLE_ASSIGNED 消息。

关键交互

  • 发送 { type: "START_GAME", data: null }

speaking — 发言阶段

组件SpeakingPhase.tsx

玩家按顺序依次发言,每次只有当前 currentSpeakerId 的玩家可以输入内容。发言内容经服务端广播后,所有人的 SpeechHistorySidebar 实时更新。

状态字段

  • isSpeaker — 当前轮是否轮到自己发言
  • currentSpeakerId — 正在发言的玩家 ID
  • speeches — 本轮实时发言流

关键交互

  • 发送 { type: "SPEECH", data: { content } } 提交发言
  • 发送 { type: "END_SPEECH", data: null } 结束本人发言

team_select — 组队阶段

组件TeamSelectPhase.tsx

当前领袖(leaderId)从玩家列表中选择 requiredTeamSize 名成员组成任务队伍。

状态字段

  • leaderId — 当前领袖的 user_id
  • requiredTeamSize — 本任务所需队员人数

关键交互(仅领袖可操作):

  • 发送 { type: "SUBMIT_TEAM", data: { team: string[] } }

team_vote — 队伍投票阶段

组件TeamVotePhase.tsx

所有玩家对提议的队伍进行公开投票(赞成/反对)。服务端收集全部投票后广播 TEAM_VOTE_RESULT

连续 5 次投票失败(consecutiveVoteFailures === 5)时游戏直接结束,邪恶方获胜。

关键交互

  • 发送 { type: "VOTE", data: { vote: boolean } }

结果展示VoteResult.tsx overlay 临时显示后自动消失。


mission — 任务执行阶段

组件MissionPhase.tsx

只有被选中的队员可以操作。好人队员只能投成功票;邪恶队员可以选择成功或失败。投票结果通过 MISSION_RESULT 广播(只显示失败票数,不公开具体投票人)。

关键交互(仅任务队员):

  • 发送 { type: "VOTE", data: { vote: boolean } }true 代表成功,false 代表破坏

结果展示MissionResult.tsx + MissionTracker.tsx 顶部进度更新。


assassin — 刺杀阶段

组件AssassinPhase.tsx

好人方已赢得 3 次任务,但游戏尚未结束。刺客玩家(role === "assassin")需要从好人阵营中指定一名玩家,若猜中梅林(Merlin),邪恶方翻盘获胜。

关键交互(仅刺客):

  • 发送 { type: "ASSASSIN_CHOOSE", data: { target_id: string } }

game_over — 游戏结束

组件GameOver.tsx

服务端推送 GAME_OVER 消息,包含:

  • winner"good""evil"
  • reason — 胜利原因
  • role_reveal — 全员身份公开映射表

阶段切换动画

每次 phase 变更时,PhaseAnnouncement.tsx 组件会在全屏弹出一个 framer-motion 动画公告,持续约 2 秒后自动消失,避免玩家错过阶段切换提示。

TuringHunt Frontend