|
@@ -0,0 +1,450 @@
|
|
|
+import PlaySoundManager from '../Manager/core/PlaySoundManager';
|
|
|
+import CCUtils from '../Utiles/CCUtils';
|
|
|
+import Utiles from '../Utiles/Utiles';
|
|
|
+
|
|
|
+/** @type {*} */
|
|
|
+const { ccclass, property } = cc._decorator;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 游戏类型
|
|
|
+ */
|
|
|
+export enum GameType {
|
|
|
+ /** 节奏练习 */
|
|
|
+ Rhythmexercises = 1,
|
|
|
+ /** 节奏大师 */
|
|
|
+ RhythmMaster = 2,
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 游戏状态
|
|
|
+ *
|
|
|
+ * @export
|
|
|
+ * @enum {number}
|
|
|
+ */
|
|
|
+export enum GameStatus {
|
|
|
+ /** 游戏未开始 */
|
|
|
+ GameNotStart = 1,
|
|
|
+ /** 游戏开始 */
|
|
|
+ GameStart = 2,
|
|
|
+ /** 游戏结束 */
|
|
|
+ GameOver = 3,
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 游戏核心逻辑
|
|
|
+ *
|
|
|
+ * @export
|
|
|
+ * @class GameMain
|
|
|
+ * @extends {cc.Component}
|
|
|
+ */
|
|
|
+@ccclass
|
|
|
+export default class GameMain extends cc.Component {
|
|
|
+ @property(cc.Node)
|
|
|
+ private ball: cc.Node = null;
|
|
|
+ /** 移动速度 */
|
|
|
+ private speed: number = 800;
|
|
|
+ /** 当前背景 */
|
|
|
+ private curBg: cc.Node = null;
|
|
|
+ /** 监听触摸层 */
|
|
|
+ private touchLayer: cc.Node = null;
|
|
|
+
|
|
|
+ private noteNodes: cc.Node[] = [];
|
|
|
+
|
|
|
+ private noteIndex: number = 0;
|
|
|
+
|
|
|
+ private createIndex: number = 0;
|
|
|
+
|
|
|
+ /** 音符持续时间 */
|
|
|
+ private songTimes: Array<number> = [];
|
|
|
+
|
|
|
+ private sunTime: number = 0;
|
|
|
+
|
|
|
+ private curClip: cc.AudioClip = null;
|
|
|
+
|
|
|
+ private errorScope: number = 400;
|
|
|
+
|
|
|
+ public notePool: any = null;
|
|
|
+
|
|
|
+ public recycelIndex: number = 0;
|
|
|
+
|
|
|
+ public mapLayer: cc.Node = null;
|
|
|
+
|
|
|
+ public gameIsOver: boolean = false;
|
|
|
+ // LIFE-CYCLE CALLBACKS:
|
|
|
+ /** 飘分 */
|
|
|
+ public scoreLabel: cc.Node = null;
|
|
|
+ public sumScoreLabel: cc.Node = null;
|
|
|
+
|
|
|
+ public addScoreNum: number = 20;
|
|
|
+ public sumScoreNum: number = 0;
|
|
|
+
|
|
|
+ public failNode: cc.Node = null;
|
|
|
+
|
|
|
+ public gameStartBtn: cc.Node= null;
|
|
|
+
|
|
|
+ onLoad() {
|
|
|
+ this.createNotes();
|
|
|
+ this.node.opacity = 50;
|
|
|
+ this.touchLayer = CCUtils.findChild(this.node, 'touchLayer');
|
|
|
+ this.scoreLabel = CCUtils.findChild(this.node, 'Camera/scoreLabel');
|
|
|
+ this.scoreLabel.getComponent(cc.Label).string = `+${this.addScoreNum}`;
|
|
|
+ this.sumScoreLabel = CCUtils.findChild(this.node, 'Camera/sumScoreLabel');
|
|
|
+ this.sumScoreLabel.getComponent(cc.Label).string = this.sumScoreNum + '';
|
|
|
+ this.failNode = CCUtils.findChild(this.node, 'failNode');
|
|
|
+ this.failNode.active = false;
|
|
|
+ this.touchLayer.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan.bind(this), this);
|
|
|
+ this.touchLayer.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMoved.bind(this), this);
|
|
|
+ this.touchLayer.on(cc.Node.EventType.TOUCH_END, this.onTouchEnded.bind(this), this);
|
|
|
+ this.touchLayer.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnded.bind(this), this);
|
|
|
+ this.gameStartBtn = CCUtils.findChild(this.node, 'lockGame/gameStart');
|
|
|
+
|
|
|
+ cc.tween(this.node).to(0.8, { opacity: 255 }).start();
|
|
|
+ this.gameStartBtn.y = 1200;
|
|
|
+ this.gameStartBtn.scale = 0.8;
|
|
|
+ cc.tween(this.gameStartBtn).to(0.4, { y: -70, scale: 1 }).to(0.1, { y: 10, scale: 0.9 }).to(0.12, { y: 0 , scale: 1}).start();
|
|
|
+ }
|
|
|
+
|
|
|
+ protected onEnable(): void {
|
|
|
+ this.curBg = CCUtils.findChild(this.node, 'Camera/bgNode/bg1');
|
|
|
+ this.mapLayer = CCUtils.findChild(this.node, 'mapLayer');
|
|
|
+ this.songTimes = Utiles.getSongTimes();
|
|
|
+ PlaySoundManager.getInstance().loadSound('sound/gameSong/0', (clip: any): void => {
|
|
|
+ this.curClip = clip;
|
|
|
+ console.log('this.curClip: ', this.curClip);
|
|
|
+ this.gameStartBtn.on('click', this.gameStart, this);
|
|
|
+ });
|
|
|
+ this.resetGameData();
|
|
|
+ this.addOnEvent();
|
|
|
+ this.resetBallState();
|
|
|
+ this.initNotePos();
|
|
|
+ }
|
|
|
+
|
|
|
+ protected onDisable(): void {
|
|
|
+ this.gameStartBtn.off('click', this.gameStart, this);
|
|
|
+ this.clearNotes();
|
|
|
+ }
|
|
|
+
|
|
|
+ public updateScore(): void {
|
|
|
+ this.sumScoreNum += this.addScoreNum;
|
|
|
+ this.sumScoreLabel.getComponent(cc.Label).string = this.sumScoreNum + '';
|
|
|
+ }
|
|
|
+
|
|
|
+ public resetGameData(): void {
|
|
|
+ this.mapLayer.y = -186.621;
|
|
|
+ this.sunTime = 0;
|
|
|
+ this.noteIndex = 0;
|
|
|
+ this.createIndex = 0;
|
|
|
+ this.recycelIndex = 0;
|
|
|
+ this.gameIsOver = false;
|
|
|
+ this.addScoreNum = 20;
|
|
|
+ this.sumScoreNum = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public clearNotes(): void {
|
|
|
+ for (let i = 0; i < this.noteNodes.length; i++) {
|
|
|
+ this.removeNote(this.noteNodes[i]);
|
|
|
+ }
|
|
|
+ this.noteNodes = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ public addOnEvent(): void {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开始游戏
|
|
|
+ *
|
|
|
+ * @memberof GameMain
|
|
|
+ */
|
|
|
+ public gameStart(): void {
|
|
|
+ console.log('this.songTimes.length: ', this.songTimes.length);
|
|
|
+ this.musicPlay();
|
|
|
+ this.schedule(this.updateGame);
|
|
|
+ CCUtils.findChild(this.node, 'lockGame').active = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public musicPlay(): void {
|
|
|
+ PlaySoundManager.getInstance().playSound(this.curClip, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ public updateGame(dt): void {
|
|
|
+ const offY: number = this.speed * dt;
|
|
|
+ this.ball.parent.y += offY;
|
|
|
+ if (this.noteIndex <= this.songTimes.length - 1) {
|
|
|
+ if (this.noteNodes[this.noteIndex] != null) {
|
|
|
+ // console.log('====this.noteIndex===: ', this.noteIndex);
|
|
|
+ const worldPos1: cc.Vec2 = this.ball.parent.convertToWorldSpaceAR(cc.Vec2.ZERO);
|
|
|
+ const worldPos2: cc.Vec2 = this.noteNodes[this.noteIndex].convertToWorldSpaceAR(cc.Vec2.ZERO);
|
|
|
+ // console.log('worldPos2: ', worldPos2.y);
|
|
|
+ if (worldPos1.y >= worldPos2.y + this.errorScope) {
|
|
|
+ // console.log('===updateGame: ', this.noteIndex);
|
|
|
+ // this.noteNodes[this.noteIndex]['flag'] = false;
|
|
|
+ this.noteIndex++;
|
|
|
+ console.log('=============+++++');
|
|
|
+ // alert('游戏结束');
|
|
|
+ this.updateNotePos();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.gameOver();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public createNotes(): void {
|
|
|
+ // 创建对象池
|
|
|
+ const initNumber: number = 20;
|
|
|
+ this.notePool = new cc.NodePool();
|
|
|
+ for (let i: number = 0; i < initNumber; ++i) {
|
|
|
+ const enemy: any = cc.instantiate(CCUtils.findChild(this.node, 'note'));
|
|
|
+ this.notePool.put(enemy);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化音符坐标
|
|
|
+ *
|
|
|
+ * @memberof GameMain
|
|
|
+ */
|
|
|
+ public initNotePos(): void {
|
|
|
+ for (let i: number = 0; i < 20; i++) {
|
|
|
+ this.addNote();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public addNote(): void {
|
|
|
+ if (!this.songTimes) return;
|
|
|
+ const node: cc.Node = this.getNote();
|
|
|
+ node.active = true;
|
|
|
+ node.parent = this.mapLayer;
|
|
|
+ this.sunTime += this.songTimes[this.createIndex];
|
|
|
+ // 转弯
|
|
|
+ if (this.noteNodes.length == 0 || (this.noteNodes[this.noteNodes.length - 1].x = 10)) {
|
|
|
+ node.x = -10;
|
|
|
+ } else {
|
|
|
+ node.x = 10;
|
|
|
+ }
|
|
|
+ CCUtils.findChild(node, 'noteSp').getComponent(sp.Skeleton).setAnimation(0, '01', false);
|
|
|
+ const num: number = Number(this.sunTime.toFixed(2));
|
|
|
+ node.y = this.speed * num;
|
|
|
+ this.noteNodes.push(node);
|
|
|
+ this.createIndex++;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 移除音符节点
|
|
|
+ *
|
|
|
+ * @memberof RhythmexercisesDriver
|
|
|
+ */
|
|
|
+ private removeNote(node: cc.Node): void {
|
|
|
+ // console.log('node;', node);
|
|
|
+ if (node == null) return;
|
|
|
+ CCUtils.findChild(node, 'noteSp').getComponent(sp.Skeleton).setAnimation(0, '02', false);
|
|
|
+ node.active = false;
|
|
|
+ this.notePool.put(node);
|
|
|
+ }
|
|
|
+
|
|
|
+ public updateNotePos(): void {
|
|
|
+ if (this.noteIndex > 10) {
|
|
|
+ if (this.createIndex >= this.songTimes.length) {
|
|
|
+ console.warn('音符生成完毕', this.createIndex, ' this.songTimes.length: ', this.songTimes.length);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.removeNote(this.noteNodes[this.recycelIndex++]);
|
|
|
+ this.addNote();
|
|
|
+ }
|
|
|
+
|
|
|
+ // this.noteIndex
|
|
|
+ // for (let i: number = 0; i < this.noteNodes.length; i++) {
|
|
|
+ // // 找到已经过去的音符
|
|
|
+ // // console.log('flag', this.noteNodes[i]['flag']);
|
|
|
+ // const node: cc.Node = this.getNote();
|
|
|
+ // if (!node['flag']) {
|
|
|
+ // node['flag'] = true;
|
|
|
+ // CCUtils.findChild(node, 'noteSp').getComponent(sp.Skeleton).setAnimation(0, '01', false);
|
|
|
+ // this.sunTime += this.songTimes[this.createIndex];
|
|
|
+ // const num: number = Number(this.sunTime.toFixed(2));
|
|
|
+ // node.y = this.speed * num;
|
|
|
+ // // ++this.createIndex;
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化球
|
|
|
+ *
|
|
|
+ * @memberof GameMain
|
|
|
+ */
|
|
|
+ public resetBallState(): void {
|
|
|
+ this.ball.x = -150;
|
|
|
+ this.ball.angle = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 背景管理
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @memberof GameMain
|
|
|
+ */
|
|
|
+ private bgManager(): void {}
|
|
|
+
|
|
|
+ private changeBgColor(): void {
|
|
|
+ this.curBg.stopAllActions();
|
|
|
+ const c: cc.Color = cc.color(Utiles.random(50, 255), Utiles.random(50, 255), Utiles.random(50, 255));
|
|
|
+ cc.tween(this.curBg).delay(0.3).to(0.5, { color: c }).start();
|
|
|
+ CCUtils.findChild(this.ball.parent, 'changeBg').getComponent(sp.Skeleton).setAnimation(0, '01', false);
|
|
|
+ }
|
|
|
+ private changeBallDir(): void {
|
|
|
+ this.ball.stopAllActions();
|
|
|
+ this.ball.angle = 0;
|
|
|
+ const time: number = 0.05;
|
|
|
+ if (this.ball.x > 0) {
|
|
|
+ this.ball;
|
|
|
+ cc.tween(this.ball).to(time, { angle: -30, x: -150 }).to(time, { angle: 0 }).start();
|
|
|
+ // this.ball.x = -150;
|
|
|
+ } else {
|
|
|
+ cc.tween(this.ball).to(time, { angle: 30, x: 150 }).to(time, { angle: 0 }).start();
|
|
|
+ // this.ball.x = 150;
|
|
|
+ }
|
|
|
+ console.log('changeBallDir: ', this.ball.x);
|
|
|
+ }
|
|
|
+
|
|
|
+ private playNoteAnim(): void {
|
|
|
+ // this.noteNodes[this.noteIndex]['flag'] = false;
|
|
|
+ CCUtils.findChild(this.noteNodes[this.noteIndex], 'noteSp').getComponent(sp.Skeleton).setAnimation(0, '02', false);
|
|
|
+ this.scoreLabelAction();
|
|
|
+ this.noteIndex++;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 节奏判定
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ private onTouchBegan(): void {
|
|
|
+ if (this.gameIsOver) {
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ // 判断是否碰到音符
|
|
|
+ if (this.noteNodes[this.noteIndex] != null) {
|
|
|
+ const worldPos1: cc.Vec2 = this.ball.parent.convertToWorldSpaceAR(cc.Vec2.ZERO);
|
|
|
+ const worldPos2: cc.Vec2 = this.noteNodes[this.noteIndex].convertToWorldSpaceAR(cc.Vec2.ZERO);
|
|
|
+ this.changeBallDir();
|
|
|
+ console.log('this.noteIndex: ', this.noteIndex);
|
|
|
+ // 判断是否在音符范围内,在的话,再播放动画
|
|
|
+ if (worldPos1.y >= worldPos2.y - 120 && worldPos1.y <= worldPos2.y + this.errorScope) {
|
|
|
+ this.changeBgColor();
|
|
|
+ this.playNoteAnim();
|
|
|
+
|
|
|
+ this.updateNotePos();
|
|
|
+ this.updateScore();
|
|
|
+ } else {
|
|
|
+ this.gameOver();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.gameOver();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private onTouchMoved(): void {}
|
|
|
+
|
|
|
+ private onTouchEnded(): void {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 游戏结束
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @memberof GameMain
|
|
|
+ */
|
|
|
+ private gameOver(): void {
|
|
|
+ console.log('======debug===gameOver');
|
|
|
+ CCUtils.findChild(this.node, 'Camera').setPosition(cc.v2(0, 0));
|
|
|
+ this.gameFail();
|
|
|
+ cc.audioEngine.stopAllEffects();
|
|
|
+ CCUtils.findChild(this.node, 'lockGame').active = true;
|
|
|
+ this.unschedule(this.updateGame);
|
|
|
+ this.resetGameData();
|
|
|
+ this.resetBallState();
|
|
|
+ this.clearNotes();
|
|
|
+ this.initNotePos();
|
|
|
+ }
|
|
|
+
|
|
|
+ private gameFail(): void {
|
|
|
+ this.failNode.active = true;
|
|
|
+ this.playLoadingTextEffect(CCUtils.findChild(this.failNode, 'failLabel'), 0.08, ' FAIL \n 游戏结束');
|
|
|
+ }
|
|
|
+
|
|
|
+ private playLoadingTextEffect(node: cc.Node, t: number, str: string): void {
|
|
|
+ let strTemp: string = '';
|
|
|
+
|
|
|
+ for (let i: number = 0; i < str.length; i++) {
|
|
|
+ cc.tween(node)
|
|
|
+ .delay(t * i)
|
|
|
+ .call((): void => {
|
|
|
+ strTemp += str[i];
|
|
|
+ node.getComponent(cc.Label).string = strTemp;
|
|
|
+ })
|
|
|
+ .start();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 再来一次
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @memberof GameMain
|
|
|
+ */
|
|
|
+ private againGame(): void {
|
|
|
+ this.resetsGame();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重置游戏数据
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @memberof GameMain
|
|
|
+ */
|
|
|
+ private resetsGame(): void {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从对象池获取音符
|
|
|
+ *
|
|
|
+ * @memberof RhythmexercisesNote
|
|
|
+ */
|
|
|
+ public getNote(): cc.Node {
|
|
|
+ let note: cc.Node = null;
|
|
|
+ if (this.notePool.size() > 0) {
|
|
|
+ note = this.notePool.get();
|
|
|
+ } else {
|
|
|
+ note = cc.instantiate(CCUtils.findChild(this.node, 'note'));
|
|
|
+ }
|
|
|
+
|
|
|
+ return note;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 回收到对象池
|
|
|
+ *
|
|
|
+ * @memberof RhythmexercisesNote
|
|
|
+ */
|
|
|
+ public recycleNote(node: cc.Node): void {
|
|
|
+ if (node == null) return;
|
|
|
+ this.notePool.put(node);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清空对象池
|
|
|
+ *
|
|
|
+ * @memberof RhythmexercisesNote
|
|
|
+ */
|
|
|
+ public clearPool(): void {
|
|
|
+ this.notePool.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ public scoreLabelAction(): void {
|
|
|
+ this.scoreLabel.stopAllActions();
|
|
|
+ this.scoreLabel.active = true;
|
|
|
+ this.scoreLabel.opacity = 255;
|
|
|
+ this.scoreLabel.setPosition(cc.v2(0, -200));
|
|
|
+ this.scoreLabel.scale = 1;
|
|
|
+ cc.tween(this.scoreLabel).to(0.3, { scale: 1.5, x: 135, y: -140 }).to(0.2, { opacity: 0 }).start();
|
|
|
+ }
|
|
|
+}
|