最终效果:
做贪吃蛇游戏需要Html5,部分Css美化,重要的是JavaScript的应用,因为我们主要是运用Html5的Canvas标签来打造游戏的,所以还是在JavaScript上的笔墨较多
首先搭建好框架:
snake
然后在javascript代码区创建画布Dom对象:
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
创建蛇对象:
var snake = {
head : { x : 15 * 3, y : 0 },
body : [{ x : 15 * 2, y : 0 },{ x : 15 * 1, y : 0 },{ x : 0, y : 0 }],
speed : 100,
direction: "right",
};
注意点:蛇对象中的body是一个数组,数组内的元素是代表蛇每个节在画布上的X坐标和Y坐标,snake.body[0]为最靠近head的节,依此类推。。
描绘蛇:
function drawSnake(){
ctx.clearRect( 0, 0, 450, 450 );
var headImg = new Image();
var headSrc = "./snake_head_min_" + snake.direction +".png";/*存贮蛇图片的位置,用于动态改变head的图片位置*/
headImg.src= headSrc;
ctx.drawImage(headImg, snake.head.x, snake.head.y );
for( var i = 0; i <= snake.body.length - 1; i++){
var cell = new Image();
cell.src = "./snake_body_min.png";
ctx.drawImage(cell, snake.body[i].x, snake.body[i].y );
}
}
注意点:
1.每次描绘蛇之前都需要将原有的图画清空------ ctx.clearRect( 0, 0, 450, 450); clearRect()用法详见:HTML5 canvas clearRect() 方法;
2.这里我采用的不是填充矩形的方法来实现画蛇,而是采用描绘图像的方法: 用法详见:HTML 5
1)创建图像:var Img = new Image();
2)图像位置:Img.src="./img.png";
3)开始描绘:ctx.drawImage( Img, 0, 0);后两个参数表示的是描绘图片的x坐标的y坐标;
在这里我采用了自己制作的图片,注意要调整图片的大小(为展示,此处显示大图):
body head
因为蛇头有方向:所以对于head我们有四张图片:
创建食物对象:
var food = {
x : 300,
y : 150,
};
x , y 代表食物在画布的x坐标和y位置。
描绘食物:
function drawFood(){
if(IsEat()){
food.x = parseInt(Math.random() * 28) * 15;
food.y = parseInt(Math.random() * 28) * 15;
}
var foodImg = new Image();
foodImg.src="./apple_min.png";
ctx.drawImage(foodImg, food.x, food.y );
}
function drawFood(){
if(IsEat()){
food.x = parseInt(Math.random() * 28) * 15;
food.y = parseInt(Math.random() * 28) * 15;
}
var foodImg = new Image();
foodImg.src="./apple_min.png";
ctx.drawImage(foodImg, food.x, food.y );
}
注意点:
1.关于获取随机数:Math.random();该函数返回一个区间为(0, 1 )的随机数;
2.此处我们将随机数乘以28以放大随机数的区间为(0, 28 ),总共的格子数为30 * 30 个 即450 / 15 = 30;
3.我们将其随机数的区间转化为整数:即1,2,3,4,。。。,27,
4.当food 被蛇吃的时候(snake.head的坐标与食物的坐标相同的时候),我们要随机在生成新的食物坐标,此处不考虑食物生成的坐标与蛇的身体有相同(食物生成在了蛇的body上)
判断食物是否被吃:
function IsEat(){
if( snake.head.x == food.x && snake.head.y == food.y){
snake.body[snake.body.length] = { x : 0, y : 0};
return 1;
}
return 0;
}
注意点:
1.此处用了if判断语句,且判断的表达式需满足 蛇的头的坐标与食物的坐标相同(x坐标和y坐标);
2.为了在描绘食物的方法(drawFood();)里更好的判断,我们设置返回值 1 代表被吃,0代表未被吃;
3.食物被吃之后应该生成一个新的节(此处默认生成的节懂得x坐标和y坐标都为0(这个不要紧)在蛇移动的时候会自动改变该值)
snake.body[snake.body.length] = { x : 0, y : 0};
开始重头大戏----移动蛇:
首先移动蛇我们需要的是:不断地描绘图像,并且不断的更新蛇的头的身体各节的坐标:
代码上:
function moveSnake(){
for( var i = snake.body.length - 1; i > 0 ; i-- ){
snake.body[i].x = snake.body[i - 1].x;
snake.body[i].y = snake.body[i - 1].y;
}
snake.body[0].x = snake.head.x;
snake.body[0].y = snake.head.y;
switch( snake.direction ){
case "right":{
snake.head.x = snake.head.x + 15;
break;
}
case "left":{
snake.head.x = snake.head.x - 15;
break;
}
case "up":{
snake.head.y = snake.head.y - 15;
break;
}
case "down":{
snake.head.y = snake.head.y + 15;
break;
}
}
drawSnake();
drawFood();
IsGameover();
setTimeout( 'moveSnake()', snake.speed );
}
注意点:
1.为了达到更新蛇的头和蛇的身体各节坐标的目标,我们的想法应该是:较后的节继承较前的节的坐标;所以就有for循环:
for( var i = snake.body.length - 1; i > 0 ; i-- ){
snake.body[i].x = snake.body[i - 1].x;
snake.body[i].y = snake.body[i - 1].y;
}
snake.body[0].x = snake.head.x;
snake.body[0].y = snake.head.y;
for( var i = snake.body.length - 1; i > 0 ; i-- ){
snake.body[i].x = snake.body[i - 1].x;
snake.body[i].y = snake.body[i - 1].y;
}
snake.body[0].x = snake.head.x;
snake.body[0].y = snake.head.y;
最靠近头的节将继承头的坐标。
2.针对头的坐标更新我们根据蛇的方向(snake.direction)来进行判断:
switch( snake.direction ){}
3.在移动蛇的时候,我们需要不断的画蛇,不断的画食物,不断的判断是否结束游戏,并且我们需要不断的调用自己这个函数;
更新时间我们用setTimeout();用法详见:HTML DOM setTimeout() 方法
判断GameOver:
判断游戏结束有两个标准:
1.碰壁,游戏结束
2.吃着自己,游戏结束
代码上:
function IsGameover(){
if(snake.head.x == game.width && snake.direction == 'right'){
alert("GameOver!");
}
if(snake.head.x == -15 && snake.direction == 'left'){
alert("GameOver!");
}
if(snake.head.y == game.height && snake.direction == 'down'){
alert("GameOver!");
}
if(snake.head.y == -15 && snake.direction == 'up'){
alert("GameOver!");
}
for( var i = 0; i < snake.body.length; i++ ){
if( snake.head.x == snake.body[i].x && snake.head.y == snake.body[i].y){
alert("GameOver!");
}
}
}
注意点:
1.四个if判断语句用于判断碰壁:!!满足条件为 坐标 和 蛇的移动方向(例如 蛇的head的x坐标为0,方向向上 =》 碰壁)
2.for循环语句:对每个body的节判断其坐标是否与head的坐标重合(重合即代表 蛇头吃到自己的身体了)
监听键盘输入:
document.onkeydown = function(e){
var code = e.keyCode;
switch(code){
case 38:{
if( snake.direction != 'down'){
snake.direction='up';
}
break;
}
case 39:{
if( snake.direction != 'left'){
snake.direction='right';
}
break;
}
case 40:{
if( snake.direction != 'up'){
snake.direction='down';
}
break;
}
case 37:{
if( snake.direction != 'right'){
snake.direction='left';
}
break;
}
default:break;
}
}
注意点:
1.html Dom document对象的onkeydown事件后的函数需要引入参数(e)
2.对该事件(event)的键盘值(keyCode)进行判断然后改变蛇的方向--snake.direction;
该游戏的制作就完成了,当然我们也可以把它可以做的更好。
最后上完整代码:
snake
图片资源:
本文中的超链接指向W3school