import { _decorator, Component, Vec3 } from 'cc'; import { BulletLifecycleConfig, HitResult } from '../BulletTypes'; const { ccclass } = _decorator; /** * 生命周期控制(可移植版):范围、时间、穿透/弹射计数、返回发射源等 */ @ccclass('BCBulletLifecycle') export class BulletLifecycle extends Component { private cfg: BulletLifecycleConfig | null = null; private origin: Vec3 = new Vec3(); private lifetime = 0; private distance = 0; private piercingLeft = 0; private ricochetLeft = 0; private shouldReturn = false; private returnTimer = 0; public init(cfg: BulletLifecycleConfig, startPos: Vec3, pierceInit?: number, ricochetInit?: number) { this.cfg = { ...cfg }; this.origin.set(startPos); this.lifetime = 0; this.distance = 0; this.piercingLeft = Math.max(0, pierceInit ?? (cfg?.penetration ?? 0)); this.ricochetLeft = Math.max(0, ricochetInit ?? (cfg?.ricochetCount ?? 0)); this.returnTimer = 0; this.shouldReturn = !!cfg?.returnToOrigin; } update(dt: number) { if (!this.cfg) return; this.lifetime += dt; const pos = this.node.worldPosition; const dx = pos.x - this.origin.x; const dy = pos.y - this.origin.y; this.distance = Math.sqrt(dx * dx + dy * dy); // 处理返回延迟 if (this.shouldReturn) { const delay = Math.max(0, this.cfg.returnDelay ?? 0); if (this.lifetime >= delay) { // 上层可以根据 shouldReturnNow 触发回程逻辑(例如改变弹道方向) } } } /** 命中时通知,用于更新计数 */ public notifyHit(hit: HitResult) { if (hit.pierced) { if (this.piercingLeft > 0) this.piercingLeft -= 1; } else { // 非穿透命中默认视为消耗一次 penetration(例如普通 hit_destroy) if (this.piercingLeft > 0) this.piercingLeft -= 1; } if (hit.ricochet) { if (this.ricochetLeft > 0) this.ricochetLeft -= 1; } } /** 是否应该立即销毁 */ public shouldDestroyNow(): boolean { if (!this.cfg) return true; // 时间限制 const maxLifetime = this.cfg.maxLifetime ?? Infinity; if (this.lifetime > maxLifetime) return true; // 射程限制 const maxRange = this.cfg.maxRange ?? Infinity; if (this.cfg.type === 'range_limit' && this.distance > maxRange) return true; // 穿透/弹射计数耗尽 if (this.cfg.type === 'hit_destroy' && this.piercingLeft <= 0) return true; if (this.cfg.type === 'ricochet_counter' && this.ricochetLeft <= 0) return true; // ground_impact:由外层根据地面碰撞事件触发销毁,此处不主动判定 return false; } /** 是否进入回程阶段(供上层改变弹道方向) */ public shouldReturnNow(): boolean { if (!this.cfg || !this.shouldReturn) return false; const delay = Math.max(0, this.cfg.returnDelay ?? 0); return this.lifetime >= delay; } }