GameController.ts 20 KB

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