| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 | import { _decorator, Animation, AnimationClip, Component, Node, Rect, SpriteFrame, UITransform, Vec3 } from 'cc';import { LifeBar } from './LifeBar';import { BulletPool } from './BulletPool';const { ccclass, property } = _decorator;export enum BulletState {    Normal,    Explode,}@ccclass('Bullet')export class Bullet extends Component {    //对象池    private _pool: BulletPool = null!;    private _isEnemyBullet: boolean = false;    private _animation: Animation = null;    private _animations: Map<BulletState, string> = new Map();    private _explodeframes: SpriteFrame[] = [];    private _bulletFrames: SpriteFrame[] = [];    //是否爆炸 true -> 爆炸    isExplode: boolean = false;    //子弹速度    bulletSpeed: number = 100;    //子弹方向    direction: number = 1;    //攻击力    atk: number = null;    //被攻击的节点    targetNode: Node = null;    //是否碰撞    private _hasCollided: boolean = false;    private _initPos: Vec3 = null;    protected onLoad(): void {        this._animation = this.node.addComponent(Animation);    }    start() {        this._initPos = this.node.position.clone();        this._collectAni();        this._playAnimation(BulletState.Normal);    }    public reset(config: {        pool: BulletPool,        isEnemy: boolean,        direction: number,        bulletFrames: SpriteFrame[],        explodeFrames: SpriteFrame[],        targetNode: Node,        atk: number,    }) {        //重置状态        this._pool = config.pool;        this._isEnemyBullet = config.isEnemy;        this.direction = config.direction;        this._bulletFrames = config.bulletFrames;        this._explodeframes = config.explodeFrames;        this.targetNode = config.targetNode;        this.atk = config.atk;        this._hasCollided = false;        this.isExplode = false;        this.bulletSpeed = this._isEnemyBullet ? 100 : 90;        this._initPos = this.node.position.clone();        this._playAnimation(BulletState.Normal);        //重置位置和动画        this.node.active = true;    }    private _recycle() {        if (this._pool) {            //停止所有动画和事件            this._animation.stop();            this._animation.off(Animation.EventType.FINISHED);            this.unscheduleAllCallbacks();            this.node.active = false;            //回收到对象池            this._pool.recycle(this.node, this._isEnemyBullet);        } else {            this.node.destroy();        }    }    update(deltaTime: number) {        this.move(deltaTime);        this.onBulletCollision(this.targetNode);        this._checkDistance();    }    // 处理子弹碰撞    private onBulletCollision(targetNode: Node) {        if (this._hasCollided || !targetNode.isValid) return;        const boxBullet = this.node.getComponent(UITransform).getBoundingBoxToWorld();        let boxTarget: Rect = null;        if(this.targetNode.getChildByName("Rect")){            boxTarget = this.targetNode.getChildByName("Rect").getComponent(UITransform).getBoundingBoxToWorld();        } else {            boxTarget = this.targetNode.getComponent(UITransform).getBoundingBoxToWorld();        }                if (boxTarget.intersects(boxBullet)) {            const targetLifeBar = targetNode.getComponent(LifeBar);            const curHp: number = targetLifeBar._curHp - this.atk;            targetLifeBar.updateProgressBar(curHp);            if (curHp <= 0) {                this._recycle();            }            this._hasCollided = true;            this._playAnimation(BulletState.Explode);        }    }    move(dt: number) {        let x = this.node.getWorldPosition().x;        let y = this.node.getWorldPosition().y;        let z = this.node.getWorldPosition().z;        x = x + this.bulletSpeed * this.direction * dt;        this.node.setWorldPosition(x, y, z)    }    private _checkDistance() {        const currentPos: Vec3 = this.node.position;        const distance: number = Vec3.distance(currentPos, this._initPos);        if (distance >= 250) {            this._recycle();        }    }    private _collectAni() {        this._createClip(BulletState.Explode, this._explodeframes, 10);        this._createClip(BulletState.Normal, this._bulletFrames, 10);    }    private _createClip(state: BulletState, frames: SpriteFrame[], fps: number) {        const clip: AnimationClip = AnimationClip.createWithSpriteFrames(frames, fps);        clip.name = BulletState[state];        clip.wrapMode = state === BulletState.Explode ?            AnimationClip.WrapMode.Normal :            AnimationClip.WrapMode.Loop;        this._animation.addClip(clip, clip.name);        this._animations.set(state, clip.name);    }    private _playAnimation(state: BulletState) {        if (!this._animation) return;        const clipName = this._animations.get(state);        if (!clipName) return;        this._animation.stop();        this._animation.play(clipName);        if (state === BulletState.Explode) {            this.bulletSpeed = 0;            this._animation.once(Animation.EventType.FINISHED, () => {                this._recycle();            })        }    }}
 |