SysCocosView.ts 16 KB

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