两块地板循环滚动,没啥好说的。
核心代码:
this.groundNode[0].x += Constant.GROUND_VX;
this.groundNode[1].x += Constant.GROUND_VX;
if (this.groundNode[0].x + this._width/2 < - this._size.width/2) {
this.groundNode[0].x = this.groundNode[1].x + this._width - 5;
}
if (this.groundNode[1].x + this._width/2 < - this._size.width/2) {
this.groundNode[1].x = this.groundNode[0].x + this._width - 5;
}
坠落的效果需要让小鸟在Y轴负方向有一个加速度,即单位时间类的偏移量还有一个增量。弹跳只需要让原本为负的偏移值变为正。
在onLoad方法中:
this.velocity = 0; //初始下降速度为零
在onDrop方法中:
this.node.y += this.velocity ;
this.velocity -= this.gravity;
管道的定位需要五个参数
pipeMaxOffsetY //Y轴最大偏移量
pipeMinGap //管道最小间隙
pipeMaxGap //管道最大间隙
pipeSpawnInterval //管道生成时间间隔
pipeSpawnOffsetX //管道屏幕外生成偏移量
核心代码:
spawnPipes: function() {
// 从管道预制(上端),生成管道实例
var pipeUp = cc.instantiate(this.pipePrefabs[Constant.PIPE_UP]);
// 定义为上端类型
pipeUp.getComponent('Pipe').init(Constant.PIPE_UP);
// 获取管道的高度(上端与上端的相同)
var pipeHeight = pipeUp.getComponent('cc.Sprite').spriteFrame.getRect().height;
// 设置上端管道的横向起始位置(屏幕右端另加一定偏移)
pipeUp.x = this.size.width / 2 + this.pipeSpawnOffsetX;
// 设置上端管道的纵向起始位置(随机取偏移量)
pipeUp.y = Math.floor(Math.random() * this.pipeMaxOffsetY) + pipeHeight/2;
// 下端生成逻辑基本与上端相同
var pipeDown = cc.instantiate(this.pipePrefabs[Constant.PIPE_DOWN]);
pipeDown.getComponent('Pipe').init(Constant.PIPE_DOWN);
pipeDown.x = this.size.width / 2 + this.pipeSpawnOffsetX;
// 随机生成上端与下端管道之间的间隙值(pipeMinGap与pipeMaxGap之间)
var pipeGap = Math.floor(Math.random() * (this.pipeMaxGap - this.pipeMinGap)) + this.pipeMinGap + 20;
pipeDown.y = pipeUp.y - pipeGap - pipeHeight;
// 添加管道到pipes节点上
this.pipesNode.addChild(pipeUp);
this.pipesNode.addChild(pipeDown);
// 添加管道到管道数组中
this.pipes.push(pipeUp);
this.pipes.push(pipeDown);
},
// 超出屏幕范围的管道,从数组中移除,并从节点上删除
if ( curPipeNode.x < -(this.size.width/2 + Constant.PIPE_SPAWN_OFFSET_X)) {
this.pipes.splice(i, 1);
this.pipesNode.removeChild(curPipeNode, true);
}
撞地死亡:小鸟包围盒下边界Y坐标与地板上表面Y坐标对比
撞天花板死亡:小鸟包围盒上边界Y坐标与屏幕上边界Y坐标对比
撞管道死亡:小鸟包围盒与管道包围盒坐标碰撞检
核心代码:
// 获取小鸟的包围盒
var birdBox = this.bird.node.getBoundingBox();
// 获取当前管道的包围盒
var pipeBox = curPipeNode.getBoundingBox();
var birdRect = new cc.Rect(birdBox.x, birdBox.y,
birdBox.width, birdBox.height);
var pipeRect = new cc.Rect(pipeBox.x, pipeBox.y,
pipeBox.width, pipeBox.height);
// 根据两个矩形范围判断是否相交
if (pipeRect.intersects(birdRect)) {
this.onGameOver();
return;
}
// 小鸟触地,则死亡
if (this.bird.node.y < this.groundTop || (this.bird.node.y > (this.size.height/2 + this.bird.node.height/2))) {
this.onGameOver();
}
通过管道加分:通关管道判断为小鸟X坐标是否超过管道的X坐标。加分的辅助判断条件,小鸟的通过状态是否及时改变,否则通过以后会不停加分。小鸟通过的管道时只能以上或下其中一根管道的坐标作为参考标准,否则每通过一组管道会加两分。
最高纪录分:游戏开始前显示,如果此前纪录为0则不显示。游戏结束时检查是否有新纪录产生,有则修改,无则保持。
核心代码:
// 获取当前管道对象
var curPipe = curPipeNode.getComponent('Pipe');
// 判断小鸟是否顺利通过管道,是则加分
if ( curPipeNode.x < this.bird.node.x && curPipe.isPassed === false
&& curPipe.type === Constant.PIPE_UP) {
curPipe.isPassed = true;
this.addScore();
}
var Storage = {
getHighScore: function() {
var score = cc.sys.localStorage.getItem('HighScore') || 0;
return parseInt(score);
},
setHighScore: function(score) {
cc.sys.localStorage.setItem('HighScore', score);
}
};
module.exports = Storage;
groundImag: cc.Sprite, //精灵节点类型
groundNode: [cc.Node], //节点数组类型
AnimName: ' ', // 字符串类型
gravity: 0.5 //数值类型
pipesPrefabs: [cc.Prefab], //预制件类型
gameOverText: cc.Label, //文本类型
jumpAudio:{
default: null,
url: cc.AudioClip //音频文件
}
// 关闭菜单节点显示
this.gameMenu.active = false;
// 获取本身的cc.Animation对象,并播放AnimName动画
this.getComponent(cc.Animation).play(this.AnimName);
// 播放弹跳音效
cc.audioEngine.playEffect(this.jumpAudio, false);
this.schedule(this.函数名, 时间间隔) //标准格式
this.schedule(this.spawnPipes, this.pipeSpawnInterval); //示例
// 获取屏幕尺寸
this._size = cc.winSize;
// 获取地板图片的宽度
this._width = this.groundImg.spriteFrame.getRect().width;
var pipeUp = cc.instantiate(this.pipePrefabs[Constant.PIPE_UP]);
this.pipesNode.addChild(pipeUp);
this.pipes.push(pipeUp);
this.pipes.splice(i, 1);
this.pipesNode.removeChild(curPipeNode, true);
const Bird = require('Bird'); //写在当前类的最上面
// 小鸟对象
bird: Bird, //写在propertity中
this.bird.OnDrop(); // 引用类的成员函数调用
//方便参数集中管理
var Constant = cc.Enum({
// 地板移动时间间隔
GROUND_MOVE_INTERVAL: 0.05,
// 单位时间地板移动速度
GROUND_VX: -5,
// 上端管道序号为0
PIPE_UP: 0,
// 下端管道序号为1
PIPE_DOWN: 1,
// 游戏失败文字
GAMEOVER_TXT: 'GAME OVER',
// 最高分文字
HIGHSCORE_TXT: 'HighScore: ',
});
module.exports = Constant; //没有这一句将无法再外部引用
setInputControl: function() {
var self = this;
cc.eventManager.addListener({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
onTouchBegan: self._onTouchBegan.bind(self)
}, self.node);
},
_onTouchBegan: function( touch, event ) {
if ( this.isGameOver === true )
return;
this.bird.onJump();
},
1,游戏运行按钮不可点,无法进入浏览器界面。说明角码存在编译器无法通过的错误,通常会有明显的红叉提示。
2,脚本丢失,说明对应的脚本中存在错误。比如,类型定义是出现书写错误(如将,cc.Node,写成了cc.node)
3,其他组件丢失,通常发生在组件发生纠错修改之后。