在这个网站“http://thecodeplayer.com/walkthrough/html5-game-tutorial-make-a-snake-game-using-html5-canvas-jquery”上看别人用html5+javascript写了一个贪食蛇的游戏,感觉不错,特别是有那个播放功能,可以看着别人一步一步的完成,作者思路清晰,操作犀利(VI党v5),居然这么快的就完成了(想起最开始学C#的时候,我用C#写俄罗斯方块,貌似花了不少时间啊)。。。
最近自己也看了一些关于这方面的书,于是,自己也从头写了一个,花了两三个小时,嘿嘿。不过在试玩的过程中,发现几个问题:1、吃食物的时候,每次都会有一种停顿感;2、很快的按上下左右,即使自身长度只有3个都会出现game over。。。;3、玩着玩着,在准备吃食物的那一刹那,就卡着不动了。。。这种情况偶尔会出现,貌似没规律。。。
于是,为了满足自己那点小小的体验感(现在都把它放在第一位哦~亲~),改了下,顺便写出来吧,不然。。。这个博客。。。太。。。少。。。东东啦。。。
第一个问题,是因为每次吃到食物的时候都是加在末尾,就像这样:
@@@ * :再往前走一步就吃食物了
@@@ :往前走一步,这是没食物的情况
@@@@ :这是吃了食物的情况
吃了食物,由于尾巴没动,于是乎就感觉停顿了一下~
于是,我想改成这样:
@@@ *
@@@@ :吃到食物的时候
貌似这样。。。食物在墙边上的时候就不好了。。。
哎。。。有点小失望,不过没关系,接着看第二个问题,为了验证我对于第二个问题原因的猜想,我加了一些打印信息,包括碰撞前的方向,保存蛇身体的数组,碰撞时蛇身体的数组,这样,很容易就可以发现,原来是头反向了。。。由于按键太快了,蛇原本是往上走的,我按左,蛇头向左走了一步,这个时候我直接按右是不会往右走的,因为在控制方向那里做了判断,不能直接反向,但是,如果我按键很快,按上,蛇还没来得及移动,我又按了右,这个时候时候就可以了。。。于是乎。。。蛇就撞自己身上了。。。
于是,我想了一个很拙劣的方法(因为我觉得应该有其他更好的办法吧),定义了一个变量,每次按了方向键后为false,每次开始蛇要移动的时候为false,只有当蛇移动完了才赋值为true,然后,每次按方向键后,判断一下这个变量,如果为true,则认可这次输入,反正,什么都不做。
第三个问题。。。由于随机性很强,不排除硬件问题。。。
好吧,就这样啦。。。感觉像是一个人在唠唠叨叨。。。
PS:请54注释里那些蹩脚的English吧,那不是给你们看的~
<!DOCTYPE html>
<html>
<head>
<title>Snake</title>
</head>
<body>
<canvas id="canvas" width="600" height="600">
Your browser not support Canvas!
</canvas>
<script type="text/javascript">
var c = document.getElementById('canvas');
var ctx = c.getContext('2d');
// ctx.translate(100,100);
var canvasWidth;
var canvasHeight;
//snake array
var snakeArray;
//snake unit width
var px;
//fps
var cycle;
//setInterval
var gameLoop;
//key
var left = 37;
var up = 38;
var right = 39;
var down = 40;
//direction
var d;
//food
var f;
//score
var score;
//too fast become direction
var flagD;
init();
//init snake
function init(){
canvasWidth = c.width;
canvasHeight = c.height;
snakeArray = [];
px = 20;
cycle = 500/1000;
d = right;
f = {x:-1,y:-1};
score = 0;
flagD = true;
if(typeof gameLoop != 'undefined'){
clearInterval(gameLoop);
}
initSnake(3);
initFood();
play();
}
function play(){
gameLoop = setInterval(function(){
ctx.fillStyle = 'white';
ctx.fillRect(0,0,canvasWidth,canvasHeight);
ctx.strokeStyle = 'black';
ctx.strokeRect(0,0,canvasWidth,canvasHeight);
moveSnake();
//paintFood();
paintSnake(snakeArray);
ctx.fillStyle = 'red';
paintCell(f.x,f.y);
var scoreStr = 'Score:' + score;
ctx.fillText(scoreStr,5,canvasHeight - 5);
},cycle*1000);
}
//init snake
function initSnake(length){
for(var i=length;i>0;i--){
snakeArray.push({x:i,y:0});
}
};
// paintSnake();
function paintSnake(){
ctx.fillStyle = 'blue';
for(var i=0;i<snakeArray.length;i++){
paintCell(snakeArray[i].x,snakeArray[i].y);
}
}
//paint cell
function paintCell(x,y){
ctx.fillRect(x*px,y*px,px-1,px-1);
}
// move snake
function moveSnake(){
flagD = false;
// console.log("move direction:" + d);
// for(var tt in snakeArray){
//
// console.log(tt+":"+snakeArray[tt].x+","+snakeArray[tt].y);
// };
//control direction
var p = {x:snakeArray[0].x,y:snakeArray[0].y};
if(d == left) p.x--;
else if(d == right) p.x++;
else if(d == up) p.y--;
else if(d == down) p.y++;
//eat food
if(p.x == f.x && p.y == f.y){
score++;
initFood();
}else{
snakeArray.pop();
}
//
if(p.x == -1 || p.x == canvasWidth/px || p.y == -1 || p.y == canvasHeight/px
|| checkColliction(p.x,p.y)){
alert(p.x + ":" + p.y);
init();
return;
}
snakeArray.unshift(p);
flagD = true;
}
// check collection
function checkColliction(x,y){
for(var t in snakeArray){
if(x == snakeArray[t].x && y == snakeArray[t].y)
{
// console.log('collection');
// for(var tt in snakeArray){
//
// console.log(tt+":"+snakeArray[tt].x+","+snakeArray[tt].y);
// }
return true;
}
}
return false;
}
//
function initFood(){
var flag = false;
do{
f.x = Math.floor(canvasWidth/px*Math.random());
f.y = Math.floor(canvasHeight/px*Math.random());
for(var t in snakeArray){
if(f.x == snakeArray[t].x && f.y == snakeArray[t].y)
flag = true;
}
}while(flag);
}
//add listin key
window.addEventListener('keydown',function(e){
if(flagD){
if(e.keyCode == left && d != right) d = left;
else if(e.keyCode == right && d != left) d = right;
else if(e.keyCode == up && d!= down) d = up;
else if(e.keyCode == down && d != up) d = down;
flagD = false;
};
});
</script>
</body>
</html>