GameMgr.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. import Monster from "./role/Monster";
  2. import Player from "./role/Player";
  3. import Role from "./role/Role";
  4. import Timer from "./Timer";
  5. import TopBar from "./ui/TopBar";
  6. import Login from "./ui/Login";
  7. import Account from "./ui/Account";
  8. import Coach from "./role/Coach";
  9. import Tool from "./Tool";
  10. const {ccclass, property} = cc._decorator;
  11. /**游戏管理类 */
  12. @ccclass
  13. export default class GameMgr extends cc.Component {
  14. @property({
  15. type:cc.Prefab
  16. })
  17. private ui_login:cc.Prefab = null;
  18. @property({
  19. type:cc.AudioClip
  20. })
  21. public ad_bong:cc.AudioClip = null;
  22. @property({
  23. type:cc.AudioClip
  24. })
  25. public ad_btn:cc.AudioClip = null;
  26. @property({
  27. type:cc.AudioClip
  28. })
  29. public ad_bgm:cc.AudioClip = null;
  30. public gameViewSize:cc.Size;
  31. public camera:cc.Node;
  32. public background:cc.Node;
  33. public teachMode:TeachMode;
  34. private coach:Coach;
  35. private player:Player;
  36. private monster:Monster;
  37. private topBar:TopBar;
  38. private timer:Timer;
  39. private score:number = 0;
  40. public onLoad():void{
  41. window.gameMgr = this;
  42. this.camera = this.node.getChildByName('Main Camera');
  43. this.addLoginUi();
  44. }
  45. private addLoginUi():void{
  46. let ui = cc.instantiate(this.ui_login);
  47. ui.addComponent(Login);
  48. this.node.addChild(ui);
  49. //把登录界面作为背景节点
  50. this.background = ui;
  51. }
  52. public startGame():void{
  53. this.createMonster();
  54. this.createPlayer();
  55. this.player.setTarget(this.monster);
  56. this.monster.setTarget(this.player);
  57. this.createPlayerButton();
  58. this.createTopBarUi();
  59. this.setAccountScoreListener();
  60. this.setGameOverListener();
  61. this.timer.showStartCountDownAnimation(this.background,this.startMatch.bind(this));
  62. this.score = 0;
  63. }
  64. /**教学模式 */
  65. public startTeachMode():void{
  66. this.createCoach();
  67. this.createPlayer();
  68. this.coach.setTarget(this.player);
  69. this.player.setTarget(this.coach);
  70. this.createPlayerButton();
  71. this.createTopBarUi(true);
  72. this.player.pausing = false;
  73. this.coach.pausing = false;
  74. this.teachMode = new TeachMode(this.gameViewSize,this.background,this.coach,this.player);
  75. this.teachMode.start();
  76. }
  77. private createCoach():void{
  78. this.coach = new cc.Node().addComponent(Coach);
  79. this.coach.node.y = -this.gameViewSize.height*0.43;
  80. this.coach.node.scaleX *= this.gameViewSize.width/cc.view.getDesignResolutionSize().width;//适配游戏可视域的宽度
  81. this.background.addChild(this.coach.node);
  82. }
  83. private createMonster():void{
  84. this.monster = new cc.Node().addComponent(Monster);
  85. this.monster.node.y = -this.gameViewSize.height*0.43;
  86. this.monster.node.scaleX *= this.gameViewSize.width/cc.view.getDesignResolutionSize().width;//适配游戏可视域的宽度
  87. this.background.addChild(this.monster.node);
  88. }
  89. private createPlayer():void{
  90. this.player = new cc.Node().addComponent(Player);
  91. this.player.node.y = -this.gameViewSize.height/2;
  92. this.player.node.scaleX *= this.gameViewSize.width/cc.view.getDesignResolutionSize().width;//适配游戏可视域的宽度
  93. this.background.addChild(this.player.node);
  94. }
  95. /**摇杆 */
  96. private btn_rocker:cc.Node;
  97. private btn_rocker_offset:cc.Vec2;
  98. /**防守按钮 */
  99. private btn_defense:cc.Node;
  100. private createPlayerButton():void{
  101. this.btn_rocker = Tool.createButtonNode({
  102. width:this.gameViewSize.width,
  103. height:this.gameViewSize.height,
  104. });
  105. this.background.addChild(this.btn_rocker);
  106. this.btn_defense = Tool.createButtonNode({
  107. y:-550,
  108. backgroundImage:'texture/circle',
  109. transition:cc.Button.Transition.NONE,
  110. color:cc.Color.GRAY,
  111. opacity:155
  112. });
  113. this.background.addChild(this.btn_defense);
  114. //监听事件
  115. this.player.node.on(Role.EventType_NoAction,()=>{
  116. this.btn_rocker_offset = cc.v2(0,0);
  117. },this);
  118. this.btn_rocker.on(cc.Node.EventType.TOUCH_START,(event:cc.Event.EventTouch)=>{
  119. this.btn_rocker_offset = cc.v2(0,0);
  120. });
  121. this.btn_rocker.on(cc.Node.EventType.TOUCH_MOVE,(event:cc.Event.EventTouch)=>{
  122. this.btn_rocker_offset = this.btn_rocker_offset.add(event.getDelta());
  123. if(this.btn_rocker_offset.mag()>100){
  124. if(this.btn_rocker_offset.x<0&&this.btn_rocker_offset.y>=0){
  125. this.player.rightJay();
  126. return;
  127. }
  128. if(this.btn_rocker_offset.x>=0&&this.btn_rocker_offset.y>=0){
  129. this.player.leftJay();
  130. return;
  131. }
  132. if(this.btn_rocker_offset.x<0&&this.btn_rocker_offset.y<0){
  133. this.player.leftDodge();
  134. return;
  135. }
  136. if(this.btn_rocker_offset.x>0&&this.btn_rocker_offset.y<0){
  137. this.player.rightDodge();
  138. return;
  139. }
  140. }
  141. },this);
  142. this.btn_rocker.on(cc.Node.EventType.TOUCH_END,(event:cc.Event.EventTouch)=>{
  143. this.btn_rocker_offset = cc.v2(0,0);
  144. },this);
  145. this.btn_rocker.on(cc.Node.EventType.TOUCH_CANCEL,(event:cc.Event.EventTouch)=>{
  146. this.btn_rocker_offset = cc.v2(0,0);
  147. },this);
  148. this.btn_defense.on(cc.Node.EventType.TOUCH_START,()=>{
  149. this.player.defense();
  150. this.btn_defense.opacity = 90;
  151. },this);
  152. this.btn_defense.on(cc.Node.EventType.TOUCH_END,()=>{
  153. this.btn_defense.opacity = 155;
  154. },this);
  155. this.btn_defense.on(cc.Node.EventType.TOUCH_CANCEL,()=>{
  156. this.btn_defense.opacity = 155;
  157. },this);
  158. }
  159. /**
  160. * 创建战斗顶部栏
  161. * @param isCocah 对手是否为教练?
  162. */
  163. private createTopBarUi(isCoach?:boolean):void{
  164. let ui = cc.instantiate(cc.loader.getRes('prefab/ui_topBar',cc.Prefab)) as cc.Node;
  165. ui.scaleX *= this.gameViewSize.width/cc.view.getDesignResolutionSize().width;//适配游戏可视域的宽度
  166. this.background.addChild(ui);
  167. this.topBar = ui.addComponent(TopBar);
  168. this.topBar.listenRole(this.player,isCoach?this.coach:this.monster);
  169. this.timer = ui.addComponent(Timer);
  170. this.timer.init(60,this.topBar.timerLabel);
  171. }
  172. /**开始比赛 */
  173. private startMatch():void{
  174. this.player.pausing = false;
  175. this.monster.pausing = false;
  176. this.timer.startCountTime();
  177. }
  178. /**暂停比赛 */
  179. private pauseMatch():void{
  180. this.player.pausing = true;
  181. this.monster.pausing = true;
  182. this.timer.stopCountTime();
  183. }
  184. /**
  185. * 设置计分监听事件
  186. * 积分规则:被击中扣100,击中加100分,躲避成功加100分,防守成功加100分,分数下限为0
  187. */
  188. private setAccountScoreListener():void{
  189. this.player.node.on(Role.EventType_BeHit,()=>{
  190. let nextScore = this.score - 100;
  191. nextScore<0 ? this.score = 0 : this.score = nextScore;
  192. },this);
  193. this.player.node.on(Role.EventType_DodgeSuccess,()=>{
  194. this.score += 100;
  195. },this);
  196. this.player.node.on(Role.EventType_DefenseSuccess,()=>{
  197. this.score += 100;
  198. },this);
  199. this.monster.node.on(Role.EventType_BeHit,()=>{
  200. this.score += 100;
  201. },this);
  202. }
  203. /**设置游戏结束监听事件 */
  204. private setGameOverListener():void{
  205. //玩家死亡
  206. this.player.node.on(Role.EventType_Die,()=>{
  207. this.pauseMatch();
  208. this.player.node.runAction(cc.fadeOut(1));
  209. this.addAccountUi(false);
  210. },this);
  211. //怪物死亡
  212. this.monster.node.on(Role.EventType_Die,()=>{
  213. this.pauseMatch();
  214. this.monster.node.runAction(cc.fadeOut(1));
  215. this.addAccountUi(true);
  216. },this);
  217. //时间结束
  218. this.timer.node.on(Timer.EventType_ZERO,()=>{
  219. this.pauseMatch();
  220. if(this.player.property_hp>=this.monster.property_hp){
  221. this.addAccountUi(true);
  222. }else{
  223. this.addAccountUi(false);
  224. }
  225. },this);
  226. }
  227. /**展示结算面板 */
  228. private addAccountUi(win:boolean):void{
  229. //删除防御按钮
  230. this.btn_defense.destroy();
  231. if(win){
  232. //胜利时间加分:剩余时间*100分
  233. this.score += Math.floor(this.timer.time*100);
  234. }
  235. this.score += Math.floor(this.player.property_hp/this.player.property_maxHp*1000);
  236. let ui = cc.instantiate(cc.loader.getRes('prefab/ui_account',cc.Prefab));
  237. ui.scaleX *= this.gameViewSize.width/cc.view.getDesignResolutionSize().width;//适配游戏可视域的宽度
  238. let account:Account = ui.addComponent(Account);
  239. this.background.addChild(ui);
  240. account.showResult(win);
  241. account.showScore(this.score);
  242. }
  243. }
  244. /**教学模式类 */
  245. class TeachMode {
  246. private gameViewSize:cc.Size;
  247. private background:cc.Node;
  248. private coach:Coach;
  249. private player:Player;
  250. private fingerInitPos:cc.Vec2 = cc.v2(0,-250);
  251. private finger:cc.Node;
  252. private label:cc.Label;
  253. private circleMask:cc.Node;
  254. private blackScreen:cc.Node;
  255. constructor(gameViewSize:cc.Size,background:cc.Node,coach:Coach,player:Player){
  256. this.gameViewSize = gameViewSize;
  257. this.background = background;
  258. this.coach = coach;
  259. this.player = player;
  260. //创建圆形遮罩
  261. this.circleMask = cc.instantiate(cc.loader.getRes('prefab/circleMask',cc.Prefab));
  262. this.circleMask.zIndex = 1;
  263. this.circleMask.active = false;
  264. this.background.addChild(this.circleMask);
  265. //创建手指节点
  266. this.finger = new cc.Node();
  267. this.finger.zIndex = 2;
  268. this.finger.setAnchorPoint(0,1);
  269. this.finger.setPosition(this.fingerInitPos);
  270. this.finger.addComponent(cc.Sprite).spriteFrame = cc.loader.getRes('texture/finger',cc.SpriteFrame);
  271. this.finger.active = false;
  272. this.background.addChild(this.finger);
  273. //创建文字标签
  274. this.label = new cc.Node().addComponent(cc.Label);
  275. this.label.node.zIndex = 3;
  276. this.label.node.setPosition(0,-400);
  277. this.label.lineHeight = 50;
  278. this.label.horizontalAlign = cc.Label.HorizontalAlign.CENTER;
  279. this.label.node.active = false;
  280. this.background.addChild(this.label.node);
  281. //黑色屏幕
  282. this.blackScreen = Tool.createButtonNode({
  283. width:this.gameViewSize.width,
  284. height:this.gameViewSize.height,
  285. backgroundImage:'texture/white',
  286. transition:cc.Button.Transition.NONE,
  287. color:cc.Color.BLACK,
  288. opacity:0
  289. });
  290. this.blackScreen.zIndex = 4;
  291. this.blackScreen.active = false;
  292. this.background.addChild(this.blackScreen);
  293. }
  294. /**
  295. * 运动手指
  296. * @param isClick 是则为点击模式,否则为运动模式,运动模式运动偏移量
  297. * @param offset 运动偏移量
  298. */
  299. private runFinger(isClick:boolean,offset?:cc.Vec2):void{
  300. this.finger.active = true;
  301. this.finger.stopAllActions();
  302. if(isClick){
  303. this.finger.setPosition(-10,-530);
  304. this.finger.runAction(cc.repeatForever(cc.sequence(
  305. cc.fadeIn(0.3),
  306. cc.scaleTo(0.6,0.8),
  307. cc.scaleTo(0.6,1),
  308. cc.fadeOut(0.3),
  309. )));
  310. }else{
  311. this.finger.setPosition(this.fingerInitPos);
  312. this.finger.runAction(cc.repeatForever(cc.sequence(cc.fadeIn(0.3),
  313. cc.moveBy(0.6,cc.v2(offset)),
  314. cc.fadeOut(0.3),
  315. cc.callFunc(()=>{
  316. this.finger.setPosition(this.fingerInitPos);
  317. },this))));
  318. }
  319. }
  320. /**
  321. * 设置标签
  322. * @param text 文本
  323. * @param color 颜色
  324. */
  325. public setLabel(text:string,color?:cc.Color){
  326. this.label.string = text;
  327. this.label.node.color = color?color:cc.Color.WHITE;
  328. this.label.node.active = true;
  329. }
  330. /**开始教学 */
  331. public start():void{
  332. //创建标题
  333. let node = new cc.Node();
  334. node.addComponent(cc.Sprite).spriteFrame = cc.loader.getRes('texture/font_teach1',cc.SpriteFrame);
  335. node.setScale(1.5);
  336. node.setPosition(0,250);
  337. this.background.addChild(node);
  338. node.runAction(cc.sequence(cc.scaleBy(2,0.8).easing(cc.easeBackInOut()),cc.callFunc(()=>{
  339. node.destroy();
  340. this.teachRightJay();
  341. },this)));
  342. }
  343. /**左拳教学 */
  344. private teachRightJay():void{
  345. this.runFinger(false,cc.v2(-200,200))
  346. this.setLabel('向左上方滑动\n打出右勾拳');
  347. this.player.node.on(Role.EventType_DoAttack,this.rightJayFinish,this);
  348. }
  349. /**左拳完成 */
  350. private rightJayFinish():void{
  351. if(this.player.direction==-1){
  352. this.player.node.off(Role.EventType_DoAttack,this.rightJayFinish,this);
  353. this.finger.active = false;
  354. this.label.node.active = false;
  355. setTimeout(this.teachLeftJay.bind(this),500);
  356. }
  357. }
  358. /**右拳教学 */
  359. private teachLeftJay():void{
  360. this.runFinger(false,cc.v2(200,200));
  361. this.setLabel('向右上方滑动\n打出左勾拳');
  362. this.player.node.on(Role.EventType_DoAttack,this.leftJayFinish,this);
  363. }
  364. /**右拳完成 */
  365. private leftJayFinish():void{
  366. if(this.player.direction==1){
  367. this.player.node.off(Role.EventType_DoAttack,this.leftJayFinish,this);
  368. this.finger.active = false;
  369. this.label.node.active = false;
  370. setTimeout(this.createLeftAttackMark.bind(this),500);
  371. }
  372. }
  373. /**对手发出左攻击标志 */
  374. private createLeftAttackMark():void{
  375. this.coach.createMark(1,false,()=>{
  376. this.circleMask.setPosition(this.coach.mark.position);
  377. this.circleMask.active = true;
  378. this.teachRightDodge();
  379. });
  380. }
  381. /**右躲避教学 */
  382. private teachRightDodge():void{
  383. this.runFinger(false,cc.v2(200,-200));
  384. this.setLabel('向右下方滑动\n发起右躲避');
  385. this.player.node.on(Role.EventType_DoDodge,this.rightDodgeFinish,this);
  386. }
  387. /**右躲避完成 */
  388. public rightDodgeFinish():void{
  389. if(this.player.direction==1){
  390. this.player.node.off(Role.EventType_DoDodge,this.rightDodgeFinish,this);
  391. this.coach.mark.destroy();
  392. this.circleMask.active = false;
  393. this.finger.active = false;
  394. this.coach.leftJay();
  395. this.setLabel('记住:\n对方的攻击信号\n是预判的关键',cc.Color.YELLOW);
  396. setTimeout(this.createRightAttackMark.bind(this),3000);
  397. }
  398. }
  399. /**对手发出右攻击标志 */
  400. public createRightAttackMark():void{
  401. this.coach.createMark(-1,false,()=>{
  402. this.circleMask.setPosition(this.coach.mark.position);
  403. this.circleMask.active = true;
  404. this.teachLeftDodge();
  405. });
  406. }
  407. /**左躲避教学 */
  408. public teachLeftDodge():void{
  409. this.runFinger(false,cc.v2(-200,-200));
  410. this.setLabel('向左下方滑动\n发起左躲避');
  411. this.player.node.on(Role.EventType_DoDodge,this.leftDodgeFinish,this);
  412. }
  413. /**左躲避完成 */
  414. public leftDodgeFinish():void{
  415. if(this.player.direction==-1){
  416. this.player.node.off(Role.EventType_DoDodge,this.leftDodgeFinish,this);
  417. this.coach.mark.destroy();
  418. this.circleMask.active = false;
  419. this.finger.active = false;
  420. this.coach.rightJay();
  421. this.setLabel('记住:\n躲避成功可恢复大量的耐力\n是持续战斗的关键',cc.Color.YELLOW);
  422. setTimeout(this.teachDefense.bind(this),3000);
  423. }
  424. }
  425. /**防御教学 */
  426. public teachDefense():void{
  427. this.runFinger(true);
  428. this.setLabel('点击此处按钮\n发起防御');
  429. this.player.node.on(Role.EventType_DoDefense,this.defenseFinish,this);
  430. }
  431. /**防御完成 */
  432. public defenseFinish():void{
  433. this.player.node.off(Role.EventType_DoDefense,this.defenseFinish,this);
  434. this.finger.destroy();
  435. this.coach.rightJay();
  436. this.setLabel('记住:\n防御成功可以恢复少量血量\n是续航的关键',cc.Color.YELLOW);
  437. setTimeout(this.end.bind(this),3000);
  438. }
  439. /**结束教学 */
  440. public end():void{
  441. this.label.node.destroy();
  442. //创建标题
  443. let node = new cc.Node();
  444. node.addComponent(cc.Sprite).spriteFrame = cc.loader.getRes('texture/font_teach2',cc.SpriteFrame);
  445. node.setScale(1.5);
  446. node.setPosition(0,250);
  447. this.background.addChild(node);
  448. node.runAction(cc.sequence(cc.scaleBy(2,0.8).easing(cc.easeBackInOut()),cc.callFunc(()=>{
  449. node.destroy();
  450. this.blackScreen.active = true;
  451. //缓动
  452. let tween = new cc.Tween();
  453. tween.target(this.background);
  454. tween.to(1,{opacity:255},null);
  455. tween.then(cc.callFunc(()=>{
  456. //完成新手教程,缓存数据中记录为老玩家
  457. cc.sys.localStorage.setItem('isOldPlayer','true');
  458. window.gameMgr.teachMode = null;//回收教学模式
  459. //正式开始游戏
  460. this.background.removeAllChildren(true);
  461. window.gameMgr.startGame();
  462. },this));
  463. tween.start();
  464. },this)));
  465. }
  466. }