<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport">
<style>
body {
text-align: center;
}
</style>
</head>
<body>
<canvas id="canvas" style="border:2px solid red" width="410" height="410"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var canvasWidth = 410,
canvasHeight = 410;
var snakeFn = function () {
//食物大小
this.foodSize = 10;
//初始化
this.init();
}
/**
* @property init 初始化
* */
snakeFn.prototype.init = function () {
//移动方向
this.direction = 'right';
//蛇身
this.snakeX = (canvasWidth - this.foodSize) / 2;
this.snakeY = (canvasHeight - this.foodSize) / 2;
this.snake = [
{x: this.snakeX, y: this.snakeY},
{x: this.snakeY - this.foodSize, y: this.snakeY},
{x: this.snakeY - this.foodSize*2, y: this.snakeY}
];
ctx.fillStyle = "red"
//蛇
this.drawSnake();
this.snakeLoop();
}
/**
* @property draw 画蛇
* */
snakeFn.prototype.drawSnake = function(){
//渲染蛇身
for (var i = 0; i < this.snake.length; i++) {
var snakeItem = this.snake[i];
var x = snakeItem.x,y=snakeItem.y;
ctx.fillRect(x, y, this.foodSize, this.foodSize);
}
}
/**
* @property food 食物
* */
snakeFn.prototype.food = function () {
//随机生成
var x = Math.floor(Math.random() * canvasWidth);
var y = Math.floor(Math.random() * canvasHeight);
var xRemainder = x % this.foodSize;
var yRemainder = y % this.foodSize;
if(!this.foodX && !this.foodY){
//保证每次生成是foodSize 的倍数
this.foodX = xRemainder != 0 ? x - xRemainder : x;
this.foodY = yRemainder != 0 ? y - yRemainder : y;
//防止食物随机出在蛇的身上
for(var i = 0 ; i < this.snake.length ; i++){
//判断食物坐标是否和身体重合
if(this.snake[i].x== this.foodX &&
this.snake[i].y == this.foodX){
//重新生成食物
this.foodX = null;
this.foodY = null;
this.food(true);
return;
}
}
}
ctx.fillRect(this.foodX, this.foodY, this.foodSize, this.foodSize);
}
/**
* @property snakeMove 蛇移动
* @description 在此更新蛇身坐标及吃掉食物
* */
snakeFn.prototype.snakeMove = function(){
var snakeHead = this.snake[0];
//移动方向
switch (this.direction) {
case 'top':
this.snake[0]={
x:snakeHead.x,
y:snakeHead.y-this.foodSize
}
break;
case 'right':
this.snake[0]={
x:snakeHead.x + this.foodSize,
y:snakeHead.y
}
break;
case 'bottom':
this.snake[0]={
x:snakeHead.x,
y:snakeHead.y+this.foodSize,
}
break;
case 'left':
this.snake[0]={
x:snakeHead.x-this.foodSize,
y:snakeHead.y,
};
break;
default:
snakeHead={
x:snakeHead.x + this.foodSize,
y:snakeHead.y
}
};
//把当前坐标替换成前一个坐标
var temp;
for (var i = 1; i < this.snake.length; i++) {
temp = this.snake[i];
this.snake[i] = snakeHead;
snakeHead = temp;
}
//吃掉食物
if(this.snake[0].x == this.foodX && this.snake[0].y == this.foodY){
var lastSnake = this.snake[this.snake.length - 1]; //获取最后一个身体
var plastSnake = this.snake[this.snake.length - 2]; //获取倒数第二个身体
this.snake.push({
x: 2*lastSnake.x - plastSnake.x,
y : 2*lastSnake.y - plastSnake.y
});
//重新生成食物
this.foodX = null;
this.foodY = null;
this.food(true);
}
//渲染蛇身
this.drawSnake();
}
/**
* @property snakeLoop 蛇移动定时
* */
snakeFn.prototype.snakeLoop = function () {
var snakeThis = this;
//蛇移动
this.snakeLoopInterval = setInterval(function () {
//清空画布
ctx.clearRect(0,0,canvasWidth,canvasHeight);
//随机出现食物
snakeThis.food();
//绘制新的图形
snakeThis.snakeMove();
//判断游戏是否结束
snakeThis.gameOver();
}, 500)
}
/**
* @property directionChange 移动方向改变
* @param e { object } event
* */
snakeFn.prototype.directionChange = function (e) {
var keyType = {
38: 'top',
39: 'right',
40: 'bottom',
37: 'left'
}
var historyDirection = snakeGame.direction;
snakeGame.direction = keyType[e.keyCode];
if(snakeGame.direction == 'top' && historyDirection == 'bottom' ||
snakeGame.direction == 'bottom' && historyDirection == 'top' ||
snakeGame.direction == 'right' && historyDirection == 'left' ||
snakeGame.direction == 'left' && historyDirection == 'right'
){
snakeGame.reverseSnake = true;
snakeGame.snake = snakeGame.snake.reverse();
//渲染蛇身
snakeGame.drawSnake();
}
}
/**
* @property gameOver 游戏结束
* */
snakeFn.prototype.gameOver = function () {
//临界值判断
var snakeHead = this.snake[0];
var gameOver = false;
if (
snakeHead.x < 0 ||
snakeHead.x > canvasWidth - this.foodSize ||
snakeHead.y < 0 ||
snakeHead.y > canvasHeight - this.foodSize
) {
gameOver= true;
} else{
//判断头结点是否碰撞身体
for(var i = 1 ; i < this.snake.length; i++){
if(this.snake[i].x == snakeHead.x &&
this.snake[i].y == snakeHead.y){
gameOver = true;
}
}
}
//游戏结束
if(gameOver){
//清除定时
clearInterval(this.snakeLoopInterval);
//提示信息
alert("你太菜了,游戏结束");
//清空画布
ctx.clearRect(0,0,canvasWidth,canvasHeight);
this.init();
}
}
var snakeGame = new snakeFn();
window.onkeyup = snakeGame.directionChange;
</script>
</body>
</html>
js 小游戏贪吃蛇
于 2021-05-13 14:07:39 首次发布