js实现贪吃蛇小游戏
本文实例为大家分享了js实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>贪吃蛇</title>
<link rel="stylesheet" href="style.css" >
</head>
<body>
<div id="game">
<div id="explain">
<div>操作WASD 空格开始/暂停 R重新开始</div>
<div>当前分数:<span id="grade">0</span>分</div>
</div>
<canvas id="snakegame" width="500" height="500">
</canvas>
</div>
<script type="text/javascript" src="main.js" charset="UTF-8"></script>
</body>
</html>
style.css
*{
padding: 0;
margin: 0;
}
#game {
width: 500px;
margin: auto;
}
#explain {
width: 500px;
}
#explain div{
width: 500px;
height: 30px;
}
#snakegame {
background: green;
}
main.js
/**
* el 挂载的元素
* attribute 贪吃蛇的属性
*/
class Game {
constructor (el, attribute) {
this.el = document.getElementById(el);
// 获取画布的宽高
this.el.elW = parseInt(window.getComputedStyle(this.el).width);
this.el.elH = parseInt(window.getComputedStyle(this.el).height);
this.init(attribute);
this.keyListening();
}
// 初始化
init(attribute) {
this.attribute = {
color: "red", // 颜色
direction: "rigth", // 移动方向
state: "pause", // 状态 run pause end
grade: 0, // 分数
body: [{x: 20, y: 0}, {x: 0, y: 0}], // 贪吃蛇身体
wh: 20, // 矩形的宽高
speed: 200 // 速度
};
if (attribute) {
this.newAttribute = attribute;
Object.keys(attribute).forEach(key => {
this.attribute[key] = attribute[key];
});
}
this.food ={
x: 0,
y: 0,
color: 'red'
}
this.draw();
this.foodDraw();
}
// 绘制贪吃蛇
draw() {
let el = this.el;
let { body, wh, color } = this.attribute;
// 确定浏览器是否支持canvans元素
if (el.getContext) {
let context = snakegame.getContext("2d");
context.fillStyle = color;
body.forEach( key => {
context.fillRect(key.x, key.y, wh, wh);
});
}
}
// 随机生成食物
foodDraw() {
let el = this.el, wh = this.attribute.wh;
this.food.x = Math.floor(Math.random()*(el.elW - wh)),
this.food.y = Math.floor(Math.random()*(el.elH - wh));
while (this.isOverlap()) {
this.food.x = Math.floor(Math.random()*(el.elW - wh)),
this.food.y = Math.floor(Math.random()*(el.elH - wh));
}
if (el.getContext) {
let context = snakegame.getContext("2d");
context.fillStyle = this.food.color;
context.fillRect(this.food.x, this.food.y, wh, wh);
}
}
// 判断食物是否与贪吃蛇的身体重叠
isOverlap() {
let { wh } = this.attribute;
let food = this.food;
let flag = false;
function isIn(key, x, y) {
if (key.x <= x && key.x + wh >= x && key.y <= y && key.y + wh >= y) {
return true;
} else {
return false;
}
}
this.attribute.body.forEach(key => {
// 食物的上下左右四个点一个点在贪吃蛇的身体内就判断为重叠
if (isIn(key, food.x, food.y) || isIn(key, food.x, food.y + wh) || isIn(key, food.x + wh, food.y) || isIn(key, food.x + wh, food.y + wh)) {
flag = true;
}
});
return flag;
}
// 清除图形
clear(x, y, width, height) {
// 确定浏览器是否支持canvans元素
if (this.el.getContext) {
let context = snakegame.getContext("2d");
context.clearRect(x, y, width, height);
}
}
// 游戏状态更新
updateState(state) {
this.attribute.state = state;
if (state === "run") {
this.run();
}
}
// 游戏线程
run() {
let { body, wh, speed} = this.attribute;
let time = setInterval(() => {
// 判断游戏线程是否在运行
if (this.attribute.state !== 'run') {
clearInterval(time);
}
let obj = {};
switch(this.attribute.direction) {
case 'left':
obj['x'] = body[0].x - wh;
obj['y'] = body[0].y;
break;
case 'rigth':
obj['x'] = body[0].x + wh;
obj['y'] = body[0].y;
break;
case 'up':
obj['x'] = body[0].x;
obj['y'] = body[0].y - wh;
break;
case 'down':
obj['x'] = body[0].x;
obj['y'] = body[0].y + wh;
break;
}
body.unshift(obj);
// 判断是否吃到食物
if (this.isOverlap()) {
this.clear(this.food.x, this.food.y, wh, wh);
this.attribute.grade++;
this.foodDraw();
this.draw();
} else {
if (this.end()) {
alert("游戏结束");
this.updateState('end');
clearInterval(time);
} else {
let item = body.pop();
this.clear(item.x, item.y, wh, wh);
this.draw();
}
}
}, speed);
}
// 键盘事件监听
keyListening() {
document.onkeydown = (event) => {
let e = event || window.event || arguments.callee.caller.arguments[0];
if (e && e.keyCode === 87 && this.attribute.direction !== 'down') { // 按下W
this.attribute.direction = 'up';
}
if (e && e.keyCode === 65 && this.attribute.direction !== 'rigth') { // 按下A
this.attribute.direction = 'left';
}
if (e && e.keyCode === 68 && this.attribute.direction !== 'left') { // 按下D
this.attribute.direction = 'rigth';
}
if (e && e.keyCode === 83 && this.attribute.direction !== 'up') { // 按下W
this.attribute.direction = 'down';
}
if (e && e.keyCode === 32) { // 按下空格
let state;
if (this.attribute.state === 'pause') {
state = 'run';
}
if (this.attribute.state === 'run') {
state = 'pause';
}
this.updateState(state);
}
if (e && e.keyCode === 82) { // 按下R键
this.reStart();
}
}
}
// 是否死亡
end() {
let body = [...this.attribute.body];
let obj = body.shift();
let flag = false;
if (obj.x < 0 || obj.x >= this.el.elW || obj.y < 0 || obj.y >= this.el.elH) {
flag = true;
}
body.forEach(key => {
if (key.x === obj.x && key.y === obj.y) {
flag = true;
}
});
return flag;
}
// 重新开始
reStart() {
// 清除整个画布
this.clear(0, 0, this.el.elW, this.el.elH);
// 重新开始
this.init(this.newAttribute);
}
}
let game = new Game("snakegame", {color: "yellow"});
let grade = document.getElementById("grade");
let oldGrade = game.attribute.grade;
setInterval(() => {
if (oldGrade !== game.attribute.grade) {
oldGrade = game.attribute.grade;
grade.innerText = game.attribute.grade;
}
})
截图
以上是 js实现贪吃蛇小游戏 的全部内容, 来源链接: utcz.com/z/352900.html