【Canvas + JavaScript】200行代码贪吃蛇游戏

Cano12358 2014-08-23 06:53:18
加精
以前没有任何的游戏开发经验,这次也是自己摸索着做出来的,肯定有很多地方做的不合适,希望大家指点一下。
展示地址:http://www.tianliantian.com/game/snake/index.htm
把CSS压缩了之后正好200行代码。
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>贪吃蛇</title>
</head>
<body>
<div id="page">
<div id="yard"><canvas id="canvas" height="600px" width="800px"></canvas></div>
<div id="help">
<div id="mark">Mark:<span id="mark_con"></span></div>
<div id="helper">
<table>
<tr>
<td></td>
<td><button onclick="keydown(38);">Up</button></td>
<td></td>
</tr>
<tr>
<td><button onclick="keydown(37);">Left</button></td>
<td><button onclick="keydown(80);" id="pause">Pause</button></td>
<td><button onclick="keydown(39);">Right</button></td>
</tr>
<tr>
<td></td>
<td><button onclick="keydown(40);">Down</button></td>
<td></td>
</tr>
</table><a href="index.htm">Restart</a>
</div>
</div>
</div>
</body>
</html>

CSS(压缩后):
<style type="text/css">
*{margin:0;padding: 0;font-family: "Microsoft YaHei";}
#page{margin-right: auto;margin-left: auto; margin-top: 20px;height: 600px; width: 980px; }
#yard{ width: 800px;border: 1px solid gray;box-shadow: 0 0 10px black; float: right;}
#mark{font-weight: 800;}
#mark_con{ color: red; }
button{width: 50px; }
</style>

JS:
<script type="text/javascript">
//伪常量
var BLOCK_SIZE = 20; //格子大小
var COLS = 40; //列数
var ROWS = 30; //行数
//变量
var snakes = []; //保存蛇坐标
var c = null; //绘图对象
var toGo = 3; //行进方向
var snakecount = 4; //蛇身数量
var interval = null; //计时器
var foodX = 0; //食物X轴坐标
var foodY = 0; //食物Y轴坐标
var oMark = null; //分数显示框
var isPause = false; //是否暂停
// 绘图函数
function draw(){
c.clearRect(0,0,BLOCK_SIZE * COLS, BLOCK_SIZE * ROWS);
//画出横线
for( var i = 1; i <= ROWS; i++ ) {
c.beginPath();
c.moveTo(0, i * BLOCK_SIZE);
c.lineTo(BLOCK_SIZE * COLS, i * BLOCK_SIZE);
c.strokeStyle = "gray";
c.stroke();
}
//画出竖线
for(var i = 1; i <= COLS; i++){
c.beginPath();
c.moveTo(i * BLOCK_SIZE, 0);
c.lineTo(i * BLOCK_SIZE, BLOCK_SIZE * ROWS);
c.stroke();
}
//画出蛇
for (var i = 0; i < snakes.length; i++){
c.beginPath();
c.fillStyle = "green";
c.fillRect(snakes[i].x, snakes[i].y, BLOCK_SIZE, BLOCK_SIZE);
c.moveTo(snakes[i].x, snakes[i].y);
c.lineTo(snakes[i].x + BLOCK_SIZE, snakes[i].y);
c.lineTo(snakes[i].x + BLOCK_SIZE, snakes[i].y + BLOCK_SIZE);
c.lineTo(snakes[i].x, snakes[i].y + BLOCK_SIZE);
c.closePath();
c.strokeStyle = "white";
c.stroke();
}
//画出食物
c.beginPath();
c.fillStyle = "yellow";
c.fillRect(foodX, foodY, BLOCK_SIZE, BLOCK_SIZE);
c.moveTo(foodX, foodY);
c.lineTo(foodX + BLOCK_SIZE, foodY);
c.lineTo(foodX + BLOCK_SIZE, foodY + BLOCK_SIZE);
c.lineTo(foodX, foodY + BLOCK_SIZE);
c.closePath();
c.strokeStyle = "red";
c.stroke();
}
//游戏初始化
function start(){
for( var i = 0; i < snakecount; i++){
snakes[i] = {x: i * BLOCK_SIZE, y: 0};
}
addFood();
draw();
oMark.innerHTML = 0;
}
//移动函数
function move(){
switch(toGo){
case 1: //左边
snakes.push({x: snakes[snakecount - 1].x - BLOCK_SIZE, y: snakes[snakecount - 1].y});
break;
case 2: //上边
snakes.push({x: snakes[snakecount - 1].x, y: snakes[snakecount - 1].y - BLOCK_SIZE});
break;
case 3: //右边
snakes.push({x: snakes[snakecount - 1].x + BLOCK_SIZE, y: snakes[snakecount - 1].y});
break;
case 4: //下边
snakes.push({x: snakes[snakecount - 1].x, y: snakes[snakecount - 1].y + BLOCK_SIZE});
break;
default:;
}
snakes.shift();
isEat();
isDie();
draw();
}
//吃到食物判断
function isEat(){
if (snakes[snakecount - 1].x == foodX && snakes[snakecount - 1].y == foodY) {
oMark.innerHTML = (parseInt(oMark.innerHTML) + 1).toString();
addFood();
addSnake();
}
}
//添加蛇身
function addSnake(){
snakecount++;
snakes.unshift({x:BLOCK_SIZE * COLS, y:BLOCK_SIZE * ROWS});
}
//交互响应函数
function keydown(keyCode){
switch(keyCode){
case 37: //左边
if(toGo != 1 && toGo != 3) toGo = 1;break;
case 38: //上边
if(toGo != 2 && toGo != 4) toGo = 2;break;
case 39: //右边
if(toGo != 3 && toGo != 1) toGo = 3;break;
case 40: //下的
if(toGo != 4 && toGo != 2) toGo = 4;break;
case 80: //开始/暂停
if(isPause){
interval = setInterval(move,100);
isPause = false;
document.getElementById('pause').innerHTML = "Pause";
}else{
clearInterval(interval);
isPause = true;
document.getElementById('pause').innerHTML = "Start";
}
break;
}
}
//制造食物
function addFood(){
foodX = Math.floor(Math.random() * (COLS - 1)) * BLOCK_SIZE;
foodY = Math.floor(Math.random() * (ROWS - 1)) * BLOCK_SIZE;
// console.log(foodX + " -- " + foodY);
}
//死亡判断
function isDie(){
if(snakes[snakecount - 1].x == -20 || snakes[snakecount - 1].x == BLOCK_SIZE * COLS
|| snakes[snakecount - 1].y == -20 || snakes[snakecount - 1].y == BLOCK_SIZE * ROWS){
alert("Game Over!");
clearInterval(interval);
}
for(var i = 0; i < snakecount - 1; i++){
if(snakes[snakecount - 1].x == snakes[i].x && snakes[snakecount - 1].y == snakes[i].y){
clearInterval(interval);
alert("Game Over!");
}
}
}
// 启动函数
window.onload = function(){
c = document.getElementById('canvas').getContext('2d');
oMark = document.getElementById('mark_con');
start();
interval = setInterval(move,100);
document.onkeydown = function(event){
var event = event || window.event;
keydown(event.keyCode);
}
}
</script>
...全文
3386 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
AbraRussell 2015-12-15
  • 打赏
  • 举报
