Files
esengine/docs/guide/time-and-timers.md
yhh 240b165970 chore: 更新仓库 URL (ecs-framework → esengine)
仓库已从 esengine/ecs-framework 重命名为 esengine/esengine
更新所有引用旧 URL 的文件
2025-12-08 21:23:37 +08:00

553 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 时间和定时器系统
ECS 框架提供了完整的时间管理和定时器系统,包括时间缩放、帧时间计算和灵活的定时器调度功能。
## Time 类
Time 类是框架的时间管理核心,提供了游戏时间相关的所有功能。
### 基本时间属性
```typescript
import { Time } from '@esengine/esengine';
class GameSystem extends EntitySystem {
protected process(entities: readonly Entity[]): void {
// 获取帧时间(秒)
const deltaTime = Time.deltaTime;
// 获取未缩放的帧时间
const unscaledDelta = Time.unscaledDeltaTime;
// 获取游戏总时间
const totalTime = Time.totalTime;
// 获取当前帧数
const frameCount = Time.frameCount;
console.log(`${frameCount} 帧,帧时间: ${deltaTime}s总时间: ${totalTime}s`);
}
}
```
### 时间缩放
Time 类支持时间缩放功能,可以实现慢动作、快进等效果:
```typescript
class TimeControlSystem extends EntitySystem {
public enableSlowMotion(): void {
// 设置为慢动作50%速度)
Time.timeScale = 0.5;
console.log('慢动作模式启用');
}
public enableFastForward(): void {
// 设置为快进200%速度)
Time.timeScale = 2.0;
console.log('快进模式启用');
}
public pauseGame(): void {
// 暂停游戏(时间静止)
Time.timeScale = 0;
console.log('游戏暂停');
}
public resumeNormalSpeed(): void {
// 恢复正常速度
Time.timeScale = 1.0;
console.log('恢复正常速度');
}
protected process(entities: readonly Entity[]): void {
// deltaTime 会受到 timeScale 影响
const scaledDelta = Time.deltaTime; // 受时间缩放影响
const realDelta = Time.unscaledDeltaTime; // 不受时间缩放影响
for (const entity of entities) {
const movement = entity.getComponent(Movement);
if (movement) {
// 使用缩放时间进行游戏逻辑更新
movement.update(scaledDelta);
}
const ui = entity.getComponent(UIComponent);
if (ui) {
// UI 动画使用真实时间,不受游戏时间缩放影响
ui.update(realDelta);
}
}
}
}
```
### 时间检查工具
```typescript
class CooldownSystem extends EntitySystem {
private lastAttackTime = 0;
private lastSpawnTime = 0;
constructor() {
super(Matcher.all(Weapon));
}
protected process(entities: readonly Entity[]): void {
// 检查攻击冷却
if (Time.checkEvery(1.5, this.lastAttackTime)) {
this.performAttack();
this.lastAttackTime = Time.totalTime;
}
// 检查生成间隔
if (Time.checkEvery(3.0, this.lastSpawnTime)) {
this.spawnEnemy();
this.lastSpawnTime = Time.totalTime;
}
}
private performAttack(): void {
console.log('执行攻击!');
}
private spawnEnemy(): void {
console.log('生成敌人!');
}
}
```
## Core.schedule 定时器系统
Core 提供了强大的定时器调度功能,可以创建一次性或重复执行的定时器。
### 基本定时器使用
```typescript
import { Core } from '@esengine/esengine';
class GameScene extends Scene {
protected initialize(): void {
// 创建一次性定时器
this.createOneTimeTimers();
// 创建重复定时器
this.createRepeatingTimers();
// 创建带上下文的定时器
this.createContextTimers();
}
private createOneTimeTimers(): void {
// 2秒后执行一次
Core.schedule(2.0, false, null, (timer) => {
console.log('2秒延迟执行');
});
// 5秒后显示提示
Core.schedule(5.0, false, this, (timer) => {
const scene = timer.getContext<GameScene>();
scene.showTip('游戏提示5秒已过');
});
}
private createRepeatingTimers(): void {
// 每秒重复执行
const heartbeatTimer = Core.schedule(1.0, true, null, (timer) => {
console.log(`游戏心跳 - 总时间: ${Time.totalTime.toFixed(1)}s`);
});
// 可以保存定时器引用用于后续控制
this.saveTimerReference(heartbeatTimer);
}
private createContextTimers(): void {
const gameData = { score: 0, level: 1 };
// 每2秒增加分数
Core.schedule(2.0, true, gameData, (timer) => {
const data = timer.getContext<typeof gameData>();
data.score += 10;
console.log(`分数增加!当前分数: ${data.score}`);
});
}
private saveTimerReference(timer: any): void {
// 可以稍后停止定时器
setTimeout(() => {
timer.stop();
console.log('定时器已停止');
}, 10000); // 10秒后停止
}
private showTip(message: string): void {
console.log('提示:', message);
}
}
```
### 定时器控制
```typescript
class TimerControlExample {
private attackTimer: any;
private spawnerTimer: any;
public startCombat(): void {
// 启动攻击定时器
this.attackTimer = Core.schedule(0.5, true, this, (timer) => {
const self = timer.getContext<TimerControlExample>();
self.performAttack();
});
// 启动敌人生成定时器
this.spawnerTimer = Core.schedule(3.0, true, null, (timer) => {
this.spawnEnemy();
});
}
public stopCombat(): void {
// 停止所有战斗相关定时器
if (this.attackTimer) {
this.attackTimer.stop();
console.log('攻击定时器已停止');
}
if (this.spawnerTimer) {
this.spawnerTimer.stop();
console.log('生成定时器已停止');
}
}
public resetAttackTimer(): void {
// 重置攻击定时器
if (this.attackTimer) {
this.attackTimer.reset();
console.log('攻击定时器已重置');
}
}
private performAttack(): void {
console.log('执行攻击');
}
private spawnEnemy(): void {
console.log('生成敌人');
}
}
```
### 复杂定时器场景
```typescript
class AdvancedTimerUsage {
private powerUpDuration = 0;
private powerUpActive = false;
public activatePowerUp(): void {
if (this.powerUpActive) {
console.log('能力提升已激活');
return;
}
this.powerUpActive = true;
this.powerUpDuration = 10; // 10秒持续时间
console.log('能力提升激活!');
// 每秒更新剩余时间
const countdownTimer = Core.schedule(1.0, true, this, (timer) => {
const self = timer.getContext<AdvancedTimerUsage>();
self.powerUpDuration--;
console.log(`能力提升剩余时间: ${self.powerUpDuration}`);
if (self.powerUpDuration <= 0) {
self.deactivatePowerUp();
timer.stop(); // 停止倒计时
}
});
// 能力提升结束定时器(备用)
Core.schedule(10.0, false, this, (timer) => {
const self = timer.getContext<AdvancedTimerUsage>();
if (self.powerUpActive) {
self.deactivatePowerUp();
}
});
}
private deactivatePowerUp(): void {
this.powerUpActive = false;
this.powerUpDuration = 0;
console.log('能力提升结束');
}
// 创建波次攻击定时器
public startWaveAttack(): void {
let waveCount = 0;
const maxWaves = 5;
const waveTimer = Core.schedule(2.0, true, { waveCount, maxWaves }, (timer) => {
const context = timer.getContext<{ waveCount: number, maxWaves: number }>();
context.waveCount++;
console.log(`${context.waveCount} 波攻击!`);
if (context.waveCount >= context.maxWaves) {
console.log('所有波次攻击完成');
timer.stop();
}
});
}
// 创建条件定时器
public startConditionalTimer(): void {
Core.schedule(0.1, true, this, (timer) => {
const self = timer.getContext<AdvancedTimerUsage>();
// 检查某个条件
if (self.shouldStopTimer()) {
console.log('条件满足,停止定时器');
timer.stop();
return;
}
// 继续执行定时器逻辑
self.performTimerAction();
});
}
private shouldStopTimer(): boolean {
// 检查停止条件
return Time.totalTime > 30; // 30秒后停止
}
private performTimerAction(): void {
console.log('执行定时器动作');
}
}
```
## 实际应用示例
### 技能冷却系统
```typescript
class SkillCooldownSystem extends EntitySystem {
constructor() {
super(Matcher.all(SkillComponent));
}
protected process(entities: readonly Entity[]): void {
for (const entity of entities) {
const skill = entity.getComponent(SkillComponent);
// 更新技能冷却
if (skill.isOnCooldown) {
skill.cooldownRemaining -= Time.deltaTime;
if (skill.cooldownRemaining <= 0) {
skill.cooldownRemaining = 0;
skill.isOnCooldown = false;
console.log(`技能 ${skill.name} 冷却完成`);
}
}
}
}
public useSkill(entity: Entity, skillName: string): boolean {
const skill = entity.getComponent(SkillComponent);
if (skill.isOnCooldown) {
console.log(`技能 ${skillName} 还在冷却中,剩余 ${skill.cooldownRemaining.toFixed(1)}`);
return false;
}
// 执行技能
this.executeSkill(entity, skill);
// 开始冷却
skill.isOnCooldown = true;
skill.cooldownRemaining = skill.cooldownDuration;
return true;
}
private executeSkill(entity: Entity, skill: SkillComponent): void {
console.log(`执行技能: ${skill.name}`);
// 技能效果逻辑
}
}
```
### 游戏状态定时器
```typescript
class GameStateManager {
private gamePhase = 'preparation';
private phaseTimer: any;
public startGame(): void {
this.startPreparationPhase();
}
private startPreparationPhase(): void {
this.gamePhase = 'preparation';
console.log('准备阶段开始 - 10秒准备时间');
this.phaseTimer = Core.schedule(10.0, false, this, (timer) => {
const self = timer.getContext<GameStateManager>();
self.startCombatPhase();
});
}
private startCombatPhase(): void {
this.gamePhase = 'combat';
console.log('战斗阶段开始 - 60秒战斗时间');
this.phaseTimer = Core.schedule(60.0, false, this, (timer) => {
const self = timer.getContext<GameStateManager>();
self.startResultPhase();
});
// 每10秒刷新一波敌人
Core.schedule(10.0, true, null, (timer) => {
if (this.gamePhase === 'combat') {
this.spawnEnemyWave();
} else {
timer.stop(); // 战斗阶段结束时停止刷新
}
});
}
private startResultPhase(): void {
this.gamePhase = 'result';
console.log('结算阶段开始 - 5秒结算时间');
this.phaseTimer = Core.schedule(5.0, false, this, (timer) => {
const self = timer.getContext<GameStateManager>();
self.endGame();
});
}
private endGame(): void {
console.log('游戏结束');
this.gamePhase = 'ended';
}
private spawnEnemyWave(): void {
console.log('刷新敌人波次');
}
public getCurrentPhase(): string {
return this.gamePhase;
}
}
```
## 最佳实践
### 1. 合理使用时间类型
```typescript
class MovementSystem extends EntitySystem {
protected process(entities: readonly Entity[]): void {
for (const entity of entities) {
const movement = entity.getComponent(Movement);
// ✅ 游戏逻辑使用缩放时间
movement.position.x += movement.velocity.x * Time.deltaTime;
// ✅ UI动画使用真实时间不受游戏暂停影响
const ui = entity.getComponent(UIAnimation);
if (ui) {
ui.update(Time.unscaledDeltaTime);
}
}
}
}
```
### 2. 定时器管理
```typescript
class TimerManager {
private timers: any[] = [];
public createManagedTimer(duration: number, repeats: boolean, callback: () => void): any {
const timer = Core.schedule(duration, repeats, null, callback);
this.timers.push(timer);
return timer;
}
public stopAllTimers(): void {
for (const timer of this.timers) {
timer.stop();
}
this.timers = [];
}
public cleanupCompletedTimers(): void {
this.timers = this.timers.filter(timer => !timer.isDone);
}
}
```
### 3. 避免过多的定时器
```typescript
// ❌ 避免:为每个实体创建定时器
class BadExample extends EntitySystem {
protected onAdded(entity: Entity): void {
Core.schedule(1.0, true, entity, (timer) => {
// 每个实体一个定时器,性能差
});
}
}
// ✅ 推荐:在系统中统一管理时间
class GoodExample extends EntitySystem {
private lastUpdateTime = 0;
protected process(entities: readonly Entity[]): void {
// 每秒执行一次逻辑
if (Time.checkEvery(1.0, this.lastUpdateTime)) {
this.processAllEntities(entities);
this.lastUpdateTime = Time.totalTime;
}
}
private processAllEntities(entities: readonly Entity[]): void {
// 批量处理所有实体
}
}
```
### 4. 定时器上下文使用
```typescript
interface TimerContext {
entityId: number;
duration: number;
onComplete: () => void;
}
class ContextualTimerExample {
public createEntityTimer(entityId: number, duration: number, onComplete: () => void): void {
const context: TimerContext = {
entityId,
duration,
onComplete
};
Core.schedule(duration, false, context, (timer) => {
const ctx = timer.getContext<TimerContext>();
console.log(`实体 ${ctx.entityId} 的定时器完成`);
ctx.onComplete();
});
}
}
```
时间和定时器系统是游戏开发中的重要工具,正确使用这些功能能让你的游戏逻辑更加精确和可控。