GameController.ts 17 KB

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