/** @format */ import {ComNodeConfig} from '../components/ComNodeConfig' import {ComCocosNode} from '../components/ComCocosNode' import {ECSSystem} from '../lib/ECSSystem' import {GenFilterKey} from '../lib/ECSComponent' import {ComTransform} from '../components/ComTransform' import {ComRole} from '../components/ComRole' import {FightWorld} from '../worlds/FightWorld' import {Data} from '../../GameControl' import {cObject} from '../../collision/Object' import {cCollider} from '../../collision/Collider' import {EventEnter, EventHPChange, EventType} from '../core/NodeEvent' import {ComFindEnemy} from '../components/ComFindEnemy' import {ComBullet} from '../components/ComBullet' import {ComMovable} from '../components/ComMovable' import {ShapeType} from '../../collision/Shape' import {ComAttackable} from '../components/ComAttackable' import {ComDizzy} from '../components/ComDizzy' import {ComHasSkill} from '../components/ComHasSkill' import {ComSkillAbel} from '../components/ComSkillAbel' import {ComSkill} from '../components/ComSkill' import {ComLifeTime} from '../components/ComLifeTime' import {ComBehaviorTree} from '../components/ComBehaviorTree' import {BT} from '../../behaviorTree/BehaviorTree' import {ComRoleSpine} from '../components/ComRoleSpine' import {RoleEventProcess} from '../core/RoleEventProcess' import {BulletEventProcess} from '../core/BulletEventProcess' import {SkillEventProcess} from '../core/SkillEventProcess' import {EventProcess} from '../core/EventProcess' import {RoleSpineProcess} from '../core/RoleSpineProcess' import {ComFrameAni} from '../components/ComFrameAni' import {FrameAniProcess} from '../core/FrameAniProcess' import {ComEnter} from '../components/ComEnter' import {BULLET_EFFECT_TYPE, FRAME_ANI_NAME, GAME_SCALE_TYPE} from '../../enums/Enum' import {ccUtils} from '../../utils/ccUtils' export interface ITouchProcessor { onTouchStart(worldPos: cc.Vec2, world: FightWorld): void onTouchMove?(worldPos: cc.Vec2, world: FightWorld): void onTouchEnd?(worldPos: cc.Vec2, world: FightWorld): void onTouchCancel?(worldPos: cc.Vec2, world: FightWorld): void } const FILTER_COCOS_NODE = GenFilterKey([ComNodeConfig], [ComCocosNode]) const FILTER_NODE_EVENT = GenFilterKey([ComCocosNode, ComTransform]) export class SysCocosView extends ECSSystem implements ITouchProcessor { bulletCD: number = 0 onTouchStart(worldPos: cc.Vec2, world: FightWorld): void { if (this.bulletCD > 0) return let curPos = ccUtils.convertWorldPosToNode(world.fightCore.node, worldPos) if ( curPos.x < Data.game.fightAreaMinX || curPos.x < Data.game.fightAreaMinX || curPos.y > Data.game.fightAreaMaxY || curPos.y < Data.game.fightAreaMinY ) return let entity = world.createBaseBulletEntity(curPos) if (entity) { world.fightCore.showClickAni(cc.v3(curPos)) this.bulletCD = 0.5 } } onTouchMove(worldPos: cc.Vec2, world: FightWorld): void {} onTouchCancel(worldPos: cc.Vec2, world: FightWorld): void {} onTouchEnd(worldPos: cc.Vec2, world: FightWorld): void {} onAdd(world: FightWorld) {} onRemove(world: FightWorld) {} onEntityEnter(world: FightWorld, entity: number) {} onEntityLeave(world: FightWorld, entity: number) {} onUpdate(world: FightWorld, dt: number) { let self = this this.bulletCD -= dt if (this.bulletCD <= 0) this.bulletCD = 0 world.getFilter(FILTER_NODE_EVENT).walk((entity: number) => { let comCocosNode = world.getComponent(entity, ComCocosNode) if (!comCocosNode.loaded) { return } let eventProcess = comCocosNode.node.getComponent(EventProcess) if (!eventProcess) return let comTrans = world.getComponent(entity, ComTransform) eventProcess.syncPos(comTrans.x, comTrans.y) while (comCocosNode.events.length) { let event = comCocosNode.events.shift() if (event.type != EventType.GraphicsDraw) { //console.log('entity----->', entity, 'EventType----->', EventType[event.type]) } eventProcess.processEvent(event) } return false }) //先运行存在节点,再加载节点,加载的节点下一帧运行 world.getFilter(FILTER_COCOS_NODE).walk((entity: number) => { let comNodeConfig = world.getComponent(entity, ComNodeConfig) let comCocosNode = world.addComponent(entity, ComCocosNode) comCocosNode.loaded = false let comRole = world.getComponent(entity, ComRole) if (comRole) { comCocosNode.events.push( new EventHPChange( comRole.HP, comRole.lastHP, comRole.nowHP, comRole.lastShieldHP, comRole.shieldHP, 0, ), ) } self.loadView(world, entity, comNodeConfig) return false }) } private loadView(world: FightWorld, entity: number, nodeConfig: ComNodeConfig) { let comCocosNode = world.getComponent(entity, ComCocosNode) //当时间被重置,这个时候不再创建 if (!comCocosNode) return if (comCocosNode.node) { // 销毁当前node world.putNode(entity) } let layers = cc.find('Layers', world.fightCore.node) if (!layers) return let node: cc.Node let prefabName = nodeConfig.prefabName let pool = world.fightCore.gamePool.get(prefabName) if (pool.size() > 0 && pool.size() < 100) { node = pool.get() } else { node = cc.instantiate(Data.game.gameAssetMap.get(`prefab/fight/${prefabName}`) as cc.Prefab) node.x = -1000 } node.parent = layers.getChildByName(`${nodeConfig.layer}`) comCocosNode.node = node let eventProcess = node.getComponent(EventProcess) eventProcess.world = world let comRoleSpine = world.getComponent(entity, ComRoleSpine) if (comRoleSpine) { let roleSpineProcess = node.getComponent(RoleSpineProcess) roleSpineProcess.init(comRoleSpine.roleCfg, comRoleSpine.group == Data.game.gFriend) roleSpineProcess.onAttach() } let comRole = world.getComponent(entity, ComRole) let comTransform = world.getComponent(entity, ComTransform) if (comRole) { let roleEventProcess = eventProcess as RoleEventProcess roleEventProcess.init(comRole.roleCfg, comRole.group == Data.game.gFriend, comRole.width, comRole.height) comRole.cObject = node.addComponent(cObject) comRole.cObject.type = ShapeType.Box comRole.cObject.center = cc.v3(0, comRole.height / 2, 0) comRole.cObject.size = cc.v3(comRole.width, comRole.height, 0) comRole.cObject.init(comRole.group, entity) cCollider.inst.insert(comRole.cObject.body) let comAttackable = world.addComponent(entity, ComAttackable) comAttackable.dirty = false comAttackable.curAttack = 0 comAttackable.beAttacks.length = 0 comAttackable.countDown = 0 comAttackable.isMelee = comRole.attackRange > 0 && comRole.attackRange <= Data.game.meleeRange let comFindEnemy = world.addComponent(entity, ComFindEnemy) comFindEnemy.enemy = 0 comFindEnemy.willAttackMelee = 0 comFindEnemy.willBeAttackMelee = 0 comFindEnemy.cObject = node.addComponent(cObject) comFindEnemy.cObject.type = ShapeType.Box comFindEnemy.cObject.center = cc.v3(0, 0, 0) //comFindEnemy.cObject.radius = Data.game.meleeRange comFindEnemy.cObject.size = cc.v3(Data.game.meleeMonitorRangeX, Data.game.meleeMonitorRangeY, 0) comFindEnemy.cObject.init( comRole.group == Data.game.gFriend ? Data.game.gFriendMeleeMonitor : Data.game.gEnemyMeleeMonitor, entity, ) cCollider.inst.insert(comFindEnemy.cObject.body) comFindEnemy.attackCObject = node.addComponent(cObject) comFindEnemy.attackCObject.type = ShapeType.Sphere comFindEnemy.attackCObject.center = cc.v3(0, comRole.height / 2, 0) comFindEnemy.attackCObject.radius = comRole.roleCfg.attackRange comFindEnemy.attackCObject.init( comRole.group == Data.game.gFriend ? Data.game.gFriendAttackMonitor : Data.game.gEnemyAttackMonitor, entity, ) cCollider.inst.insert(comFindEnemy.attackCObject.body) if (comAttackable.isMelee) { comFindEnemy.cObjectMeleeX = node.addComponent(cObject) comFindEnemy.cObjectMeleeX.type = ShapeType.Box comFindEnemy.cObjectMeleeX.center = cc.v3(0, comRole.height / 2, 0) comFindEnemy.cObjectMeleeX.size = cc.v3(Data.game.meleeYMonitorRangeX, Data.game.meleeYMonitorRangeY, 0) comFindEnemy.cObjectMeleeX.init( comRole.group == Data.game.gFriend ? Data.game.gFriendMeleeXMonitor : Data.game.gEnemyMeleeXMonitor, entity, ) cCollider.inst.insert(comFindEnemy.cObjectMeleeX.body) } let comDizzy = world.addComponent(entity, ComDizzy) comDizzy.dirty = false comDizzy.countDown = 0 let comHasSkill = world.addComponent(entity, ComHasSkill) comHasSkill.skillCObjects.length = 0 comRole.skills.forEach((skillCfg, index) => { comHasSkill.skillCObjects[index] = node.addComponent(cObject) let skillCObject = comHasSkill.skillCObjects[index] skillCObject.type = ShapeType.Sphere skillCObject.center = cc.v3(0, 0, 0) skillCObject.radius = skillCfg.monitorRadius let skillGroup if (comRole.group == Data.game.gFriend) { skillGroup = skillCfg.isHurt ? Data.game.gFriendHurtSkillMonitor : Data.game.gFriendGainSkillMonitor } else { skillGroup = skillCfg.isHurt ? Data.game.gEnemyHurtSkillMonitor : Data.game.gEnemyGainSkillMonitor } skillCObject.init(skillGroup, entity) cCollider.inst.insert(skillCObject.body) }) let comSkillAbel = world.addComponent(entity, ComSkillAbel) comSkillAbel.dirty = false comSkillAbel.countDown = Infinity comSkillAbel.isInShield = false comSkillAbel.skillDirty = false comSkillAbel.startDirty = false comSkillAbel.castSkillTime = 0 comSkillAbel.skillBulletTime = 0 comSkillAbel.skillBulletNum = 0 comSkillAbel.skillConfig = null comSkillAbel.roles.length = 0 // 此处必须让所有的cObject位置更新 node.getComponents(cObject).forEach(cObject => { cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0)) }) if (comRole.roleCfg.lifeDuration > 0) { let comLifeTime = world.addComponent(entity, ComLifeTime) comLifeTime.countDown = comRole.roleCfg.lifeDuration comLifeTime.dirty = true } let comMovable = world.addComponent(entity, ComMovable) comMovable.pointIdx = -1 comMovable.points.length = 0 comMovable.leftMeleeEnemiesPosDirty = new Array(Data.game.attackLeftRadiusPoints.length).fill(-1) comMovable.rightMeleeEnemiesPosDirty = new Array(Data.game.attackRightRadiusPoints.length).fill(-1) if (comRole.enterTime > 0) { let comEnter = world.addComponent(entity, ComEnter) comEnter.duration = comRole.enterTime comEnter.countDown = comEnter.duration } else { // 添加behavior tree let comBehavior = world.addComponent(entity, ComBehaviorTree) comBehavior.bb = new BT.BlackBoard() world.initRoleBehavior(comBehavior, comRole.roleCfg) comCocosNode.events.push(new EventEnter()) } } let comBullet = world.getComponent(entity, ComBullet) if (comBullet) { let bulletEventProcess = eventProcess as BulletEventProcess bulletEventProcess.bulletConfig = comBullet.bulletCfg //bulletEventProcess.initLight(comTransform.x, comTransform.y, comBullet.bulletCfg) comBullet.cObject = node.addComponent(cObject) comBullet.cObject.type = ShapeType.Sphere comBullet.cObject.center = cc.v3(0, 0, 0) comBullet.cObject.radius = comBullet.bulletCfg.Uiscale[1] comBullet.cObject.init(comBullet.group, entity) cCollider.inst.insert(comBullet.cObject.body) comBullet.cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0)) comBullet.hitEnemies.length = 0 let comMovable = world.addComponent(entity, ComMovable) comMovable.speed = comBullet.bulletCfg.moveSpeed //计算弧度(-π到π) let radian = Math.atan2(comTransform.dir.y, comTransform.dir.x) //弧度转角度 node.angle = cc.misc.radiansToDegrees(radian) if (comBullet.bulletCfg.effectType.includes(BULLET_EFFECT_TYPE.line)) { let aniEntity = world.createAni(FRAME_ANI_NAME.lightLine, 0) let comFrameAni = world.getComponent(aniEntity, ComFrameAni) comFrameAni.lineStartPos = cc.v2(comTransform.x, comTransform.y) comFrameAni.lineEndEntity = entity comBullet.ejectionAnis.push(aniEntity) } } let comSkill = world.getComponent(entity, ComSkill) if (comSkill) { let skillEventProcess = eventProcess as SkillEventProcess skillEventProcess.skillCfg = comSkill.skillCfg comSkill.cObject = node.addComponent(cObject) comSkill.cObject.type = ShapeType.Box comSkill.cObject.center = cc.v3(0, 0, 0) comSkill.cObject.size = cc.v3(comSkill.skillCfg.attackRangeX, comSkill.skillCfg.attackRangeY, 0) comSkill.cObject.init(comSkill.group, entity) cCollider.inst.insert(comSkill.cObject.body) comSkill.cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0)) // 必须等技能加载好再放 comSkill.dirty = true if (world.isOneRoleSkill(comSkill.skillCfg)) { let comRole = world.getComponent(comSkill.role, ComRole) if (!world.isDie(comRole)) { comCocosNode.node.scale *= comRole.roleCfg.gameScale[GAME_SCALE_TYPE.skillHit] / 100 } } skillEventProcess.node.scale = comSkill.skillCfg.offsetPos[3] / 100 } let comFrameAni = world.getComponent(entity, ComFrameAni) if (comFrameAni) { let frameAniProcess = eventProcess as FrameAniProcess let aniConfig = comFrameAni.aniConfig frameAniProcess.aniConfig = aniConfig let roleCfg = world.getComponent(comFrameAni.role, ComRole)?.roleCfg if (roleCfg) { node.scale *= ((comFrameAni.aniConfig.offsetPos[3] / 100) * roleCfg.gameScale[GAME_SCALE_TYPE.skillHit]) / 100 } comFrameAni.dirty = true } comCocosNode.loaded = true // eventProcess会有一些配置,等上面配置赋值后再onAttach eventProcess.onAttach() return node } }