SysCocosView.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /** @format */
  2. import {ComNodeConfig} from '../components/ComNodeConfig'
  3. import {ComCocosNode} from '../components/ComCocosNode'
  4. import {ECSSystem} from '../lib/ECSSystem'
  5. import {GenFilterKey} from '../lib/ECSComponent'
  6. import {ComTransform} from '../components/ComTransform'
  7. import {ComRole} from '../components/ComRole'
  8. import {FightWorld} from '../worlds/FightWorld'
  9. import {Data} from '../../GameControl'
  10. import {cObject} from '../../collision/Object'
  11. import {cCollider} from '../../collision/Collider'
  12. import {EventEnter, EventHPChange, EventType} from '../core/NodeEvent'
  13. import {ComFindEnemy} from '../components/ComFindEnemy'
  14. import {ComBullet} from '../components/ComBullet'
  15. import {ComMovable} from '../components/ComMovable'
  16. import {ShapeType} from '../../collision/Shape'
  17. import {ComAttackable} from '../components/ComAttackable'
  18. import {ComDizzy} from '../components/ComDizzy'
  19. import {ComHasSkill} from '../components/ComHasSkill'
  20. import {ComSkillAbel} from '../components/ComSkillAbel'
  21. import {ComSkill} from '../components/ComSkill'
  22. import {ComLifeTime} from '../components/ComLifeTime'
  23. import {ComBehaviorTree} from '../components/ComBehaviorTree'
  24. import {BT} from '../../behaviorTree/BehaviorTree'
  25. import {ComRoleSpine} from '../components/ComRoleSpine'
  26. import {RoleEventProcess} from '../core/RoleEventProcess'
  27. import {BulletEventProcess} from '../core/BulletEventProcess'
  28. import {SkillEventProcess} from '../core/SkillEventProcess'
  29. import {EventProcess} from '../core/EventProcess'
  30. import {RoleSpineProcess} from '../core/RoleSpineProcess'
  31. import {ComFrameAni} from '../components/ComFrameAni'
  32. import {FrameAniProcess} from '../core/FrameAniProcess'
  33. import {ComEnter} from '../components/ComEnter'
  34. import {BULLET_EFFECT_TYPE, FRAME_ANI_NAME, GAME_SCALE_TYPE} from '../../enums/Enum'
  35. import {ccUtils} from '../../utils/ccUtils'
  36. export interface ITouchProcessor {
  37. onTouchStart(worldPos: cc.Vec2, world: FightWorld): void
  38. onTouchMove?(worldPos: cc.Vec2, world: FightWorld): void
  39. onTouchEnd?(worldPos: cc.Vec2, world: FightWorld): void
  40. onTouchCancel?(worldPos: cc.Vec2, world: FightWorld): void
  41. }
  42. const FILTER_COCOS_NODE = GenFilterKey([ComNodeConfig], [ComCocosNode])
  43. const FILTER_NODE_EVENT = GenFilterKey([ComCocosNode, ComTransform])
  44. export class SysCocosView extends ECSSystem implements ITouchProcessor {
  45. bulletCD: number = 0
  46. onTouchStart(worldPos: cc.Vec2, world: FightWorld): void {}
  47. onTouchMove(worldPos: cc.Vec2, world: FightWorld): void {}
  48. onTouchCancel(worldPos: cc.Vec2, world: FightWorld): void {}
  49. onTouchEnd(worldPos: cc.Vec2, world: FightWorld): void {}
  50. onAdd(world: FightWorld) {}
  51. onRemove(world: FightWorld) {}
  52. onEntityEnter(world: FightWorld, entity: number) {}
  53. onEntityLeave(world: FightWorld, entity: number) {}
  54. onUpdate(world: FightWorld, dt: number) {
  55. let self = this
  56. this.bulletCD -= dt
  57. if (this.bulletCD <= 0) this.bulletCD = 0
  58. world.getFilter(FILTER_NODE_EVENT).walk((entity: number) => {
  59. let comCocosNode = world.getComponent(entity, ComCocosNode)
  60. if (!comCocosNode.loaded) {
  61. return
  62. }
  63. let eventProcess = comCocosNode.node.getComponent(EventProcess)
  64. if (!eventProcess) return
  65. let comTrans = world.getComponent(entity, ComTransform)
  66. eventProcess.syncPos(comTrans.x, comTrans.y)
  67. while (comCocosNode.events.length) {
  68. let event = comCocosNode.events.shift()
  69. if (event.type != EventType.GraphicsDraw) {
  70. //console.log('entity----->', entity, 'EventType----->', EventType[event.type])
  71. }
  72. eventProcess.processEvent(event)
  73. }
  74. return false
  75. })
  76. //先运行存在节点,再加载节点,加载的节点下一帧运行
  77. world.getFilter(FILTER_COCOS_NODE).walk((entity: number) => {
  78. let comNodeConfig = world.getComponent(entity, ComNodeConfig)
  79. let comCocosNode = world.addComponent(entity, ComCocosNode)
  80. comCocosNode.loaded = false
  81. let comRole = world.getComponent(entity, ComRole)
  82. if (comRole) {
  83. comCocosNode.events.push(
  84. new EventHPChange(
  85. comRole.HP,
  86. comRole.lastHP,
  87. comRole.nowHP,
  88. comRole.lastShieldHP,
  89. comRole.shieldHP,
  90. 0,
  91. ),
  92. )
  93. }
  94. self.loadView(world, entity, comNodeConfig)
  95. return false
  96. })
  97. }
  98. private loadView(world: FightWorld, entity: number, nodeConfig: ComNodeConfig) {
  99. let comCocosNode = world.getComponent(entity, ComCocosNode)
  100. //当时间被重置,这个时候不再创建
  101. if (!comCocosNode) return
  102. if (comCocosNode.node) {
  103. // 销毁当前node
  104. world.putNode(entity)
  105. }
  106. let layers = cc.find('Layers', world.fightCore.node)
  107. if (!layers) return
  108. let node: cc.Node
  109. let prefabName = nodeConfig.prefabName
  110. let pool = world.fightCore.gamePool.get(prefabName)
  111. if (pool.size() > 0 && pool.size() < 100) {
  112. node = pool.get()
  113. } else {
  114. node = cc.instantiate(Data.game.gameAssetMap.get(`prefab/fight/${prefabName}`) as cc.Prefab)
  115. node.x = -1000
  116. }
  117. node.parent = layers.getChildByName(`${nodeConfig.layer}`)
  118. comCocosNode.node = node
  119. let eventProcess = node.getComponent(EventProcess)
  120. eventProcess.world = world
  121. let comRoleSpine = world.getComponent(entity, ComRoleSpine)
  122. if (comRoleSpine) {
  123. let roleSpineProcess = node.getComponent(RoleSpineProcess)
  124. roleSpineProcess.init(comRoleSpine.roleCfg, comRoleSpine.group == Data.game.gFriend)
  125. roleSpineProcess.onAttach()
  126. }
  127. let comRole = world.getComponent(entity, ComRole)
  128. let comTransform = world.getComponent(entity, ComTransform)
  129. if (comRole) {
  130. let roleEventProcess = eventProcess as RoleEventProcess
  131. roleEventProcess.init(comRole.roleCfg, comRole.group == Data.game.gFriend, comRole.width, comRole.height)
  132. comRole.cObject = node.addComponent(cObject)
  133. comRole.cObject.type = ShapeType.Box
  134. comRole.cObject.center = cc.v3(0, comRole.height / 2, 0)
  135. comRole.cObject.size = cc.v3(comRole.width, comRole.height, 0)
  136. comRole.cObject.init(comRole.group, entity)
  137. cCollider.inst.insert(comRole.cObject.body)
  138. let comAttackable = world.addComponent(entity, ComAttackable)
  139. comAttackable.dirty = false
  140. comAttackable.curAttack = 0
  141. comAttackable.beAttacks.length = 0
  142. comAttackable.countDown = 0
  143. comAttackable.isMelee = comRole.attackRange > 0 && comRole.attackRange <= Data.game.meleeRange
  144. let comFindEnemy = world.addComponent(entity, ComFindEnemy)
  145. comFindEnemy.enemy = 0
  146. comFindEnemy.willAttackMelee = 0
  147. comFindEnemy.willBeAttackMelee = 0
  148. comFindEnemy.cObject = node.addComponent(cObject)
  149. comFindEnemy.cObject.type = ShapeType.Box
  150. comFindEnemy.cObject.center = cc.v3(0, 0, 0)
  151. //comFindEnemy.cObject.radius = Data.game.meleeRange
  152. comFindEnemy.cObject.size = cc.v3(Data.game.meleeMonitorRangeX, Data.game.meleeMonitorRangeY, 0)
  153. comFindEnemy.cObject.init(
  154. comRole.group == Data.game.gFriend ? Data.game.gFriendMeleeMonitor : Data.game.gEnemyMeleeMonitor,
  155. entity,
  156. )
  157. cCollider.inst.insert(comFindEnemy.cObject.body)
  158. comFindEnemy.attackCObject = node.addComponent(cObject)
  159. comFindEnemy.attackCObject.type = ShapeType.Sphere
  160. comFindEnemy.attackCObject.center = cc.v3(0, comRole.height / 2, 0)
  161. comFindEnemy.attackCObject.radius = comRole.roleCfg.attackRange
  162. comFindEnemy.attackCObject.init(
  163. comRole.group == Data.game.gFriend ? Data.game.gFriendAttackMonitor : Data.game.gEnemyAttackMonitor,
  164. entity,
  165. )
  166. cCollider.inst.insert(comFindEnemy.attackCObject.body)
  167. if (comAttackable.isMelee) {
  168. comFindEnemy.cObjectMeleeX = node.addComponent(cObject)
  169. comFindEnemy.cObjectMeleeX.type = ShapeType.Box
  170. comFindEnemy.cObjectMeleeX.center = cc.v3(0, comRole.height / 2, 0)
  171. comFindEnemy.cObjectMeleeX.size = cc.v3(Data.game.meleeYMonitorRangeX, Data.game.meleeYMonitorRangeY, 0)
  172. comFindEnemy.cObjectMeleeX.init(
  173. comRole.group == Data.game.gFriend ? Data.game.gFriendMeleeXMonitor : Data.game.gEnemyMeleeXMonitor,
  174. entity,
  175. )
  176. cCollider.inst.insert(comFindEnemy.cObjectMeleeX.body)
  177. }
  178. let comDizzy = world.addComponent(entity, ComDizzy)
  179. comDizzy.dirty = false
  180. comDizzy.countDown = 0
  181. let comHasSkill = world.addComponent(entity, ComHasSkill)
  182. comHasSkill.skillCObjects.length = 0
  183. comRole.skills.forEach((skillCfg, index) => {
  184. comHasSkill.skillCObjects[index] = node.addComponent(cObject)
  185. let skillCObject = comHasSkill.skillCObjects[index]
  186. skillCObject.type = ShapeType.Sphere
  187. skillCObject.center = cc.v3(0, 0, 0)
  188. skillCObject.radius = skillCfg.monitorRadius
  189. let skillGroup
  190. if (comRole.group == Data.game.gFriend) {
  191. skillGroup = skillCfg.isHurt ? Data.game.gFriendHurtSkillMonitor : Data.game.gFriendGainSkillMonitor
  192. } else {
  193. skillGroup = skillCfg.isHurt ? Data.game.gEnemyHurtSkillMonitor : Data.game.gEnemyGainSkillMonitor
  194. }
  195. skillCObject.init(skillGroup, entity)
  196. cCollider.inst.insert(skillCObject.body)
  197. })
  198. let comSkillAbel = world.addComponent(entity, ComSkillAbel)
  199. comSkillAbel.dirty = false
  200. comSkillAbel.countDown = Infinity
  201. comSkillAbel.isInShield = false
  202. comSkillAbel.skillDirty = false
  203. comSkillAbel.startDirty = false
  204. comSkillAbel.castSkillTime = 0
  205. comSkillAbel.skillBulletTime = 0
  206. comSkillAbel.skillBulletNum = 0
  207. comSkillAbel.skillConfig = null
  208. comSkillAbel.roles.length = 0
  209. // 此处必须让所有的cObject位置更新
  210. node.getComponents(cObject).forEach(cObject => {
  211. cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0))
  212. })
  213. if (comRole.roleCfg.lifeDuration > 0) {
  214. let comLifeTime = world.addComponent(entity, ComLifeTime)
  215. comLifeTime.countDown = comRole.roleCfg.lifeDuration
  216. comLifeTime.dirty = true
  217. }
  218. let comMovable = world.addComponent(entity, ComMovable)
  219. comMovable.pointIdx = -1
  220. comMovable.points.length = 0
  221. comMovable.leftMeleeEnemiesPosDirty = new Array(Data.game.attackLeftRadiusPoints.length).fill(-1)
  222. comMovable.rightMeleeEnemiesPosDirty = new Array(Data.game.attackRightRadiusPoints.length).fill(-1)
  223. if (comRole.enterTime > 0) {
  224. let comEnter = world.addComponent(entity, ComEnter)
  225. comEnter.duration = comRole.enterTime
  226. comEnter.countDown = comEnter.duration
  227. } else {
  228. // 添加behavior tree
  229. let comBehavior = world.addComponent(entity, ComBehaviorTree)
  230. comBehavior.bb = new BT.BlackBoard()
  231. world.initRoleBehavior(comBehavior, comRole.roleCfg)
  232. comCocosNode.events.push(new EventEnter())
  233. }
  234. }
  235. let comBullet = world.getComponent(entity, ComBullet)
  236. if (comBullet) {
  237. let bulletEventProcess = eventProcess as BulletEventProcess
  238. bulletEventProcess.bulletConfig = comBullet.bulletCfg
  239. //bulletEventProcess.initLight(comTransform.x, comTransform.y, comBullet.bulletCfg)
  240. comBullet.cObject = node.addComponent(cObject)
  241. comBullet.cObject.type = ShapeType.Sphere
  242. comBullet.cObject.center = cc.v3(0, 0, 0)
  243. comBullet.cObject.radius = comBullet.bulletCfg.Uiscale[1]
  244. comBullet.cObject.init(comBullet.group, entity)
  245. cCollider.inst.insert(comBullet.cObject.body)
  246. comBullet.cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0))
  247. comBullet.hitEnemies.length = 0
  248. let comMovable = world.addComponent(entity, ComMovable)
  249. comMovable.speed = comBullet.bulletCfg.moveSpeed
  250. //计算弧度(-π到π)
  251. let radian = Math.atan2(comTransform.dir.y, comTransform.dir.x)
  252. //弧度转角度
  253. node.angle = cc.misc.radiansToDegrees(radian)
  254. if (comBullet.bulletCfg.effectType.includes(BULLET_EFFECT_TYPE.line)) {
  255. let aniEntity = world.createAni(FRAME_ANI_NAME.lightLine, 0)
  256. let comFrameAni = world.getComponent(aniEntity, ComFrameAni)
  257. comFrameAni.lineStartPos = cc.v2(comTransform.x, comTransform.y)
  258. comFrameAni.lineEndEntity = entity
  259. comBullet.ejectionAnis.push(aniEntity)
  260. }
  261. }
  262. let comSkill = world.getComponent(entity, ComSkill)
  263. if (comSkill) {
  264. let skillEventProcess = eventProcess as SkillEventProcess
  265. skillEventProcess.skillCfg = comSkill.skillCfg
  266. comSkill.cObject = node.addComponent(cObject)
  267. comSkill.cObject.type = ShapeType.Box
  268. comSkill.cObject.center = cc.v3(0, 0, 0)
  269. comSkill.cObject.size = cc.v3(comSkill.skillCfg.attackRangeX, comSkill.skillCfg.attackRangeY, 0)
  270. comSkill.cObject.init(comSkill.group, entity)
  271. cCollider.inst.insert(comSkill.cObject.body)
  272. comSkill.cObject.setPosition(cc.v3(comTransform.x, comTransform.y, 0))
  273. // 必须等技能加载好再放
  274. comSkill.dirty = true
  275. if (world.isOneRoleSkill(comSkill.skillCfg)) {
  276. let comRole = world.getComponent(comSkill.role, ComRole)
  277. if (!world.isDie(comRole)) {
  278. comCocosNode.node.scale *= comRole.roleCfg.gameScale[GAME_SCALE_TYPE.skillHit] / 100
  279. }
  280. }
  281. skillEventProcess.node.scale = comSkill.skillCfg.offsetPos[3] / 100
  282. }
  283. let comFrameAni = world.getComponent(entity, ComFrameAni)
  284. if (comFrameAni) {
  285. let frameAniProcess = eventProcess as FrameAniProcess
  286. let aniConfig = comFrameAni.aniConfig
  287. frameAniProcess.aniConfig = aniConfig
  288. let roleCfg = world.getComponent(comFrameAni.role, ComRole)?.roleCfg
  289. if (roleCfg) {
  290. node.scale *=
  291. ((comFrameAni.aniConfig.offsetPos[3] / 100) * roleCfg.gameScale[GAME_SCALE_TYPE.skillHit]) / 100
  292. }
  293. comFrameAni.dirty = true
  294. }
  295. comCocosNode.loaded = true
  296. // eventProcess会有一些配置,等上面配置赋值后再onAttach
  297. eventProcess.onAttach()
  298. return node
  299. }
  300. }