javascript開發(fā)實(shí)現(xiàn)貪吃蛇游戲
貪吃蛇的例子:
在此例子中,利用snake數(shù)組的第0個(gè)元素和direction對(duì)象中的x值和y值做加法,算出蛇的下一個(gè)位置。利用間隔函數(shù),不停的修改類名來(lái)進(jìn)行渲染操作,感覺(jué)是一個(gè)很靈活的例子。
style.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.page{
width: 100vw;
height: 100vh;
position: absolute;
left: 0;
top: 0;
}
body{
font-size: 0.16rem;
}
.startGame{
/* display: none; */
background: purple;
display: flex;
justify-content: center;
align-items: center;
}
.startBtn,.reStartBtn{
width:2rem;
height: 0.5rem;
text-align: center;
line-height: 0.5rem;
background: deepskyblue;
color: #fff;
}
.endGame{
display: none;
/* display:flex; */
flex-direction: column;
justify-content: center;
align-items: center;
background: lightsalmon;
}
.endGame h1{
margin: 1rem 0;
color: #fff;
}
.gaming{
display: none;
background: black;
color: #fff;
}
.gaming .score{
display: flex;
justify-content: space-between;
height: 0.5rem;
align-items: center;
width: 100vw;
padding: 0 0.25rem;
}
.gaming .score .pauseBtn{
width: 0.8rem;
height: 0.3rem;
line-height: 0.3rem;
background: #999;
text-align: center;
}
.gaming .mainGame{
/* 15*20 */
width: 3.45rem;
height:4.6rem ;
background: #555;
margin: 0.3rem auto;
display: flex;
flex-wrap: wrap;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
box-sizing: content-box;
}
.gaming .mainGame .gezi{
width: 0.23rem;
height: 0.23rem;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.gaming .mainGame .gezi.snake{
width: 0.23rem;
height: 0.23rem;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background-color: #fff;
}
.gaming .mainGame .gezi.food{
width: 0.23rem;
height: 0.23rem;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
/* background-color: orangered; */
}
.gaming .mainGame .gezi.food:before{
width: 100%;
height: 100%;
content: "";
display: block;
background:yellow;
animation: food 1s alternate infinite ;
box-shadow: 0 0 10px #ffffcc;
}
.gaming .mainGame .gezi.food[data-food=redStar]:before{
background:deeppink;
}
@keyframes food{
from{
transform: scale(1) rotate(0deg);
}
to{
transform: scale(0.5) rotate(360deg);
}
}
.gaming .mainGame .gezi.snake:before{
content:"" ;
display: block;
width: 100%;
height: 100%;
background: #ccc;
animation: snake 0.4s;
box-sizing: border-box;
}
@keyframes snake{
from{
background: #fff;
box-shadow:0 0 15px rgba(255,255,255,1);
}
to{
background: #ccc;
box-shadow:0 0 15px rgba(255,255,255,0.5);
}
}
index.js主要實(shí)現(xiàn)了所有的貪吃蛇的頁(yè)面的各種操作
var startBtn = document.querySelector(".startBtn")
var startPage = document.querySelector(".page.startGame")
var gamingPage = document.querySelector(".gaming")
var endGamePage = document.querySelector(".endGame")
var mainGame = document.querySelector(".mainGame")
var numDom = document.querySelector(".score .left .num")
var endGameScore = document.querySelector(".endGame .num")
var reStartBtn = document.querySelector('.reStartBtn');
var pauseBtn=document.querySelector(".pauseBtn");
var snake = [{x:0,y:1},{x:1,y:1},{x:2,y:1}];
var snakeFood = {
x:10,y:10
}
//初始化得分
var score = 0;
var interId;
var ispaused=false;
//定義蛇運(yùn)動(dòng)的方向
//從右向左{x:-1,y:0}
//從左向右{x:1,y:0}
//從上到下{x:0,y:1}
//從下到上{x:0,y:-1}
var direction = {x:-1,y:0}
startBtn.onclick = function(){
startPage.style.display = "none"
gamingPage.style.display = "block"
gameIng()
}
function renderGezi(){
for(var i=0;i<20;i++){
for(var j=0;j<15;j++){
var gezi = document.createElement("div");
gezi.className = "gezi";
gezi.id = 'x'+j+'y'+i;
mainGame.appendChild(gezi)
}
}
}
renderGezi()
//隨機(jī)創(chuàng)建蛇,
function createSnake(){
var randomX = parseInt(Math.random()*13)
var randomY = parseInt(Math.random()*20)
snake = [];
for(var i= 0;i<3;i++){
snake.push({x:randomX+i,y:randomY})
}
}
function renderSnake(){
snake.forEach(function(item,i){
var snakeBody = document.querySelector("#x"+item.x+"y"+item.y);
snakeBody.className = "gezi snake";
})
}
//渲染食物
function renderFood(){
var randomX = parseInt(Math.random()*15)
var randomY = parseInt(Math.random()*20)
var foodDiv = document.querySelector("#x"+randomX+"y"+randomY)
if(foodDiv.className == "gezi snake"){
renderFood()
}else{
foodDiv.className = "gezi food"
}
}
createSnake()
renderFood()
renderSnake()
function gameIng(){
interId = setInterval(function(){
var headerX = snake[0].x + direction.x;
var headerY = snake[0].y + direction.y;
if(headerX<0){
headerX = 14;
}
if(headerX>14){
headerX = 0;
}
if(headerY<0){
headerY = 19;
}
if(headerY>19){
headerY = 0;
}
var snakeHeader = {x:headerX,y:headerY};
isSnake(snakeHeader)
if(!isFood(snakeHeader)) {
//將刪除的蛇,找到相對(duì)應(yīng)的dom,將其class類名修改成正常的gezi
var snakeFooter = snake.pop()//返回刪除的對(duì)象
var snakeFooterDiv = document.querySelector("#x"+snakeFooter.x+"y"+snakeFooter.y);
snakeFooterDiv.className = "gezi";
}
snake.unshift(snakeHeader)//在數(shù)組最前面加入
renderSnake()
},100)
}
function isSnake(snakeHeader){
var newHeader = document.querySelector("#x"+snakeHeader.x+"y"+snakeHeader.y)
if(newHeader.className == "gezi snake"){
clearInterval(interId);
gamingPage.style.display = "none"
endGamePage.style.display = "flex"
endGameScore.innerHTML = score;
return true;
}else{
return false;
}
}
function isFood(snakeHeader){
var newHeader = document.querySelector("#x"+snakeHeader.x+"y"+snakeHeader.y)
if(newHeader.className == "gezi food"){
score ++;
numDom.innerHTML = score;
renderFood()
return true;
}else{
return false;
}
}
var body = document.body
body.addEventListener("keydown",function(e){
console.log(e)
//方向不能直接顛倒向上時(shí)原來(lái)不能是向下的。
if(e.key == "ArrowUp"&&direction.y!=1){
direction = {x:0,y:-1}
}
if(e.key=="ArrowRight"&&direction.x!=-1){
direction = {x:1,y:0}
}
if(e.key == "ArrowDown"&&direction.y!=-1){
direction = {x:0,y:1}
}
if(e.key=="ArrowLeft"&&direction.x!=1){
direction = {x:-1,y:0}
}
})
ylEvent.init(body);
body.addEvent("swiperLeft",function(){
if(direction.x!=1){
direction = {x:-1,y:0}
}
})
body.addEvent("swiperRight",function(){
if(direction.x!=-1){
direction = {x:1,y:0}
}
})
body.addEvent("swiperTop",function(){
if(direction.y!=1){
direction = {x:0,y:-1}
}
})
body.addEvent("swiperBottom",function(){
if(direction.y!=-1){
direction = {x:0,y:1}
}
})
reStartBtn.onclick = function(){
location.reload();
}
pauseBtn.onclick=function(){
if(ispaused){
ispaused=false;
gameIng();
}else{
ispaused=true;
clearInterval(interId);
}
}
js輔助式響應(yīng).js
(function(){
function xys(){
var userAgent=navigator.userAgent
var html=document.querySelector("html");
//userAgent.indexOf("iPhone")通過(guò)此方法可以獲取iPhone在字符串中的索引值(開頭位置)
//沒(méi)有找到返回-1
html.className="";
if((userAgent.indexOf("iPhone"))!=-1){
html.classList.add("iphone");
}else if((userAgent.indexOf("Android"))!=-1)
{
html.classList.add("android");
}else if((userAgent.indexOf("iPad"))!=-1){
html.classList.add("ipad");
}else{
html.classList.add("pc");
}
if(window.innerWidth<640){
html.classList.add('lt640');
html.classList.add('lt960');
html.classList.add('lt1200');
}else if(window.innerWidth<960){
html.classList.add('lt960');
html.classList.add('lt1200');
html.classList.add('gt640');
}else if(window.innerWidth<1200){
html.classList.add('lt1200');
html.classList.add('gt640');
html.classList.add('gt960');
}else{
html.classList.add('gt640');
html.classList.add('gt960');
html.classList.add('gt1200');
}
var screenWidth = window.innerWidth;
var danwei = screenWidth/3.75;//屏幕的寬度/設(shè)計(jì)稿占滿全屏的寬度為多少rem
var html = document.querySelector("html")
html.style.fontSize = danwei + 'px';
}
xys();
window.onresize=function(){
xys();
}
})()
swiperEvent.js
var ylEvent = {
eventAll:{
//"自定義的事件名稱":['事件要觸發(fā)執(zhí)行的函數(shù)1','事件要觸發(fā)執(zhí)行的函數(shù)2','事件要觸發(fā)執(zhí)行的函數(shù)3']
},
init:function(dom){
dom.eventAll = {},
dom.addEvent = this.addEvent;
dom.emit = this.emit;
dom.removeEvent = this.removeEvent
dom.touchData = {};
//body.emit('swiperLeft',"msg")
dom.addEventListener("touchstart",function(e){
//console.log(e)
this.touchData.startX = e.touches[0].pageX;
this.touchData.startY = e.touches[0].pageY
})
dom.addEventListener('touchmove',function(e){
this.touchData.endX = e.touches[0].pageX;
this.touchData.endY = e.touches[0].pageY;
})
dom.addEventListener("touchend",function(e){
//console.log(e)
var x = this.touchData.endX - this.touchData.startX;
var y = this.touchData.endY - this.touchData.startY
if( (Math.abs(x) > Math.abs(y)) && Math.abs(x)>100){
if(x>0){
//console.log('向右滑動(dòng)')
e.swiperDir = 'swiperRight'
body.emit('swiperRight',e)
}else{
//console.log('向左滑動(dòng)')
e.swiperDir = 'swiperLeft'
body.emit('swiperLeft',e)
}
}else if((Math.abs(x) < Math.abs(y)) && Math.abs(y)>100){
if(y>0){
//console.log('向下滑動(dòng)')
e.swiperDir = 'swiperBottom'
body.emit('swiperBottom',e)
}else{
//console.log('向上滑動(dòng)')
e.swiperDir = 'swiperTop'
body.emit('swiperTop',e)
}
}
})
},
addEvent:function(eventName,callBackFn){
if(this.eventAll[eventName]==undefined){
this.eventAll[eventName] = []
}
this.eventAll[eventName].push(callBackFn)
},
emit:function(eventName,eventMsg){
if(this.eventAll[eventName]!=undefined){
this.eventAll[eventName].forEach(function(item,i){
item(eventMsg)
})
}
},
removeEvent:function(eventName,callBackFn){
var that = this
this.eventAll[eventName].forEach(function(item,i){
if(item==callBackFn){
that.eventAll[eventName].splice(i,1)
}
})
},
}
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <script src="js/js輔助式響應(yīng).js" type="text/javascript" charset="utf-8"></script> <link rel="stylesheet" type="text/css" href="css/style.css" /> </head> <body> <!-- 1、貪吃蛇頁(yè)面結(jié)構(gòu)和樣式 2、能夠繪制蛇 3、能夠繪制食物 4、讓蛇運(yùn)動(dòng)起來(lái) 5、蛇能夠吃食物 6、蛇碰到自己就會(huì)失敗 --> <div class="page startGame"> <div class="startBtn">開始游戲</div> </div> <div class="page gaming"> <div class="score"> <div class="left"> score:<span class="num">0</span> </div> <div class="pauseBtn"> 暫停 </div> </div> <div class="mainGame"> </div> </div> <div class="page endGame"> <h1>您最終獲取分?jǐn)?shù)是<span class="num">0</span>分</h1> <div class="reStartBtn">重新開始</div> </div> <script src="js/swiperEvent.js" type="text/javascript" charset="utf-8"></script> <script src="js/index.js" type="text/javascript" charset="utf-8"></script> </body> </html>
結(jié)果:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于 D3.js 繪制動(dòng)態(tài)進(jìn)度條的實(shí)例詳解
D3是一個(gè)被數(shù)據(jù)驅(qū)動(dòng)的文檔。這篇文章主要介紹了基于 D3.js 繪制動(dòng)態(tài)進(jìn)度條的方法,需要的朋友可以參考下2018-02-02
JavaScript操作選擇對(duì)象的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇JavaScript操作選擇對(duì)象的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧2016-05-05
基于javascript實(shí)現(xiàn)頁(yè)面加載loading效果
這篇文章主要為大家詳細(xì)介紹了基于javascript實(shí)現(xiàn)頁(yè)面加載loading效果的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03
js新聞滾動(dòng) js如何實(shí)現(xiàn)新聞滾動(dòng)效果
JS實(shí)現(xiàn)新聞滾動(dòng)效果:滾動(dòng)頻率由setTimeout(F,#%18?10:3000)這個(gè)3000來(lái)控制,感興趣的朋友可以了解下哦2013-01-01
使用typescript改造koa開發(fā)框架的實(shí)現(xiàn)
這篇文章主要介紹了使用typescript改造koa開發(fā)框架的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02

