| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- 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;
- }
- }
|