GameController.ts 18 KB

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