import { _decorator, Component, Node, Prefab, Label, Animation, instantiate, Vec3, tween } from 'cc'; import { WoodenManPlayer } from './WoodenManPlayer'; import { ModuleDef } from '../../scripts/ModuleDef'; import { resLoader } from '../../core_tgx/base/utils/ResLoader'; const { ccclass, property } = _decorator; // 玩家状态 enum PlayerState { ALIVE, // 存活 DEAD, // 死亡 QUALIFIED // 已晋级 } // 游戏阶段 export enum GamePhase { CHOOSE, // 选择阶段 MOVING, // 前进阶段 ROUND_END, // 回合结束 GAME_OVER // 游戏结束 } // 玩家数据 interface PlayerData { id: number; position: number; // 当前位置 state: PlayerState; selectedSteps: number; // 选择的步数 } @ccclass('WoodenManGame') export class WoodenManGame extends Component { @property(Prefab) rolePrefab: Prefab = null; // 角色预制体 @property(Node) dollNode: Node = null; // 木头人节点 @property(Label) aliveCountLabel: Label = null; // 存活人数显示 @property(Node) playersNode: Node = null; // 存放所有玩家的节点 // 游戏配置 private readonly TOTAL_ROUNDS = 15; // 总回合数 private readonly ROUND_TIME = 20; // 每回合时间(秒) private readonly TOTAL_DISTANCE = 12; // 终点距离(米) private readonly MIN_QUALIFIED = 20; // 最少晋级人数 private readonly INITIAL_PLAYERS = 36; // 初始玩家数 private readonly STEP_OPTIONS = [1, 2, 3, 4, 5, 6]; // 可选步数 // 游戏状态 private currentRound = 0; private currentPhase = GamePhase.CHOOSE; private remainingTime = 0; private dollTurnTime = 0; // 娃娃回头时间 private players: Map = new Map(); private aiPlayers: Node[] = []; // AI玩家节点列表 private playerNodes: Map = new Map(); // 所有玩家节点映射 async start() { await this.initPlayers(); this.initGame(); } private async initPlayers() { // 创建本地玩家 const localPlayer = await this.createPlayer(0, true); this.playerNodes.set(0, localPlayer); // 创建AI玩家 for (let i = 1; i < this.INITIAL_PLAYERS; i++) { const aiPlayer = await this.createPlayer(i, false); this.playerNodes.set(i, aiPlayer); this.aiPlayers.push(aiPlayer); } this.updateAliveCount(); } private async createPlayer(id: number, isLocal: boolean) { // 随机位置:以起点为中心,随机分布 const x = Math.random() * 10 - 5; // -5到5 const z = isLocal ? 0 : Math.random() * 4 - 2; // 本地玩家在起点,AI随机分布 // 随机角色ID(1-5) const roleId = Math.floor(Math.random() * 5) + 1; const roleIdStr = ('000' + roleId).slice(-3); const prefab: Prefab = await new Promise((resolve) => { resLoader.get(`common/role/Character${roleIdStr}`, Prefab, ModuleDef.Arean); }); if (prefab) { const role = instantiate(prefab); this.playersNode.addChild(role); role.setPosition(new Vec3(x, 0, z)); role.setRotationFromEuler(0, 180, 0); // 添加玩家组件 const playerComp = role.addComponent(WoodenManPlayer); playerComp.init(id, isLocal); return role; } return null; } // 更新存活人数显示 private updateAliveCount() { const aliveCount = Array.from(this.players.values()) .filter(p => p.state === PlayerState.ALIVE).length; this.aliveCountLabel.string = `存活: ${aliveCount}/${this.INITIAL_PLAYERS}`; } private initGame() { // 初始化玩家 for (let i = 0; i < this.INITIAL_PLAYERS; i++) { this.players.set(i, { id: i, position: 0, state: PlayerState.ALIVE, selectedSteps: 0 }); } this.startNewRound(); } private startNewRound() { this.currentRound++; this.remainingTime = this.ROUND_TIME; this.currentPhase = GamePhase.CHOOSE; this.dollTurnTime = Math.floor(Math.random() * 6) + 1; // 1-6秒随机 // 重置所有存活玩家的选择 this.players.forEach(player => { if (player.state === PlayerState.ALIVE) { player.selectedSteps = 0; } }); } // 玩家选择步数 public playerChooseSteps(playerId: number, steps: number) { if (this.currentPhase !== GamePhase.CHOOSE) return; const player = this.players.get(playerId); if (!player || player.state !== PlayerState.ALIVE) return; if (this.STEP_OPTIONS.indexOf(steps) !== -1) { player.selectedSteps = steps; } } // 执行移动阶段 private executeMovingPhase() { this.currentPhase = GamePhase.MOVING; // 播放木头人转身动画 this.playDollTurnAnimation(() => { this.players.forEach((player, id) => { if (player.state !== PlayerState.ALIVE) return; const steps = player.selectedSteps || 1; const playerNode = this.playerNodes.get(id); if (steps > this.dollTurnTime) { // 被抓到,播放死亡动画 this.killPlayer(player, playerNode); } else { // 移动玩家 this.movePlayer(player, playerNode, steps); } }); this.updateAliveCount(); }); } // 木头人转身动画 private playDollTurnAnimation(callback: () => void) { const duration = 1.0; // 转身动画持续时间 const currentRotation = this.dollNode.eulerAngles.clone(); const targetRotation = new Vec3(currentRotation.x, currentRotation.y + 180, currentRotation.z); // 使用 tween 实现平滑旋转 tween(this.dollNode) .to(duration, { eulerAngles: targetRotation }) .call(callback) .start(); } // 玩家死亡效果 private killPlayer(player: PlayerData, playerNode: Node) { player.state = PlayerState.DEAD; // 获取玩家组件 const playerComp = playerNode.getComponent(WoodenManPlayer); if (playerComp) { playerComp.setAlive(false); // 播放死亡动画,动画结束后重置位置 playerComp.playDieAnimation(() => { player.position = 0; // 重置到起点 playerNode.setPosition(new Vec3( Math.random() * 10 - 5, 0, 0 )); }); } } // 玩家移动效果 private movePlayer(player: PlayerData, playerNode: Node, steps: number) { const targetPos = new Vec3( playerNode.position.x, 0, player.position + steps ); // 使用 tween 实现平滑移动 tween(playerNode) .to(steps, { position: targetPos }) .start(); player.position += steps; if (player.position >= this.TOTAL_DISTANCE) { player.state = PlayerState.QUALIFIED; player.position = this.TOTAL_DISTANCE; // 播放胜利动画 const anim = playerNode.getComponent(Animation); anim.play('victory'); } } // AI决策 private updateAIDecisions() { if (this.currentPhase !== GamePhase.CHOOSE) return; this.aiPlayers.forEach(aiNode => { const playerComp = aiNode.getComponent(WoodenManPlayer); if (!playerComp || !playerComp.isAlive()) return; // 简单AI逻辑:随机选择1-3步 const steps = Math.floor(Math.random() * 3) + 1; this.playerChooseSteps(playerComp.getId(), steps); }); } // 检查游戏是否结束 private checkGameEnd(): boolean { let qualifiedCount = 0; this.players.forEach(player => { if (player.state === PlayerState.QUALIFIED) { qualifiedCount++; } }); return qualifiedCount >= this.MIN_QUALIFIED || this.currentRound >= this.TOTAL_ROUNDS; } // 游戏主循环 update(dt: number) { if (this.currentPhase === GamePhase.GAME_OVER) return; this.remainingTime -= dt; if (this.currentPhase === GamePhase.CHOOSE && this.remainingTime <= 0) { this.executeMovingPhase(); } if (this.currentPhase === GamePhase.MOVING) { // 移动阶段结束后 this.currentPhase = GamePhase.ROUND_END; if (this.checkGameEnd()) { this.endGame(); } else { this.startNewRound(); } } // 更新AI决策 this.updateAIDecisions(); } private endGame() { this.currentPhase = GamePhase.GAME_OVER; // 淘汰未晋级玩家 this.players.forEach(player => { if (player.state !== PlayerState.QUALIFIED) { player.state = PlayerState.DEAD; } }); // 这里可以触发游戏结束事件 this.node.emit('gameOver'); } // 获取游戏状态 public getGameState() { return { currentRound: this.currentRound, currentPhase: this.currentPhase, remainingTime: this.remainingTime, players: Array.from(this.players.values()) }; } public getCurrentPhase(): GamePhase { return this.currentPhase; } }