回复
学习一下
frank201113 2015-11-12
  • 打赏
  • 举报
回复
我想问问第101行代码snakes.unshift({x:BLOCK_SIZE * COLS, y:BLOCK_SIZE * ROWS});的作用是什么?
豌豆 2014-11-07
  • 打赏
  • 举报
回复
下下来学习一下
坏坏DE我 2014-11-07
  • 打赏
  • 举报
回复
赞一个。。。
dings503 2014-09-17
  • 打赏
  • 举报
回复
好厉害的说
lhw7791086 2014-09-01
  • 打赏
  • 举报
回复
NB
Gavin255 2014-08-29
  • 打赏
  • 举报
回复
学习了,,我也想做这个
wz_307 2014-08-26
  • 打赏
  • 举报
回复
发现bug: 触边gameover后, pause再start. 蛇就跑出去了~~
Cano12358 2014-08-25
  • 打赏
  • 举报
回复
引用 28 楼 flyskytoday 的回复:
真不错,自己动手做出来不简单
贪吃蛇不算很复杂,中间饶了不少弯,这是第三次写,前两次的思路都不对,到了中间就写不下去了。
flyskytoday 2014-08-25
  • 打赏
  • 举报
回复
真不错,自己动手做出来不简单
hookee 2014-08-25
  • 打赏
  • 举报
回复
qq825711424 2014-08-25
  • 打赏
  • 举报
回复
很牛的样子!谢谢分享!
lhw7791086 2014-08-25
  • 打赏
  • 举报
回复
凨行者 2014-08-25
  • 打赏
  • 举报
回复
不错 支持分享 赞一个
cattpon 2014-08-24
  • 打赏
  • 举报
回复
很厉害!表示鼓励~
Doown 2014-08-24
  • 打赏
  • 举报
回复
给你32个赞哦!!!
bihailantianswkj 2014-08-24
  • 打赏
  • 举报
回复
当碰到墙壁或者碰到自己身体game over点击Pause/Start按钮将会导致游戏继续的,建议game over后直接恢复到初始状态
Cano12358 2014-08-24
  • 打赏
  • 举报
回复
引用 15 楼 jslang 的回复:
[quote=引用 14 楼 Cano12358 的回复:] 应该是第一次左转,就将方向改成了向上,但是还没来得及刷新屏幕,第二次再按就是相反的方向了,撞倒了自身,就挂了。 正在考虑改进,但目前还没什么好的解决方案。
可以设置成每移动一步只能转向一次[/quote]正在尝试用一个flag变量,按下去之后就设置为false,之后就无法改变方向了,直到屏幕刷新完成后,再设回true
十飞我谁 2014-08-24
  • 打赏
  • 举报
回复
kevinmac2000 2014-08-24
  • 打赏
  • 举报
回复
很厉害!表示鼓励~
加载更多回复(17)

39,083

社区成员

发帖
与我相关
我的任务
社区描述
HTML5是构建Web内容的一种语言描述方式。HTML5是互联网的下一代标准,是构建以及呈现互联网内容的一种语言方式.被认为是互联网的核心技术之一。
社区管理员
  • HTML5社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