完全自己写的贪吃蛇,先试试没有参考别人的方法,自己的思路是怎么样的。
个人觉得贪吃蛇最难的地方是蛇移动,考虑到蛇移动可能转换方向,最好的方式,是把尾部去了截,在头部按当前蛇的方向增加一截,这样看起来蛇就移动了。
具体看注释。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>贪吃蛇</title>
<style>
/*canvas居中*/
#myCanvas {
position: absolute;
margin: auto auto;
top: 5px;
right: 5px;
bottom: 5px;
left: 5px;
border: 1px solid black;
}
</style>
<script>
//启用javascript严格模式,执行效率高
"use strict";
//定义全局变量
var gird_length=10;//每一格的宽度
var rol_gird=60;//横行60格
var col_grid=40;//一列40格
window.addEventListener("load",function(){
var myCanvas=document.getElementById("myCanvas");
var context=myCanvas.getContext("2d");
//设置canvas宽度
myCanvas.width=rol_gird*gird_length;
myCanvas.height=col_grid*gird_length;
//声明 蛇喜欢吃的点心
var food;
//得分
var score=0;
//格子类
function Grid(x,y,dir){
this.color="blue";
this.strokeColor="white";
this.x=x;
this.y=y;
if(dir==undefined){
dir="right";
}
this.dir=dir;
};
//格子显示
Grid.prototype.draw= function(){
context.save();
context.fillStyle=this.color;
context.fillRect(this.x,this.y,gird_length,gird_length);
//加grid边框
context.strokeStyle = this.strokeColor;
context.strokeRect(this.x,this.y,gird_length,gird_length);
context.restore();
};
//格子移动
Grid.prototype.move= function(){
if(this.dir==="up"){
this.y=this.y-gird_length;
}else if(this.dir==="left"){
this.x=this.x-gird_length;
}else if(this.dir==="down"){
this.y=this.y+gird_length;
}else if(this.dir==="right"){
this.x=this.x+gird_length;
}
this.draw(this.x,this.y,gird_length,gird_length);
};
//格子删除
Grid.prototype.remove= function(){
context.clearRect(this.x,this.y,gird_length,gird_length);
delete this;
};
//蛇起始出现位置在(3,3)格
var snake={
x:3,
y:3,
gridArr:new Array(),//包含格子数组
dir:"right"
};
//蛇显示,循环调用格子draw方法
snake.draw= function(){
for(var i=0;i<this.gridArr.length;i++){
this.gridArr[i].draw();
}
};
//蛇移动,本游戏难点所在
//蛇移动,不是每一个格子向前移动,这样的话不好把握蛇转换方向
//正确的方法是,把蛇最后一格去掉,按当前方向生成一个新的格子,加到最前面。
snake.move= function(){
var lastGrid=this.gridArr.shift();//数组的shift方法,删除array[0],并返回对象
lastGrid.remove();
var firstGrid=this.gridArr[this.gridArr.length-1];
//不允许蛇向反方向移动
var dir=this.dir;
if((firstGrid.dir=="up"&&dir=="down")||(firstGrid.dir=="down"&&dir=="up")
||(firstGrid.dir=="right"&&dir=="left")||(firstGrid.dir=="left"&&dir=="right")){
//如果蛇向反方向,则无效,按原来方向
dir=firstGrid.dir;
}
var g = new Grid(firstGrid.x,firstGrid.y,dir);//按蛇的方向生成一个新格子。
g.move();
//记得把lastGrid加到gridArr,如果不记得调试就可以看出来。
//没关系,程序是调出来的
this.gridArr.push(g);
};
//蛇吃了点心。向尾部加一个格子,方向和最后一个一样
snake.eat=function(){
var lastGrid=this.gridArr[0];
var x=lastGrid.x;
var y=lastGrid.y;
//后退一格
if(lastGrid.dir=="up"){
y+=gird_length;
}
else if(lastGrid.dir=="down"){
y-=gird_length;
}else if(lastGrid.dir=="right"){
x+=gird_length;
}else if(lastGrid.dir=="left"){
x-=gird_length;
}
var g = new Grid(x,y,lastGrid.dir);
g.move();
this.gridArr.unshift(g);//Array的unshift方向,向数组0位置插入一个元素
};
//蛇初始五格
snake.init=function(){
for(var i=0;i<5;i++){
this.gridArr.push(new Grid((this.x+i)*gird_length,this.y*gird_length));
}
this.draw();
};
snake.init();
randomFood().draw();
initScore();
//初始化Score
function initScore(){
context.font="20px Georgia";
context.fillText("Score:",3*gird_length,(col_grid-3)*gird_length);
context.fillText(score,9*gird_length,(col_grid-3)*gird_length);
}
//更新分数
function updateScore(){
score+=10;
context.clearRect(9*gird_length,(col_grid-5)*gird_length,3*gird_length,gird_length*2);
context.fillText(score,9*gird_length,(col_grid-3)*gird_length);
}
//检测蛇是否检测蛇是否碰到自己和碰到墙
snake.isDead= function(){
var arr = this.gridArr;
//是否碰到自己
for(var i=0;i<arr.length;i++){
var gi= arr[i];
for(var j=0;j<arr.length;j++){
if(i==j)
continue;
var gj=arr[j];
if(gi.x==gj.x&&gi.y==gj.y)
return true;
}
//是否碰到墙
if(gi.x<=0||gi.y<=0||gi.x>=myCanvas.width-gird_length||gi.y>=myCanvas.height-gird_length)
return true;
}
return false;
};
//定时移动蛇
window.timer=window.setInterval(function(){
snake.move();
//每次移动后,首先检测蛇是否碰到自己和碰到墙
if(snake.isDead()){
//删除定时器
clearInterval(timer);
alert("游戏结束,重新开始,请刷新页面");
}else{
//snake每一次移动后就检测下是否吃到food
if(isCollide()){
updateScore();
snake.eat();
//生成新的foot
randomFood().draw();
}
}
},300);
//按键改变snake方向
window.addEventListener("keydown",function(e){
var keyCode=e.keyCode;
console.log(keyCode);
if(keyCode===87){
snake.dir="up";
}else if(keyCode===68){
snake.dir="right";
}
else if(keyCode===83){
snake.dir="down";
}
else if(keyCode===65){
snake.dir="left";
}
});
//碰撞检测
function isCollide(){
var arr = snake.gridArr;
var x=food.x;
var y=food.y;
for(var i=0;i<arr.length;i++){
var g= arr[i];
if(x===g.x&&y===g.y){
return true;
}
}
return false;
}
//随机生成food;
function randomFood(){
var r=Math.random();
var x=parseInt(r*rol_gird);
var y=parseInt(r*col_grid);
food= new Grid(x*gird_length,y*gird_length);
if(isCollide()){
return randomFood();
}else
return food;
}
});
</script>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>