import { Tween, tween, Vec3, _decorator } from 'cc' import { EntityManager } from '../../Base/EntityManager' import { EntityTypeEnum, IBullet, IVec2 } from '../../Common' import { EntityStateEnum, EventEnum } from '../../Enum' import DataManager from '../../Global/DataManager' import EventManager from '../../Global/EventManager' import ObjectPoolManager from '../../Global/ObjectPoolManager' import { rad2Angle } from '../../Utils' import { ExplosionManager } from '../Explosion/ExplosionManager' import { BulletStateMachine } from './BulletStateMachine' const { ccclass } = _decorator @ccclass('BulletManager') export class BulletManager extends EntityManager implements IBullet { //静态数据 id: number owner: number type: EntityTypeEnum //动态数据 position: IVec2 direction: IVec2 private angle: number private tw: Tween private targetPos: Vec3 = new Vec3 init({ id, owner, type }: IBullet) { this.id = id this.owner = owner this.type = type this.fsm = this.addComponent(BulletStateMachine) this.fsm.init(type) this.state = EntityStateEnum.Idle this.node.active = false EventManager.Instance.on(EventEnum.ExplosionBorn, this.handleExplosion, this) } handleExplosion(id: number, { x, y }: IVec2) { if (this.id !== id) { return } const explosion = ObjectPoolManager.Instance.get(EntityTypeEnum.Explosion) const explosionManager = explosion.getComponent(ExplosionManager) || explosion.addComponent(ExplosionManager) explosionManager.init(EntityTypeEnum.Explosion, { x, y, }) EventManager.Instance.off(EventEnum.ExplosionBorn, this.handleExplosion, this) ObjectPoolManager.Instance.ret(this.node) DataManager.Instance.bulletMap.delete(this.id) this.angle = undefined } render(data: IBullet) { this.renderPosition(data) this.renderDirection(data) } renderPosition(data: IBullet) { const newPos = new Vec3(data.position.x, data.position.y) if (!this.node.active) { this.node.active = true this.node.setPosition(newPos) this.targetPos.set(newPos) } else if (!this.targetPos.equals(newPos)) { this.tw?.stop() this.node.setPosition(this.targetPos) this.targetPos.set(newPos) this.tw = tween(this.node).to(0.1, { position: this.targetPos }).start() } // this.node.setPosition(data.position.x, data.position.y) } renderDirection(data: IBullet) { if (this.angle === undefined) { const { x, y } = data.direction const side = Math.sqrt(x * x + y * y) this.angle = x > 0 ? rad2Angle(Math.asin(y / side)) : rad2Angle(Math.asin(- y / side)) + 180 } this.node.setRotationFromEuler(0, 0, this.angle) // let angle: number, sign: number // if (x !== 0) { // angle = x > 0 ? rad2Angle(Math.atan(y / x)) : rad2Angle(Math.atan(-y / x)) + 180 // sign = x > 0 ? 1 : -1 // } else { // angle = rad2Angle(Math.PI / 2) // sign = y > 0 ? 1 : -1 // } // this.node.setRotationFromEuler(0, 0, sign * angle) } }