GameController.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. import { AnimationComponent, CameraComponent, director, find, instantiate, loader, Node, Prefab, Vec3, _decorator } from 'cc';
  2. import { EventDispatcher } from '../../../engines/events/EventDispatcher';
  3. import { GUIManager } from '../../../engines/gui/GUIManager';
  4. import GameConfigManager from '../../models/GameConfigManager';
  5. import { GameModel } from '../../models/GameModel';
  6. import { FightingScene } from '../../scenes/FightingScene';
  7. import { UIConst } from '../UIConst';
  8. import { FenceBase } from './fences/FenceBase';
  9. import { FightingMediator } from './FightingMediator';
  10. import { MonsterBase } from './monsters/MonsterBase';
  11. import { MonsterHPUIPool } from './monsters/MonsterHPUIPool';
  12. import { SkillBase } from './skills/SkillBase';
  13. import SkillManager from './skills/SkillManager';
  14. import AutomaticFifleWeapon from './weapons/AutomaticFifleWeapon';
  15. import { SingleShotWeapon } from './weapons/SingleShotWeapon';
  16. import { WeaponBase } from './weapons/WeaponBase';
  17. const { ccclass, property } = _decorator;
  18. export class GameController extends EventDispatcher{
  19. public weapon:WeaponBase;
  20. public fence:FenceBase;
  21. public camera:CameraComponent;
  22. public leftEndNode:Node;
  23. public middleEndNode:Node;
  24. public rightEndNode:Node;
  25. public leftStartNode:Node;
  26. public middleStartNode:Node;
  27. public rightStartNode:Node;
  28. /**
  29. * 当前正在运行的技能
  30. */
  31. public currentSkill:SkillBase;
  32. /**
  33. * 游戏结束
  34. */
  35. public GameOver:boolean=true;
  36. public leftMonsterList:MonsterBase[];
  37. public middleMonsterList:MonsterBase[];
  38. public rightMonsterList:MonsterBase[];
  39. /**
  40. * 怪物弹痕预制体
  41. */
  42. public monsterZhouDanPrefab:Prefab;
  43. /**
  44. * 怪物血条层
  45. */
  46. public monsterHPUILayer:Node;
  47. /**
  48. * 关卡配置
  49. */
  50. public levelConfig:any;
  51. private monstersConfig:any[];
  52. /**
  53. * 这一关怪物数量
  54. */
  55. public monsterTotalCount:number;
  56. /**
  57. * 本局游戏时间
  58. */
  59. private runTime:number=0;
  60. constructor()
  61. {
  62. super();
  63. this.leftMonsterList=[];
  64. this.middleMonsterList=[];
  65. this.rightMonsterList=[];
  66. }
  67. /**
  68. * 初始化
  69. * @param leftHand
  70. * @param rightHand
  71. */
  72. Init(uiMediator:FightingMediator):void{
  73. let sceneNode:Node=find("FightingScene");
  74. if(sceneNode==null){
  75. throw new Error("找不到战斗场景节点!");
  76. }
  77. let sceneScript:FightingScene=sceneNode.getComponent(FightingScene);
  78. if(sceneNode==null){
  79. throw new Error("战斗场景上没有挂载FightingScene脚本!");
  80. }
  81. this.camera=sceneScript.camrea;
  82. this.leftStartNode=sceneScript.LeftStartPos;
  83. this.middleStartNode=sceneScript.MiddleStartPos;
  84. this.rightStartNode=sceneScript.RightStartPos;
  85. this.leftEndNode=sceneScript.LeftEndPos;
  86. this.middleEndNode=sceneScript.MiddleEndPos;
  87. this.rightEndNode=sceneScript.RightEndPos;
  88. this.monsterZhouDanPrefab=sceneScript.monsterZhouDanPrefab;
  89. this.weapon=this.CreateWeapon(sceneScript.leftHand,sceneScript.rightHand);
  90. this.StartGame();
  91. }
  92. /**
  93. * 初始化栅栏
  94. */
  95. private InitFence():void{
  96. //如果老的存在,先清理
  97. if(this.fence&&this.fence.node!=null){
  98. this.fence.node.destroy();
  99. this.fence=null;
  100. }
  101. let config:any=GameConfigManager.GetFenceConfig(GameModel.single.currentFenceId);
  102. let prefab:Prefab=loader.getRes(config.prefab);
  103. if(prefab==null){
  104. throw new Error("栅栏资源未加载!");
  105. }
  106. let fenceNode:Node=instantiate(prefab);
  107. this.fence=fenceNode.getComponent(FenceBase);
  108. this.fence.config=config;
  109. this.fence.node.setPosition(new Vec3(0,0,-2));
  110. this.scene.addChild(fenceNode);
  111. }
  112. /**
  113. * 开始游戏
  114. */
  115. StartGame():void{
  116. GameModel.single.killCount=0;
  117. GameModel.single.angerCount=0;
  118. GameModel.single.integral=0;
  119. //重置技能
  120. this.SkillReset();
  121. this.GameOver=false;
  122. this.levelConfig=GameConfigManager.GetLevelConfig(GameModel.single.currentLevel);
  123. this.runTime=0;
  124. //清理怪物
  125. this.ClearMonsters();
  126. //复制一份配置
  127. this.monstersConfig=GameConfigManager.CreateMonsterByList(this.levelConfig.monsters,this.runTime);
  128. this.monsterTotalCount=this.monstersConfig.length;
  129. //直接重置子弹数量
  130. this.weapon.bulletCount=GameConfigManager.GetWeaponConfig(GameModel.single.currentWeaponId).clip;
  131. //初始化栅栏
  132. this.InitFence();
  133. }
  134. /**
  135. * 重玩
  136. */
  137. Replay():void{
  138. this.StartGame();
  139. GUIManager.single.Show(UIConst.FIGHTING_UI);
  140. }
  141. /**
  142. * 开始下一关
  143. */
  144. PlayNextLevel():void{
  145. console.log(GameModel.single.currentLevel);
  146. this.StartGame();
  147. GUIManager.single.Show(UIConst.FIGHTING_UI);
  148. }
  149. /**
  150. * 清理怪物
  151. */
  152. ClearMonsters():void{
  153. this.clearMonsterList(this.leftMonsterList);
  154. this.clearMonsterList(this.middleMonsterList);
  155. this.clearMonsterList(this.rightMonsterList);
  156. }
  157. private clearMonsterList(list:MonsterBase[]):void{
  158. if(list.length>0){
  159. list.forEach(element => {
  160. if(element.node!=null&&element.node.isValid){
  161. element.node.destroy();
  162. }
  163. });
  164. }
  165. list.length=0;
  166. }
  167. TryFire(fireKey:number):void{
  168. if(this.currentSkill!=null&&this.currentSkill.unController){
  169. return;
  170. }
  171. if(fireKey==0){
  172. this.weapon.StopFire();
  173. }else{
  174. this.weapon.StartFire(fireKey);
  175. }
  176. }
  177. /**
  178. * 使用技能
  179. */
  180. UseSkill():void{
  181. if(this.currentSkill!=null){
  182. return;
  183. }
  184. this.currentSkill=SkillManager.single.Create(this.weapon.weaponConfig.skill);
  185. this.currentSkill.config=GameConfigManager.GetSkillConfig(this.weapon.weaponConfig.skill);
  186. this.currentSkill.AddEvent(SkillBase.SKILL_COMPLETE,this,this.SkillReset,0);
  187. this.currentSkill.UseSkill(this.weapon);
  188. GameModel.single.angerCount=0;
  189. }
  190. /**
  191. * 清除技能
  192. */
  193. private SkillReset():void{
  194. if(this.currentSkill!=null){
  195. this.currentSkill.RemoveEvent(SkillBase.SKILL_COMPLETE,this,this.SkillReset);
  196. this.currentSkill.Dispose();
  197. this.currentSkill=null;
  198. }
  199. }
  200. Update(dt:number):void{
  201. if(this.GameOver){
  202. return;
  203. }
  204. if(this.currentSkill!=null){
  205. this.currentSkill.Update(dt);
  206. }
  207. this.runTime+=dt*1000;
  208. this.weapon.Update(dt);
  209. this.CheckMonster();
  210. }
  211. /**
  212. * 检测怪物
  213. */
  214. CheckMonster():void{
  215. if(this.monstersConfig.length>0){
  216. let config:any;
  217. let monster:Node;
  218. for (let index = 0; index < this.monstersConfig.length; index++) {
  219. config = this.monstersConfig[index];
  220. if(this.runTime>=config.createTime){
  221. //根据配置创建怪物
  222. monster=this.CreateMonster(config);
  223. this.scene.addChild(monster);
  224. this.monstersConfig.splice(index,1);
  225. index--;
  226. }
  227. }
  228. }
  229. if(this.monstersConfig.length==0&&this.leftMonsterList.length==0&&this.middleMonsterList.length==0&&this.rightMonsterList.length==0){
  230. //全部怪物死亡
  231. console.log("通关");
  232. GameModel.single.currentLevel++;
  233. if(GameModel.single.currentLevel>=GameConfigManager.MaxLevel){
  234. GameModel.single.currentLevel=GameConfigManager.MaxLevel;
  235. }
  236. this.ClearMonsters();
  237. this.GameOver=true;
  238. GUIManager.single.Show(UIConst.GAME_OVER_UI,true);
  239. GUIManager.single.Hide(UIConst.FIGHTING_UI);
  240. }
  241. }
  242. /**
  243. * 怪物攻击
  244. * @param damage 伤害
  245. */
  246. MonsterAttack(attackType:number,damage:number):void{
  247. if(this.GameOver){
  248. return;
  249. }
  250. if(attackType==0){
  251. if(this.fence.IsDie==false){
  252. this.fence.Damage(damage);
  253. }
  254. }else{
  255. this.GameOver=true;
  256. GUIManager.single.Show(UIConst.GAME_OVER_UI,false);
  257. GUIManager.single.Hide(UIConst.FIGHTING_UI);
  258. }
  259. }
  260. /**
  261. * 是否有怪物可攻击 -1没有可攻击怪 0 左边 1中间 2右边
  262. */
  263. public get FindAttackMonsterPosType():number{
  264. let leftDis:number=this.NearestDistance(this.leftMonsterList);
  265. let middleDis:number=this.NearestDistance(this.middleMonsterList);
  266. let rightDis:number=this.NearestDistance(this.rightMonsterList);
  267. if(leftDis<middleDis&&leftDis<rightDis){
  268. return 0;
  269. }
  270. if(middleDis<leftDis&&middleDis<rightDis){
  271. return 1;
  272. }
  273. if(rightDis<leftDis&&rightDis<middleDis){
  274. return 2;
  275. }
  276. return -1;
  277. }
  278. /**
  279. * 就算这一路中可攻击怪的最近距离
  280. * @param monsterList
  281. */
  282. private NearestDistance(monsterList:MonsterBase[]):number{
  283. let monster:MonsterBase;
  284. let endNode:Node;
  285. let minDis:number=Number.MAX_VALUE;
  286. let dis:number;
  287. for (let index = 0; index < monsterList.length; index++) {
  288. monster = monsterList[index];
  289. if(monster.config.startPos==0){
  290. endNode=this.leftEndNode;
  291. }else if(monster.config.startPos==1){
  292. endNode=this.middleEndNode;
  293. }else{
  294. endNode=this.rightEndNode;
  295. }
  296. dis=Vec3.distance(monster.node.worldPosition,endNode.worldPosition);
  297. if(dis<=this.weapon.weaponConfig.attackDistance){
  298. if(dis<minDis){
  299. minDis=dis;
  300. }
  301. }
  302. }
  303. return minDis;
  304. }
  305. /**
  306. * 武器攻击
  307. */
  308. WeaponAttack():void{
  309. console.log("开枪了");
  310. let monsterList:MonsterBase[];
  311. let monsterLists:Array<Array<MonsterBase>>=[];
  312. //攻击1条路
  313. if(this.weapon.weaponConfig.attackRange==1){
  314. if(this.weapon.fireKey==1){
  315. monsterList=this.leftMonsterList;
  316. }else if(this.weapon.fireKey==2){
  317. monsterList=this.middleMonsterList;
  318. }else{
  319. monsterList=this.rightMonsterList;
  320. }
  321. if(monsterList.length==0){
  322. return;
  323. }
  324. monsterList.sort(this.monsterSortFunc);
  325. monsterLists.push(monsterList);
  326. }else if(this.weapon.weaponConfig.attackRange==2){//攻击2条路
  327. //左
  328. if(this.weapon.fireKey==1){
  329. if(this.leftMonsterList.length>0){
  330. this.leftMonsterList.sort(this.monsterSortFunc);
  331. monsterLists.push(this.leftMonsterList);
  332. }
  333. if(this.middleMonsterList.length>0){
  334. this.middleMonsterList.sort(this.monsterSortFunc);
  335. monsterLists.push(this.middleMonsterList);
  336. }
  337. }else if(this.weapon.fireKey==2){//中
  338. if(this.middleMonsterList.length>0){
  339. this.middleMonsterList.sort(this.monsterSortFunc);
  340. monsterLists.push(this.middleMonsterList);
  341. }
  342. //随机左边/右边
  343. let random:number=Math.random();
  344. if(random>0.5){
  345. if(this.rightMonsterList.length>0){
  346. this.rightMonsterList.sort(this.monsterSortFunc);
  347. monsterLists.push(this.rightMonsterList);
  348. }
  349. }else{
  350. if(this.leftMonsterList.length>0){
  351. this.leftMonsterList.sort(this.monsterSortFunc);
  352. monsterLists.push(this.leftMonsterList);
  353. }
  354. }
  355. }else{//右
  356. if(this.rightMonsterList.length>0){
  357. this.rightMonsterList.sort(this.monsterSortFunc);
  358. monsterLists.push(this.rightMonsterList);
  359. }
  360. if(this.middleMonsterList.length>0){
  361. this.middleMonsterList.sort(this.monsterSortFunc);
  362. monsterLists.push(this.middleMonsterList);
  363. }
  364. }
  365. }else{//攻击3条路
  366. if(this.leftMonsterList.length>0){
  367. this.leftMonsterList.sort(this.monsterSortFunc);
  368. monsterLists.push(this.leftMonsterList);
  369. }
  370. if(this.middleMonsterList.length>0){
  371. this.middleMonsterList.sort(this.monsterSortFunc);
  372. monsterLists.push(this.middleMonsterList);
  373. }
  374. if(this.middleMonsterList.length>0){
  375. this.middleMonsterList.sort(this.monsterSortFunc);
  376. monsterLists.push(this.middleMonsterList);
  377. }
  378. }
  379. //没有任何怪物可以攻击
  380. if(monsterLists.length==0){
  381. return;
  382. }
  383. //攻击怪物
  384. let monster:MonsterBase;
  385. let endNode:Node;
  386. let index:number=0;
  387. let total:number=0;
  388. let dis:number=0;
  389. monsterLists.forEach(monsterList => {
  390. //攻击怪物
  391. index=0;
  392. total=Math.min(this.weapon.weaponConfig.attackCount,monsterList.length);
  393. while(index<total){
  394. monster=monsterList[index];
  395. if(monster.config.startPos==0){
  396. endNode=this.leftEndNode;
  397. }else if(monster.config.startPos==1){
  398. endNode=this.middleEndNode;
  399. }else{
  400. endNode=this.rightEndNode;
  401. }
  402. if(Vec3.distance(monster.node.worldPosition,endNode.worldPosition)<=this.weapon.weaponConfig.attackDistance){
  403. if(this.currentSkill!=null){
  404. monster.Damage(this.weapon.weaponConfig.damage*this.currentSkill.damage);
  405. }else{
  406. monster.Damage(this.weapon.weaponConfig.damage);
  407. }
  408. }else{
  409. console.log("超出枪械攻击距离Miss");
  410. }
  411. index++;
  412. total=Math.min(this.weapon.weaponConfig.attackCount,monsterList.length);
  413. }
  414. for (let index = 0; index < monsterList.length; index++) {
  415. monster = monsterList[index];
  416. //怪物死亡
  417. if(monster.isDie){
  418. //增加怒气
  419. GameModel.single.angerCount+=monster.config.anger;
  420. //增加击杀量
  421. GameModel.single.killCount++;
  422. //增加积分
  423. if(monster.config.integral>0){
  424. GameModel.single.integral+=monster.config.integral;
  425. }
  426. //从列表中删除
  427. monsterList.splice(index,1);
  428. index--;
  429. }
  430. }
  431. });
  432. }
  433. private monsterSortFunc(a:MonsterBase,b:MonsterBase):number{
  434. if(a.node.position.z>b.node.position.z){
  435. return -1;
  436. }else if(a.node.position.z<b.node.position.z){
  437. return 1;
  438. }
  439. return 0;
  440. }
  441. /**
  442. * 根据配置生成怪物
  443. * @param config
  444. */
  445. private CreateMonster(config:any):Node{
  446. let monsterConfig:any=GameConfigManager.GetMonsterConfig(config.monsterId);
  447. if(monsterConfig==null){
  448. throw new Error("找不到怪物配置:"+config.monsterId);
  449. }
  450. let prefab:Prefab=loader.getRes(monsterConfig.prefab);
  451. let monster:Node=instantiate(prefab);
  452. monster.name="Monster"+config.mId;
  453. let monsterScript=monster.addComponent(MonsterBase);
  454. monsterScript.config=config;
  455. //左
  456. if(config.startPos==0){
  457. monster.setPosition(this.leftStartNode.worldPosition);
  458. this.leftMonsterList.push(monsterScript);
  459. }else if(config.startPos==1){//中
  460. monster.setPosition(this.middleStartNode.worldPosition);
  461. this.middleMonsterList.push(monsterScript);
  462. }else{//右
  463. monster.setPosition(this.rightStartNode.worldPosition);
  464. this.rightMonsterList.push(monsterScript);
  465. }
  466. //创建血条
  467. monsterScript.hpView=MonsterHPUIPool.Create();
  468. monsterScript.hpView.monster=monsterScript;
  469. return monster;
  470. }
  471. private CreateWeapon(leftHand:AnimationComponent,rightHand:AnimationComponent):any{
  472. let config:any=GameConfigManager.GetWeaponConfig(GameModel.single.currentWeaponId);
  473. if(config.fireType==0){
  474. return new SingleShotWeapon(leftHand,rightHand);
  475. }else if(config.fireType==1){
  476. return new AutomaticFifleWeapon(leftHand,rightHand);
  477. }
  478. return new SingleShotWeapon(leftHand,rightHand);;
  479. }
  480. get scene(){
  481. return director.getScene();
  482. }
  483. private static instance:GameController;
  484. public static get single(){
  485. if(this.instance==null){
  486. this.instance=new GameController();
  487. }
  488. return this.instance;
  489. }
  490. }