import { _decorator, Component, Node, Label, Sprite, tween, Vec3 } from 'cc'; const { ccclass, property } = _decorator; /** * 时间底座动画控制器,负责处理时间相关的动画效果 */ @ccclass('TimeBaseController') export class TimeBaseController extends Component { @property({ type: Sprite, tooltip: '时间灯1' }) timeLight1: Sprite = null; @property({ type: Sprite, tooltip: '时间灯2' }) timeLight2: Sprite = null; @property({ type: Label, tooltip: '时间标签' }) timeLabel: Label = null; // 倒计时总时间(秒) private totalTime: number = 150; // 2分30秒 // 当前剩余时间(秒) private remainingTime: number = 150; // 上一分钟时间,用于检测分钟变化 private lastMinute: number = -1; // 灯光闪烁间隔(秒) private urgentBlinkInterval: number = 0.5; // 当前是否在紧急状态(少于1分钟) private isUrgent: boolean = false; // 灯光交替显示计时器 private blinkTimer: number = 0; // 当前激活的灯 private activeLightIndex: number = 0; start() { // 初始化灯光状态 this.resetLights(); // 初始化时间显示 this.updateTimeDisplay(); } update(dt: number) { // 更新剩余时间 this.remainingTime = Math.max(0, this.remainingTime - dt); // 更新时间显示 this.updateTimeDisplay(); // 计算分钟和秒 const minutes = Math.floor(this.remainingTime / 60); const seconds = Math.floor(this.remainingTime % 60); // 检查是否进入紧急状态(剩余时间少于1分钟) const isCurrentlyUrgent = minutes < 1; // 状态变化时重置 if (this.isUrgent !== isCurrentlyUrgent) { this.isUrgent = isCurrentlyUrgent; this.blinkTimer = 0; this.resetLights(); } // 仅在紧急状态下处理灯光闪烁 if (this.isUrgent) { this.handleLightBlink(dt); } // 检查分钟变化,触发标签动画 if (minutes !== this.lastMinute) { this.lastMinute = minutes; this.playLabelPulseAnimation(); } } /** * 更新时间显示 */ private updateTimeDisplay() { if (!this.timeLabel) return; // 计算分钟和秒 const minutes = Math.floor(this.remainingTime / 60); const seconds = Math.floor(this.remainingTime % 60); // 格式化时间字符串 (mm:ss) const timeString = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; // 更新标签文本 this.timeLabel.string = timeString; } /** * 重置倒计时时间 * @param time 设置的时间(秒) */ public resetTime(time: number = 150) { this.totalTime = time; this.remainingTime = time; this.lastMinute = Math.floor(time / 60); this.updateTimeDisplay(); // 重置状态 this.isUrgent = Math.floor(time / 60) < 1; this.resetLights(); } /** * 处理灯光闪烁逻辑 */ private handleLightBlink(dt: number) { // 更新计时器 this.blinkTimer += dt; // 到达间隔时间则切换灯光 if (this.blinkTimer >= this.urgentBlinkInterval) { this.blinkTimer = 0; this.switchLights(); } } /** * 切换灯光显示 */ private switchLights() { // 紧急状态时交替闪烁两个灯 this.activeLightIndex = 1 - this.activeLightIndex; if (this.timeLight1 && this.timeLight2) { this.timeLight1.node.active = this.activeLightIndex === 0; this.timeLight2.node.active = this.activeLightIndex === 1; } } /** * 重置灯光状态 */ private resetLights() { if (this.timeLight1 && this.timeLight2) { if (this.isUrgent) { // 紧急状态下初始只显示一个灯,准备交替闪烁 this.timeLight1.node.active = true; this.timeLight2.node.active = false; this.activeLightIndex = 0; } else { // 非紧急状态下只显示第一个灯,不闪烁 this.timeLight1.node.active = true; this.timeLight2.node.active = false; } } } /** * 播放标签脉冲动画(在整数分钟时触发) */ private playLabelPulseAnimation() { if (!this.timeLabel) return; // 保存原始缩放 const originalScale = this.timeLabel.node.scale.clone(); const targetScale = new Vec3(originalScale.x * 1.3, originalScale.y * 1.3, originalScale.z); // 创建放大然后恢复的动画序列 tween(this.timeLabel.node) .to(0.1, { scale: targetScale }) .to(0.1, { scale: originalScale }) // 添加轻微抖动 .to(0.05, { position: new Vec3(5, 0, 0) }) .to(0.05, { position: new Vec3(-5, 0, 0) }) .to(0.05, { position: new Vec3(3, 0, 0) }) .to(0.05, { position: new Vec3(-3, 0, 0) }) .to(0.05, { position: new Vec3(0, 0, 0) }) .start(); } }