如何基于javascript實(shí)現(xiàn)貪吃蛇游戲
更新時(shí)間:2020年02月09日 11:11:42 作者:shumeihh
這篇文章主要介紹了如何基于javascript實(shí)現(xiàn)貪吃蛇游戲,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
這篇文章主要介紹了如何基于javascript實(shí)現(xiàn)貪吃蛇游戲,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
html代碼:
<div class="content">
<div class="btn startBtn"> <!-- 開始按鈕 -->
<button type="button"></button>
</div>
<div class="btn stopBtn"> <!-- 暫停按鈕 -->
<button type="button"></button>
</div>
<div id="snakeWrap"></div> <!-- 主題內(nèi)容 -->
</div>
css代碼:
* {
margin: 0;
padding: 0;
}
body {
background-color: #565F65;
width: 100%;
height: 10vh;
overflow: hidden;
}
.content {
width: 500px;
height: 500px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -250px;
margin-left: -250px;
background-color: #565F65;
border: 10px solid #E7E7E7;
box-shadow: inset 0px 0px 5px 2px #000;
}
.btn {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, .3); /*游戲未開始時(shí)和暫停時(shí)的遮罩*/
z-index: 2;
}
.btn button {
background: none;
border: none;
background-size: 100% 100%;
cursor: pointer;
outline: none;
position: absolute;
left: 50%;
top: 50%;
}
.startBtn button{
width: 170px;
height: 80px;
background-image: url(img/startbtn.png);
margin-top: -40px;
margin-left: -85px;
}
.stopBtn {
display: none;
}
.stopBtn button{
width: 70px;
height: 70px;
background-image: url(img/stopbtn.png);
margin-top: -35px;
margin-left: -35px;
}
#snakeWrap {
width: 500px;
height: 500px;
position: relative;
}
.snakeHead { /*蛇頭樣式*/
background-color: aqua;
border-radius: 50%;
}
.snakeBody { /*蛇身樣式*/
background-color: navajowhite;
border-radius: 50%;
}
.food { /*食物樣式*/
background-image: url(img/food.png);
background-size: cover;
}
javascript 代碼:
var sw = 20, //一個(gè)方塊的寬
sh = 20, //一個(gè)方塊的高
tr = 25, //行數(shù)
td = 25; //列數(shù)
var snake = null, //蛇的實(shí)例
food = null, //食物的實(shí)例
game = null; //游戲的實(shí)例
function Square(x, y, classname) {
this.x = x * sw; //方塊實(shí)際的位置
this.y = y * sh; //方塊實(shí)際的位置
this.class = classname;
this.viewContent = document.createElement('div'); //方塊對應(yīng)的DOM元素
this.viewContent.className = this.class;
this.parent = document.getElementById('snakeWrap'); //方塊的父級
}
Square.prototype.create = function() { //創(chuàng)建方塊 DOM,并添加到頁面里
this.viewContent.style.position = 'absolute';
this.viewContent.style.width = sw + 'px';
this.viewContent.style.height = sh + 'px';
this.viewContent.style.left = this.x + 'px';
this.viewContent.style.top = this.y + 'px';
this.parent.appendChild(this.viewContent);
};
Square.prototype.remove = function() {
this.parent.removeChild(this.viewContent);
}
//蛇
function Snake() {
this.head = null; //存一下蛇頭的信息
this.tail = null; //存一下蛇尾的信息
this.pos = []; //存儲蛇身上的每一個(gè)方塊的位置,二維數(shù)組
this.directionNum = { //存儲蛇走的方向,用一個(gè)對象來表示
left : {
x : -1,
y : 0,
rotate : 180
},
right : {
x : 1,
y : 0,
rotate : 0
},
up : {
x : 0,
y : -1,
rotate : -90
},
down : {
x : 0,
y : 1,
rotate : 90
}
}
}
Snake.prototype.init = function() {
//創(chuàng)建蛇頭
var snakeHead = new Square(2, 0, 'snakeHead');
snakeHead.create();
this.head = snakeHead; // 存儲蛇頭信息
this.pos.push([2, 0]); //把蛇頭的位置存起來
//創(chuàng)建蛇身體
var snakeBody1 = new Square(1, 0, 'snakeBody');
snakeBody1.create();
this.pos.push([1, 0]); //把蛇身1的位置存起來
var snakeBody2 = new Square(0, 0, 'snakeBody');
snakeBody2.create();
this.tail = snakeBody2; //把蛇尾的信息存起來
this.pos.push([0, 0]); //把蛇身1的位置存起來
//讓蛇頭蛇身形成鏈表關(guān)系
snakeHead.last = null;
snakeHead.next = snakeBody1;
snakeBody1.last = snakeHead;
snakeBody1.next = snakeBody2;
snakeBody2.last = snakeBody1;
snakeBody2.next = null;
//給蛇添加一條屬性,用來表示蛇走的方向
this.direction = this.directionNum.right; //默認(rèn)讓蛇往右走
}
//這個(gè)方法用來獲取蛇頭的下一個(gè)位置對應(yīng)的元素, 要根據(jù)元素做不同的事情
Snake.prototype.getNextPos = function() {
var nextPos = [ //蛇頭要走的下一個(gè)點(diǎn)的坐標(biāo)
this.head.x/sw + this.direction.x,
this.head.y/sh + this.direction.y
];
//下一個(gè)點(diǎn)是自己,代表撞到了自己,游戲結(jié)束
var selfCollind = false; //是否撞到自己
this.pos.forEach(function(value) {
if(value[0] == nextPos[0] && value[1] == nextPos[1]) {
//如果數(shù)組中的兩個(gè)數(shù)據(jù)都相等,就說明下一個(gè)點(diǎn)在蛇身上里面能找到,代表撞到自己了
selfCollind = true;
}
});
if(selfCollind) {
console.log('撞到自己了!');
this.strategies.die.call(this);
return;
}
//下一個(gè)點(diǎn)是墻,游戲結(jié)束
if(nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1) {
console.log('撞墻了!');
this.strategies.die.call(this);
return;
}
//下一個(gè)點(diǎn)是食物,吃
if(food && food.pos[0] == nextPos[0] && food.pos[1] == nextPos[1]) {
//如果這個(gè)條件成立說明現(xiàn)在蛇頭要走的下一個(gè)點(diǎn)是食物的那個(gè)點(diǎn)
console.log('撞到食物了了!');
this.strategies.eat.call(this);
return;
}
//下一個(gè)點(diǎn)什么都不是,走
this.strategies.move.call(this);
};
//處理碰撞后要做的事
Snake.prototype.strategies = {
move : function(format) { //這個(gè)參數(shù)用于決定要不要刪除最后一個(gè)方塊(蛇尾), 當(dāng)傳了這個(gè)參數(shù)后就表示要做的事情是吃
//創(chuàng)建新身體(在蛇頭位置)
var newBody = new Square(this.head.x/sw, this.head.y/sh, 'snakeBody');
//更新鏈表關(guān)系
newBody.next = this.head.next;
newBody.next.last = newBody;
newBody.last = null;
this.head.remove(); //舊舌頭從原來的位置刪除
newBody.create();
//創(chuàng)建一個(gè)新蛇頭(蛇頭下一個(gè)要走到的點(diǎn))
var newHead = new Square(this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y, 'snakeHead')
//更新鏈表關(guān)系
newHead.next = newBody;
newHead.last = null;
newBody.last = newHead;
newHead.viewContent.style.transform = 'rotate('+this.direction.rotate+'deg)';
newHead.create();
//蛇身上每一個(gè)方塊的坐標(biāo)也要更新
this.pos.splice(0,0, [this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y]);
this.head = newHead; //還要把this.head的信息更新一下
if(!format) { //如何format 的值為 false, 表示需要刪除(除了吃之外的操作)
this.tail.remove();
this.tail = this.tail.last;
this.pos.pop();
}
},
eat : function() {
this.strategies.move.call(this, true);
createFood();
game.score ++;
},
die : function() {
game.over();
}
}
snake = new Snake();
//創(chuàng)建食物
function createFood() {
//食物小方塊的隨機(jī)坐標(biāo)
var x = null;
var y = null;
var include = true; //循環(huán)跳出的條件, true表示食物的坐標(biāo)在蛇身上(需要繼續(xù)循環(huán)),false表示食物坐標(biāo)不在蛇身上(不循環(huán)了)
while(include) {
x = Math.round(Math.random() * (td - 1)); //0-29
y = Math.round(Math.random() * (tr - 1));
snake.pos.forEach(function(value) {
if(x != value[0] && y != value[1]) {
//這個(gè)條件成立說明現(xiàn)在隨機(jī)出來的這個(gè)坐標(biāo),在蛇身上并沒有找到
include = false;
}
});
}
//生成食物
food = new Square(x, y, 'food');
food.pos = [x,y]; //存儲一下生成食物的坐標(biāo),用于跟蛇頭要走的下一個(gè)點(diǎn)作對比
var foodDom = document.querySelector('.food');
if(foodDom) {
foodDom.style.left = x*sw + 'px';
foodDom.style.top = y*sh + 'px';
}else {
food.create();
}
}
//創(chuàng)建游戲邏輯
function Game() {
this.timer = null;
this.score = 0;
this.speed = 200;
}
Game.prototype.init = function() {
snake.init();
snake.getNextPos();
createFood();
document.onkeydown = function(ev) { //用戶按下方向鍵觸發(fā)事件
if(ev.which == 37 && snake.direction != snake.directionNum.right) {
//用戶按下左鍵是,蛇不能是往右走
snake.direction = snake.directionNum.left;
}else if(ev.which == 38 && snake.direction != snake.directionNum.dowm) {
snake.direction = snake.directionNum.up;
}else if(ev.which == 39 && snake.direction != snake.directionNum.left) {
snake.direction = snake.directionNum.right;
}else if(ev.which == 40 && snake.direction != snake.directionNum.up) {
snake.direction = snake.directionNum.down;
}
}
this.start();
}
Game.prototype.start = function() { //開始游戲
this.timer = setInterval(function() {
snake.getNextPos();
}, this.speed);
}
Game.prototype.pause = function() {
clearInterval(this.timer);
}
Game.prototype.over = function() { //開始游戲
clearInterval(this.timer);
alert('你的得分為' + this.score);
//游戲回到最初的狀態(tài)
var snakeWrap = document.getElementById('snakeWrap');
snakeWrap.innerHTML = '';
snake = new Snake();
game = new Game();
var startBtnWrap = document.querySelector('.startBtn');
startBtnWrap.style.display = 'block';
}
//開啟游戲
game = new Game();
var startBtn = document.querySelector('.startBtn button');
startBtn.onclick = function() {
startBtn.parentNode.style.display = 'none';
game.init();
};
//暫停
var snakeWrap = document.getElementById('snakeWrap');
var puseBtn = document.querySelector('.stopBtn button')
snakeWrap.onclick = function() {
game.pause();
puseBtn.parentNode.style.display = 'block';
}
puseBtn.onclick =function() {
game.start();
puseBtn.parentNode.style.display = 'none';
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
小程序圓形進(jìn)度條及面積圖實(shí)現(xiàn)的方法
做微信小程序的朋友大都接觸過或自己動手寫過自定義組件,下面這篇文章主要給大家介紹了關(guān)于小程序圓形進(jìn)度條及面積圖實(shí)現(xiàn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05
JavaScript實(shí)現(xiàn)簡易計(jì)算器小功能
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡易計(jì)算器小功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
js中鼠標(biāo)滾輪事件詳解(firefox多瀏覽器)
之前js 仿Photoshop鼠標(biāo)滾輪控制輸入框取值中已使用js對鼠標(biāo)滾輪事件進(jìn)行控制,滾輪事件其中考慮瀏覽器兼容性問題2010-02-02
JS實(shí)現(xiàn)懸浮移動窗口(懸浮廣告)的特效
頁面加載完成之后向頁面插入窗口,之后向窗口插入關(guān)閉按鈕,使用setInterval()函數(shù)觸發(fā)moves()函數(shù)開始動畫2013-03-03

