squidGame/tgx-games-client/assets/module_arean/level1/Script/WoodenManGame.ts

624 lines
22 KiB
TypeScript
Raw Normal View History

2025-03-06 22:47:02 +08:00
import { _decorator, Component, Node, Prefab, Label, Animation, instantiate, Vec3, tween, macro, Sprite, Color, Button, animation, director, assetManager } from 'cc';
2025-02-21 10:45:46 +08:00
import { WoodenManPlayer } from './WoodenManPlayer';
2025-03-06 22:46:48 +08:00
import { tgxAudioMgr } from 'db://assets/core_tgx/tgx';
import { ModuleDef } from 'db://assets/scripts/ModuleDef';
import { resLoader } from 'db://assets/core_tgx/base/utils/ResLoader';
import { EMusicDefine } from 'db://assets/module_basic/scripts/MusicDefine';
2025-03-07 13:33:59 +08:00
import { SceneDef } from 'db://assets/scripts/SceneDef';
2025-03-23 09:07:30 +08:00
import { ScenePreloadManager } from 'db://assets/scripts/ScenePreloadManager';
2025-02-21 10:45:46 +08:00
const { ccclass, property } = _decorator;
2025-03-01 02:24:46 +08:00
2025-02-21 10:45:46 +08:00
@ccclass('WoodenManGame')
export class WoodenManGame extends Component {
@property(Prefab)
rolePrefab: Prefab = null; // 角色预制体
@property(Node)
dollNode: Node = null; // 木头人节点
@property(Label)
aliveCountLabel: Label = null; // 存活人数显示
2025-03-06 10:50:18 +08:00
@property(Label)
winCountLabel: Label = null; // 晋级名额显示
2025-02-21 10:45:46 +08:00
@property(Node)
playersNode: Node = null; // 存放所有玩家的节点
2025-03-01 02:24:46 +08:00
@property(Node)
2025-03-06 10:50:18 +08:00
localPlayerNode: Node = null; // 本地玩家节点引用
2025-03-01 02:24:46 +08:00
2025-03-06 10:50:18 +08:00
@property(Node)
guiNode: Node = null; // ui节点
2025-03-01 02:24:46 +08:00
2025-03-23 02:31:54 +08:00
@property(Label)
timerLabel: Label = null!; // 倒计时文本显示
2025-02-21 10:45:46 +08:00
2025-03-06 22:47:02 +08:00
private turnAnimationDuration: number = 0.3; // 转身动画持续时间
2025-03-06 10:50:18 +08:00
private readonly TURN_BACK_DELAY = 2; // 转回正面的延迟时间
private readonly INITIAL_PLAYERS = 36; // 初始玩家数
2025-02-21 10:45:46 +08:00
private aiPlayers: Node[] = []; // AI玩家节点列表
private playerNodes: Map<number, Node> = new Map(); // 所有玩家节点映射
2025-03-06 10:50:18 +08:00
private readonly minRoleId: number = 1; // 最小角色ID
readonly maxRoleId: number = 5;
2025-03-06 22:47:02 +08:00
readonly REQUIRED_QUALIFIED = 10; // 需要晋级的人数
2025-03-06 10:50:18 +08:00
qualifiedCount: number = 0; // 已晋级人数
2025-03-23 02:31:54 +08:00
gameTimer: number = 120; // 游戏时间2分钟
2025-03-06 10:50:18 +08:00
isGameOver: boolean = false; // 游戏是否结束
2025-03-23 02:31:54 +08:00
private isCountdownStarted: boolean = false; // 是否已开始倒计时
private startDelay: number = 0; // 延迟多久开始倒计时
2025-03-06 10:50:18 +08:00
@property(Node)
warningLightsNode: Node = null; // 三个警示灯的父节点
private readonly WARNING_LIGHT_BASE_INTERVAL = 1; // 修改基础间隔为0.7秒
private isGameStarted: boolean = false; // 添加游戏是否已开始的标志
@property(Node)
stopButton: Node = null; // 改为停止按钮引用
@property(Animation)
goAnim: Animation;
private isDollTurning: boolean = false; // 添加标记,表示娃娃是否正在转身
private turnStartTime: number = 0; // 记录转身开始时间
// 添加公共 getter 方法
public getGameStarted(): boolean {
return this.isGameStarted;
}
public getIsDollTurning(): boolean {
return this.isDollTurning;
}
2025-02-21 10:45:46 +08:00
async start() {
await this.initPlayers();
2025-03-06 10:50:18 +08:00
this.updateWinCount();
tgxAudioMgr.inst.play(EMusicDefine.MUSIC_BGM_BATTLE, 1, ModuleDef.BASIC);
// 修改按钮事件监听
if (this.stopButton) {
this.stopButton.active = false; // 初始隐藏
this.stopButton.on(Node.EventType.TOUCH_START, this.onStopButtonPress, this);
this.stopButton.on(Node.EventType.TOUCH_END, this.onStopButtonRelease, this);
this.stopButton.on(Node.EventType.TOUCH_CANCEL, this.onStopButtonRelease, this);
}
2025-03-23 02:31:54 +08:00
// 初始化计时器显示
if (this.timerLabel) {
this.updateTimerDisplay();
}
2025-03-06 10:50:18 +08:00
// 延迟3秒后开始第一次转身
this.scheduleOnce(() => {
this.isGameStarted = true; // 标记游戏开始
// 显示停止按钮
this.guiNode.getComponent(Animation).play("showUI");
this.executeTurnBackPhase(true);
2025-03-23 02:31:54 +08:00
// 开始倒计时
this.scheduleOnce(() => {
this.startCountdown();
}, this.startDelay);
2025-03-06 22:47:02 +08:00
}, 12); // 延长等待时间,等摄像机序列播放完
2025-03-06 10:50:18 +08:00
}
onDestroy() {
// 停止所有定时器
this.unscheduleAllCallbacks();
// 停止所有 tween
if (this.dollNode) {
tween(this.dollNode).stop();
}
// 停止所有玩家的 tween 和动画
this.playerNodes.forEach((playerNode) => {
2025-03-06 22:47:02 +08:00
if (playerNode && playerNode.isValid) {
tween(playerNode).stop();
const playerComp = playerNode.getComponent(WoodenManPlayer);
if (playerComp && playerComp.isValid) {
try {
playerComp.cleanup();
} catch (error) {
console.warn('Error cleaning up player:', error);
}
}
2025-03-06 10:50:18 +08:00
}
});
// 停止警示灯相关
2025-03-06 22:47:02 +08:00
if (this.warningLightsNode && this.warningLightsNode.isValid) {
2025-03-06 10:50:18 +08:00
this.warningLightsNode.children.forEach(light => {
2025-03-06 22:47:02 +08:00
if (light && light.isValid) {
tween(light).stop();
}
2025-03-06 10:50:18 +08:00
});
}
// 取消按钮事件监听
2025-03-06 22:47:02 +08:00
if (this.stopButton && this.stopButton.isValid) {
2025-03-06 10:50:18 +08:00
this.stopButton.off(Node.EventType.TOUCH_START, this.onStopButtonPress, this);
this.stopButton.off(Node.EventType.TOUCH_END, this.onStopButtonRelease, this);
this.stopButton.off(Node.EventType.TOUCH_CANCEL, this.onStopButtonRelease, this);
}
// 停止音频
2025-03-06 22:47:02 +08:00
try {
tgxAudioMgr.inst.stop();
} catch (error) {
console.warn('Error stopping audio:', error);
}
2025-03-06 10:50:18 +08:00
}
// 修改按钮事件处理
private onStopButtonPress() {
const localPlayer = this.localPlayerNode?.getComponent(WoodenManPlayer);
if (localPlayer && localPlayer.isAlive() && !localPlayer.isPassed()) {
localPlayer.setButtonPressed(true);
localPlayer.stopMoving();
}
}
private onStopButtonRelease() {
const localPlayer = this.localPlayerNode?.getComponent(WoodenManPlayer);
if (localPlayer && localPlayer.isAlive() && !localPlayer.isPassed()) {
localPlayer.setButtonPressed(false);
localPlayer.startMoving();
}
2025-02-21 10:45:46 +08:00
}
private async initPlayers() {
2025-03-01 02:24:46 +08:00
// 初始化本地玩家
if (this.localPlayerNode) {
2025-03-06 10:50:18 +08:00
const playerComp = this.localPlayerNode.getComponent(WoodenManPlayer);
playerComp.init(0, true, this); // 设置为本地玩家
// 添加随机位置设置
2025-03-06 22:47:02 +08:00
const x = 0;
2025-03-06 10:50:18 +08:00
//const x = Math.random() * 15 - 7;
const z = 50 + Math.random() * 5;
this.localPlayerNode.setPosition(new Vec3(x, 0, z));
this.localPlayerNode.setRotationFromEuler(0, 180, 0);
// 添加本地玩家名字
const nameLabel = this.localPlayerNode.getChildByName("NameLabel");
if (nameLabel) {
const labelComponent = nameLabel.getComponent(Label);
if (labelComponent) {
labelComponent.string = "You"; // 本地玩家显示为 "You"
labelComponent.color = new Color(255, 255, 0, 255); // 黄色
}
}
nameLabel.active = false;
2025-03-01 02:24:46 +08:00
this.playerNodes.set(0, this.localPlayerNode);
}
2025-02-21 10:45:46 +08:00
// 创建AI玩家
for (let i = 1; i < this.INITIAL_PLAYERS; i++) {
2025-03-01 02:24:46 +08:00
const aiPlayer = await this.createPlayer(i);
2025-02-21 10:45:46 +08:00
this.playerNodes.set(i, aiPlayer);
this.aiPlayers.push(aiPlayer);
}
this.updateAliveCount();
}
2025-03-06 10:50:18 +08:00
private async createPlayer(id: number): Promise<Node> {
return new Promise((resolve) => {
// 随机位置:起点区域
2025-03-14 10:25:36 +08:00
const x = Math.random() * 15 - 8;
2025-03-06 22:47:02 +08:00
const z = 50 + Math.random() * 3; // 50-55随机
2025-03-06 10:50:18 +08:00
// 随机角色ID1-5
const roleId = Math.floor(Math.random() * (this.maxRoleId - this.minRoleId + 1)) + this.minRoleId;
const roleIdStr = ('000' + roleId).slice(-3);
resLoader.load(ModuleDef.Arean, `common/role/Character${roleIdStr}`, (err: Error | null, prefab: Prefab) => {
if (!err && prefab) {
const role = instantiate(prefab);
this.playersNode.addChild(role);
// 设置位置和朝向(面向-Z方向
role.setPosition(new Vec3(x, 0, z));
role.setRotationFromEuler(0, 180, 0);
// 添加 WoodenManPlayer 组件
const playerComp = role.addComponent(WoodenManPlayer);
playerComp.init(id, false, this);
// 添加角色名字NameLabel
const nameLabel = role.getChildByName("NameLabel");
if (nameLabel) {
const labelComponent = nameLabel.getComponent(Label);
if (labelComponent) {
labelComponent.string = `player${id}`;
labelComponent.color = new Color(255, 255, 255, 255);
}
}
nameLabel.active = false;
resolve(role);
} else {
console.error('Failed to load character prefab:', err);
resolve(null);
}
});
});
2025-02-21 10:45:46 +08:00
}
// 更新存活人数显示
private updateAliveCount() {
2025-03-01 02:24:46 +08:00
let aliveCount = 0;
this.playerNodes.forEach((node) => {
const player = node.getComponent(WoodenManPlayer);
if (player && player.isAlive()) {
aliveCount++;
2025-02-21 10:45:46 +08:00
}
});
2025-03-06 10:50:18 +08:00
this.aliveCountLabel.string = `${aliveCount}/${this.INITIAL_PLAYERS}`;
2025-02-21 10:45:46 +08:00
}
2025-03-06 10:50:18 +08:00
// 修改 startFirstTurn 方法
2025-03-01 02:24:46 +08:00
2025-03-06 10:50:18 +08:00
// 修改 executeTurnBackPhase 方法
2025-03-06 22:47:02 +08:00
private executeTurnBackPhase(firstTimes: boolean = false) {
2025-03-06 10:50:18 +08:00
if (!this.isGameStarted || this.isGameOver) return;
tgxAudioMgr.inst.playOneShot(EMusicDefine.WOODENMAN_GO, 1, ModuleDef.BASIC);
this.goAnim.getComponent(Animation).play("showGo");
// 直接执行转身动画
this.playDollTurnAnimation();
this.playerNodes.forEach((playerNode) => {
const playerComp = playerNode.getComponent(WoodenManPlayer);
if (playerComp && (firstTimes || !playerComp.getIsLocalPlayer()) && playerComp.isAlive() && !playerComp.isPassed()) {
playerComp.setButtonPressed(false);
// 添加随机延迟0-0.3秒)
2025-03-01 02:24:46 +08:00
this.scheduleOnce(() => {
2025-03-06 10:50:18 +08:00
playerComp.startMoving();
2025-03-06 22:47:02 +08:00
}, Math.random() * 0.3 + 0.3);
2025-03-06 10:50:18 +08:00
}
});
// 延迟后开始下一轮
this.scheduleOnce(() => {
this.executeTurningPhase();
}, this.TURN_BACK_DELAY);
2025-02-21 10:45:46 +08:00
2025-03-06 10:50:18 +08:00
}
private executeTurningPhase() {
// 先播放警告音效和警示灯
tgxAudioMgr.inst.playOneShot(EMusicDefine.WOODENMAN, 1, ModuleDef.BASIC);
if (this.warningLightsNode) {
this.warningLightsNode.active = true;
// AI玩家在警示灯期间随机停止
this.playerNodes.forEach((playerNode) => {
const playerComp = playerNode.getComponent(WoodenManPlayer);
if (playerComp && !playerComp.getIsLocalPlayer() && playerComp.isAlive() && !playerComp.isPassed()) {
2025-03-06 22:47:02 +08:00
const stopDelay = Math.random() * 1.8 + 2.5;
2025-03-01 02:24:46 +08:00
this.scheduleOnce(() => {
if (playerComp.isAlive() && playerComp.isMoving) {
2025-03-06 10:50:18 +08:00
playerComp.setButtonPressed(true);
2025-03-01 02:24:46 +08:00
playerComp.stopMoving();
}
}, stopDelay);
2025-03-06 10:50:18 +08:00
}
2025-03-01 02:24:46 +08:00
});
2025-02-21 10:45:46 +08:00
2025-03-06 10:50:18 +08:00
// 播放警示灯序列
this.playWarningLights(() => {
if (this.warningLightsNode) {
this.warningLightsNode.active = false;
}
2025-02-21 10:45:46 +08:00
2025-03-06 10:50:18 +08:00
// 开始转身
this.playDollTurnAnimation(() => {
// 等待0.3秒后开始检查移动状态
this.scheduleOnce(() => {
this.schedule(this.checkMovingInterval, 0);
tgxAudioMgr.inst.playOneShot(EMusicDefine.WOODENMAN_Kill, 1, ModuleDef.BASIC);
}, 0.3);
});
2025-02-21 10:45:46 +08:00
2025-03-06 10:50:18 +08:00
// 延迟后开始下一轮
this.scheduleOnce(() => {
this.unschedule(this.checkMovingInterval);
this.executeTurnBackPhase();
}, Math.round((3 + Math.random() * 2) * 10) / 10);
});
}
}
2025-03-01 02:24:46 +08:00
2025-03-06 10:50:18 +08:00
checkMovingInterval() {
const currentTime = Date.now();
const timeSinceTurnStart = (currentTime - this.turnStartTime) / 1000; // 转换为秒
this.playerNodes.forEach((playerNode) => {
const playerComp = playerNode.getComponent(WoodenManPlayer);
if (playerComp && playerComp.isAlive() && !playerComp.isPassed()) {
2025-03-01 02:24:46 +08:00
if (playerComp.isMoving) {
2025-03-06 10:50:18 +08:00
if (timeSinceTurnStart > 0.3) { // 如果在转身0.3秒后还在移动
this.killPlayer(playerComp, playerNode);
}
2025-03-01 02:24:46 +08:00
}
2025-03-06 10:50:18 +08:00
}
2025-02-21 10:45:46 +08:00
});
}
// 检查游戏是否结束
private checkGameEnd(): boolean {
2025-03-06 10:50:18 +08:00
if (this.isGameOver) return true;
let aliveCount = 0;
2025-02-21 10:45:46 +08:00
let qualifiedCount = 0;
2025-03-06 10:50:18 +08:00
let totalCount = 0;
2025-03-01 02:24:46 +08:00
this.playerNodes.forEach((playerNode) => {
const playerComp = playerNode.getComponent(WoodenManPlayer);
2025-03-06 10:50:18 +08:00
if (playerComp) {
totalCount++;
if (playerComp.isAlive()) aliveCount++;
if (playerComp.isPassed()) qualifiedCount++;
2025-02-21 10:45:46 +08:00
}
});
2025-03-06 10:50:18 +08:00
// 如果所有玩家都要么死亡要么晋级,游戏结束
if (qualifiedCount + (totalCount - aliveCount) === totalCount) {
this.endGame('所有玩家已完成比赛!游戏结束');
return true;
}
return false;
2025-02-21 10:45:46 +08:00
}
// 游戏主循环
update(dt: number) {
2025-03-06 10:50:18 +08:00
if (!this.isGameOver) {
this.checkGameEnd();
2025-02-21 10:45:46 +08:00
}
}
2025-03-06 10:50:18 +08:00
endGame(reason: string = '') {
if (this.isGameOver) return;
this.isGameOver = true;
2025-03-23 02:31:54 +08:00
this.isCountdownStarted = false;
2025-03-06 10:50:18 +08:00
this.unscheduleAllCallbacks(); // 停止所有定时器
2025-03-06 22:47:02 +08:00
2025-03-06 10:50:18 +08:00
// 如果是因为达到晋级人数而结束,则击杀所有未晋级的存活玩家
if (reason.includes('达到晋级人数要求')) {
this.killAllNonQualifiedPlayers();
}
// 统计最终结果
let qualifiedPlayers = 0;
let deadPlayers = 0;
2025-03-01 02:24:46 +08:00
this.playerNodes.forEach((playerNode) => {
const playerComp = playerNode.getComponent(WoodenManPlayer);
2025-03-06 10:50:18 +08:00
if (playerComp) {
if (playerComp.isPassed()) qualifiedPlayers++;
if (!playerComp.isAlive()) deadPlayers++;
2025-02-21 10:45:46 +08:00
}
});
2025-03-06 10:50:18 +08:00
// 更新最终显示
this.updateWinCount();
this.updateAliveCount();
2025-03-06 22:47:02 +08:00
this.scheduleOnce(() => {
resLoader.load(ModuleDef.Arean, 'common/prefabs/settlement', (err: Error | null, prefab: Prefab) => {
if (!err && prefab) {
const n = instantiate(prefab);
this.guiNode.addChild(n);
n.getComponent(Animation).play("showSettlement");
// Lives从10滚动到8
const livesLabel = n.getChildByPath("settlementNode/Node/lives").getComponent(Label);
let lives = { value: 36 };
tween(lives)
.to(1, { value: 10 }, {
easing: 'linear',
onUpdate: () => {
livesLabel.string = Math.floor(lives.value).toString();
}
})
.start();
// Money从400w滚动到480w
const moneyLabel = n.getChildByPath("settlementNode/Node/money").getComponent(Label);
2025-03-07 09:08:47 +08:00
let money = { value: 420 };
2025-03-06 22:47:02 +08:00
tween(money)
2025-03-07 09:08:47 +08:00
.to(1, { value: 446 }, {
2025-03-06 22:47:02 +08:00
easing: 'linear',
onUpdate: () => {
moneyLabel.string = Math.floor(money.value) + "w";
}
})
.start();
let isWin = this.localPlayerNode.getComponent(WoodenManPlayer).isPassed();
2025-03-14 10:25:36 +08:00
n.getChildByPath("settlementNode/btnOK/label").getComponent(Label).string = isWin ? "NEXT" : "RETRY";
2025-03-06 22:47:02 +08:00
n.getChildByPath("settlementNode/btnOK").on(Node.EventType.TOUCH_START, () => {
if (isWin) {
2025-03-07 13:33:59 +08:00
SceneDef.Next_Scene = "level2/scene/level2Scene";
// 切换到加载场景
director.loadScene('LoadingScene');
// director.loadScene("level2/scene/level2Scene");
2025-03-06 22:47:02 +08:00
}
else {
2025-03-14 10:25:36 +08:00
director.loadScene(director.getScene().name);
2025-03-06 22:47:02 +08:00
}
});
}
});
}, 3);
2025-03-06 10:50:18 +08:00
console.log(`游戏结束!
${reason}
${qualifiedPlayers}
${deadPlayers}
${this.gameTimer}`);
// 触发游戏结束事件
2025-02-21 10:45:46 +08:00
this.node.emit('gameOver');
2025-03-06 10:50:18 +08:00
// 隐藏停止按钮
if (this.stopButton) {
this.stopButton.active = false;
}
}
// 添加新方法:击杀所有未晋级的存活玩家
private killAllNonQualifiedPlayers() {
this.playerNodes.forEach((playerNode) => {
const playerComp = playerNode.getComponent(WoodenManPlayer);
if (playerComp && playerComp.isAlive() && !playerComp.isPassed()) {
this.killPlayer(playerComp, playerNode);
}
});
2025-02-21 10:45:46 +08:00
}
// 获取游戏状态
2025-03-01 02:24:46 +08:00
// 木头人转身动画
2025-03-06 10:50:18 +08:00
private playDollTurnAnimation(callback?: () => void) {
const currentRotation = this.dollNode.eulerAngles.clone();
const targetRotation = new Vec3(
currentRotation.x,
currentRotation.y + 180,
currentRotation.z
);
this.isDollTurning = true;
this.turnStartTime = Date.now();
tween(this.dollNode)
.to(this.turnAnimationDuration, { eulerAngles: targetRotation }, {
easing: 'quadOut',
onStart: () => {
this.node.parent?.emit('dollTurnStart');
},
onComplete: () => {
this.isDollTurning = false;
this.node.parent?.emit('dollTurnComplete');
if (callback) callback();
}
})
.start();
2025-03-01 02:24:46 +08:00
}
// 玩家死亡效果
private killPlayer(playerComp: WoodenManPlayer, playerNode: Node) {
if (!playerComp.isAlive()) return; // 防止重复处理
2025-03-06 10:50:18 +08:00
// 先设置玩家状态为死亡
2025-03-01 02:24:46 +08:00
playerComp.setAlive(false);
2025-03-06 10:50:18 +08:00
playerComp.isMoving = false;
2025-03-01 02:24:46 +08:00
2025-03-06 10:50:18 +08:00
// 确保停止所有正在进行的动画和移动
tween(playerNode).stop();
2025-03-06 22:47:02 +08:00
2025-03-06 10:50:18 +08:00
// 延迟一小段时间再播放死亡动画,避免动作冲突
this.scheduleOnce(() => {
// 播放死亡动画
playerComp.playDieAnimation();
2025-03-06 22:47:02 +08:00
2025-03-06 10:50:18 +08:00
// 更新存活人数显示
this.updateAliveCount();
// 如果是本地玩家死亡,隐藏停止按钮
if (playerComp.getIsLocalPlayer() && this.stopButton) {
this.stopButton.active = false;
}
}, 0.1);
2025-02-21 10:45:46 +08:00
}
2025-03-01 02:24:46 +08:00
2025-03-06 10:50:18 +08:00
// 更新游戏时间
private updateGameTimer() {
2025-03-23 02:31:54 +08:00
if (this.isGameOver || !this.isCountdownStarted) return;
2025-03-06 10:50:18 +08:00
this.gameTimer--;
2025-03-23 02:31:54 +08:00
this.updateTimerDisplay();
2025-03-06 10:50:18 +08:00
if (this.gameTimer <= 0) {
this.endGame('时间到!游戏结束');
}
2025-03-01 02:24:46 +08:00
}
2025-03-06 10:50:18 +08:00
// 更新晋级名额显示
updateWinCount() {
if (this.winCountLabel) {
const displayCount = Math.min(this.qualifiedCount, this.REQUIRED_QUALIFIED);
this.winCountLabel.string = `${displayCount}/${this.REQUIRED_QUALIFIED}`;
}
}
2025-03-01 02:24:46 +08:00
2025-03-06 10:50:18 +08:00
// 修改警示灯动画方法
private playWarningLights(callback?: () => void) {
// 生成随机加速倍率 (0.5~1倍)
const actualInterval = this.WARNING_LIGHT_BASE_INTERVAL;
// 先重置所有灯为初始状态
this.warningLightsNode.children.forEach(light => {
light.getComponent(Sprite).color = new Color(128, 128, 128, 255);
});
// 依次点亮每个灯
let currentLight = 0;
const lightInterval = () => {
if (currentLight >= this.warningLightsNode.children.length) {
if (callback) callback();
return;
2025-03-01 02:24:46 +08:00
}
2025-03-06 10:50:18 +08:00
// 点亮当前灯并播放音效
const light = this.warningLightsNode.children[currentLight];
light.getComponent(Sprite).color = new Color(255, 0, 0, 255);
2025-03-06 22:47:02 +08:00
2025-03-06 10:50:18 +08:00
currentLight++;
this.scheduleOnce(() => {
lightInterval();
}, actualInterval);
2025-03-01 02:24:46 +08:00
}
2025-03-06 10:50:18 +08:00
// 开始点亮第一个灯
lightInterval();
2025-02-21 10:45:46 +08:00
}
2025-03-23 02:31:54 +08:00
// 开始倒计时
private startCountdown() {
this.isCountdownStarted = true;
this.unschedule(this.updateGameTimer); // 确保不会重复计时
this.schedule(this.updateGameTimer, 1);
this.updateTimerDisplay();
}
// 更新计时器显示
private updateTimerDisplay() {
if (!this.timerLabel) return;
const minutes = Math.floor(this.gameTimer / 60);
const seconds = this.gameTimer % 60;
// 格式化为 "xx:xx"
this.timerLabel.string = `${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + seconds : seconds}`;
}
2025-02-21 10:45:46 +08:00
}