js實現(xiàn)貪吃蛇小游戲
更新時間:2019年10月29日 08:36:17 作者:紅浴巾
這篇文章主要為大家詳細(xì)介紹了js實現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了js實現(xiàn)貪吃蛇小游戲的具體代碼,供大家參考,具體內(nèi)容如下
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>當(dāng)前分?jǐn)?shù):<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", // 狀態(tài) run pause end
grade: 0, // 分?jǐn)?shù)
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);
});
}
}
// 隨機(jī)生成食物
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 => {
// 食物的上下左右四個點一個點在貪吃蛇的身體內(nèi)就判斷為重疊
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);
}
}
// 游戲狀態(tài)更新
updateState(state) {
this.attribute.state = state;
if (state === "run") {
this.run();
}
}
// 游戲線程
run() {
let { body, wh, speed} = this.attribute;
let time = setInterval(() => {
// 判斷游戲線程是否在運(yùn)行
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("游戲結(jié)束");
this.updateState('end');
clearInterval(time);
} else {
let item = body.pop();
this.clear(item.x, item.y, wh, wh);
this.draw();
}
}
}, speed);
}
// 鍵盤事件監(jiān)聽
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;
}
})
截圖

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js(jquery)實現(xiàn)無刷新跳轉(zhuǎn)404頁面不存在效果
有時候我們希望臨時讓某個分類或者多個文章不能正常訪問,手動給html文件改名?或者改后臺改程序?太麻煩了。用本文的js代碼很容易實現(xiàn),而且使用得當(dāng)很隱蔽。這篇文章主要介紹了js(jquery)實現(xiàn)無刷新跳轉(zhuǎn)404頁面不存在效果,需要的朋友可以參考下2023-04-04
Bootstrap編寫一個在當(dāng)前網(wǎng)頁彈出可關(guān)閉的對話框 非彈窗
這篇文章主要介紹了Bootstrap編寫一個在當(dāng)前網(wǎng)頁彈出可關(guān)閉的對話框,不用跳轉(zhuǎn),非彈窗,感興趣的小伙伴們可以參考一下2016-06-06
JavaScript實現(xiàn)旋轉(zhuǎn)圖像的三種方法介紹
在文檔掃描Web應(yīng)用中,我們需要旋轉(zhuǎn)傾斜的或掃描方向錯誤的文檔圖像,這篇文章主要為大家整理了使用JavaScript旋轉(zhuǎn)圖像的三種方法,希望對大家有所幫助2024-01-01
javascript實現(xiàn) 在光標(biāo)處插入指定內(nèi)容
javascript實現(xiàn) 在光標(biāo)處插入指定內(nèi)容...2007-05-05

