关卡
本来按照只有一关的思路设计,整个逻辑都是循环,突然我说要加上多个关卡,猛的不适应,考虑了一下,无耻的去看原著的代码,发现原著是使用了一个数组,来定义地图上障碍物的位置与高度,于是完全拷贝过来为己用。
var levelMap=[
[0, 0, 0, 0, 0, 50, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
这个数组就很明确了,把地图分为若干个小块,如果数组为0,表示什么也没有,如果有值,代表障碍物的高度。
然后增加一个变量level代表关数,当方块到右侧胜利时,改为关数增加一,然后调用开局函数,在开局函数增加level的判断,如果当前level不为最大值,则绘制当前关数的地图,然后就可以循环进行游戏了。
function start(){
if(jumpProcess!=null) clearInterval(jumpProcess)
if(moveProcess!=null) clearInterval(moveProcess)
console.log("当前关数",level)
if(level<levelMap.length){
createObstacles(level)
console.log(level)
console.log(levelMap[0])
fallDown()
ctx.clearRect(0,0,650,350);
}
else{
win();
}
}
写绘制地图的动画代码
//画出障碍物
function createObstacles(level){
ctxBg.clearRect(0,0,canvas.width,canvas.height);
for(i=0;i<levelMap[level].length;i++){
if(levelMap[level][i]!=0){
drawObstacle(i,levelMap[level][i])
}
}
}
function drawObstacle(position,height){
var objHeight=0
var thisProcess=setInterval(function(){
if(objHeight<height){
ctxBg.fillRect(objWidth*position,canvas.height-objHeight,objWidth,objHeight);
objHeight+=1
}
else{
clearInterval(thisProcess)
}
},5)
}
以上完成以后,游戏就有了多个关卡。
然后我在碰撞这里犯了糊涂,竟然用了一个switch来把每一关的碰撞条件手动计算出来。工程越搞越多,越想越不对劲,突然才想明白应该怎么做。每一次移动时,都去数组遍历看是否当前坐标有障碍物,但不确定这样做是否有效率,测试时至少不卡顿。
function collision(level){
for(i=0;i<levelMap[level].length;i++){
if(levelMap[level][i]!=0){
if(playerX+playerRadius>=i*objWidth && playerX-playerRadius<=i*objWidth+objWidth && playerY<=levelMap[level][i]+playerRadius){
return true;
}
}
}
}
至此,关卡逻辑均已完成,只剩下设置关卡的具体参数。
手机支持
没有什么特殊操作,只有点击屏幕一种方式,不停的点就可以完成所有操作。
addEventListener('touchstart',touch,false);
addEventListener('touchmove',touch,false);
addEventListener('touchend',touch,false);
function touch (event){
var event = event || window.event;
switch(event.type){
case "touchstart":
keyDown()
//这是控制跳跃、开局、重新开始的函数
break;
case "touchmove":
event.preventDefault();
keyDown()
break;
}
}
计分板等文字信息
在主CANVAS上半部画出死亡数、关数。方块跳到最高处时也仅处于CANVAS的下半部,所以充分利用空间。
在碰撞与过关时绘制信息即可。
总结
简单的加了几关,整体看上去像一个完整的小游戏,可玩性还可以。盯着小bug修复了一下午。
后续游戏可以添加微信朋友圈分享、自定义地图等功能。