JavaScript編寫推箱子游戲
推箱子游戲是老游戲了, 網(wǎng)上有各種各樣的版本, 說下推箱子游戲的簡單實現(xiàn),以及我找到的一些參考視頻和實例;
如下是效果圖:

這個拖箱子游戲做了移動端的適配, 我使用了zepto的touch模塊, 通過手指滑動屏幕就可以控制烏龜走不同的方向;
因為推箱子這個游戲比較簡單, 直接用了過程式的方式寫代碼, 模塊也就是兩個View 和 Model, 剩下就是用戶的事件Controller, 用戶每一次按下鍵盤的方向鍵都會改變數(shù)據(jù)模型的數(shù)據(jù),然后重新生成游戲的靜態(tài)html, 然后用innerHTML方式插入到界面, 自動生成DOM節(jié)點;
游戲的關(guān)卡模型就是數(shù)據(jù), 我把每一關(guān)的數(shù)據(jù)分為三塊:
地圖數(shù)據(jù),二維數(shù)組(地圖數(shù)據(jù)包括板磚, 箱子要去的目標(biāo)位置, 空白的位置)
箱子數(shù)據(jù),一維數(shù)組(箱子的初始位置)
小烏龜?shù)臄?shù)據(jù),json對象
每一個關(guān)卡都有對應(yīng)的游戲關(guān)卡數(shù)據(jù), 模擬的數(shù)據(jù)如下:
level: [
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,1,1,1,0,0,0,0],
[0,1,1,3,3,1,0,0,0],
[0,1,0,0,0,0,1,0,0],
[0,1,0,0,0,0,1,0,0],
[0,1,1,1,1,1,1,0,0]
],
person: {x : 2, y : 2},
box: [{x:3, y : 2},{x:4,y:2}]
},
//第二關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,1,1,1,1,1,0,0],
[0,1,0,0,1,1,1,0],
[0,1,0,0,0,0,1,0],
[1,1,1,0,1,0,1,1],
[1,3,1,0,1,0,0,1],
[1,3,0,0,0,1,0,1],
[1,3,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1]
],
person: {x : 2, y : 2},
box: [{x:3, y : 2}, {x:2,y:5} ,{x:5, y:6}]
/*
box : [
{x:3, y : 1},
{x:4, y : 1},
{x:4, y : 2},
{x:5, y : 5}
]
*/
},
//第三關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,0,1,1,1,1,1,1,0],
[0,1,1,1,0,0,0,0,1,0],
[1,1,3,0,0,1,1,0,1,1],
[1,3,3,0,0,0,0,0,0,1],
[1,3,3,0,0,0,0,0,1,1],
[1,1,1,1,1,1,0,0,1,0],
[0,0,0,0,0,1,1,1,1,0]
],
person: {x : 8, y : 3},
box: [{x:4, y : 2}, {x:3,y:3} ,{x:4, y:4},{x:5, y:3},{x:6, y:4}]
},
//第四關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,1,1,1,1,1,1,1,0,0],
[0,1,0,0,0,0,0,1,1,1],
[1,1,0,1,1,1,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,0,3,3,1,0,0,0,1,1],
[1,1,3,3,1,0,0,0,1,0],
[0,1,1,1,1,1,1,1,1,0]
],
person: {x : 2, y : 3},
box: [{x:2, y : 2}, {x:4,y:3} ,{x:6, y:4},{x:7, y:3},{x:6, y:4}]
},
//第五關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,1,1,1,1,0,0],
[0,0,1,3,3,1,0,0],
[0,1,1,0,3,1,1,0],
[0,1,0,0,0,3,1,0],
[1,1,0,0,0,0,1,1],
[1,0,0,1,0,0,0,1],
[1,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1]
],
person: {x : 4, y : 6},
box: [{x:4, y : 3}, {x:3,y:4} ,{x:4, y:5}, {x:5,y:5}]
/*
box : [
{x:3, y : 1},
{x:4, y : 1},
{x:4, y : 2},
{x:5, y : 5}
]
*/
},
//第六關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,0,0,1,1,1,1,1,1,1,0],
[0,0,0,0,1,0,0,1,0,0,1,0],
[0,0,0,0,1,0,0,0,0,0,1,0],
[1,1,1,1,1,0,0,1,0,0,1,0],
[3,3,3,1,1,0,0,0,0,0,1,1],
[3,0,0,1,0,0,0,0,1,0,0,1],
[3,0,0,0,0,0,0,0,0,0,0,1],
[3,0,0,1,0,0,0,0,1,0,0,1],
[3,3,3,1,1,1,0,1,0,0,1,1],
[1,1,1,1,1,0,0,0,0,0,1,0],
[0,0,0,0,1,0,0,1,0,0,1,0],
[0,0,0,0,1,1,1,1,1,1,1,0]
],
person: {x : 5, y : 10},
box: [
{x:5, y:6},
{x:6, y:3},
{x:6, y:5},
{x:6, y:7},
{x:6, y:9},
{x:7, y:2},
{x:8, y:2},
{x:9, y:6}
]
}
]
有一個很重要的東西就是推箱子游戲的主要邏輯:因為小烏龜走的地方只能是空白的區(qū)域,而且烏龜前面有墻就不能走, 或者烏龜前面是箱子,就再判斷箱子前面是否有墻, 如果沒有墻烏龜和箱子都可以走往前走一步,如果有墻就不能走。每一次小烏龜走了都改變地圖數(shù)據(jù),然后重新生成界面,如此循環(huán), 每一小烏龜走完都要檢測地圖數(shù)據(jù)中的箱子數(shù)據(jù)是否全對上了,對上了就給用戶提示, 并進(jìn)入下一關(guān);
游戲的模板引擎用了handlebarsJS, 可以去官網(wǎng)看API 。 這個是寫過的一篇博客,Handlebars的使用方法文檔整理(Handlebars.js):打開, 模板內(nèi)容:
<script id="tpl" type="text/x-handlebars-template">
{{#initY}}{{/initY}}
{{#each this}}
{{#each this}}
<div class="{{#getClass this}}{{/getClass}}" data-x="{{@index}}" data-y="{{#getY}}{{/getY}}" style="left:{{#calc @index}}{{/calc}};top:{{#calc 1111}}{{/calc}}">
<!--{{@index}}
{{#getY}}{{/getY}}
-->
</div>
{{/each}}
{{#addY}}{{/addY}}
{{/each}}
</script>
為Handlebars定了幾個helper,包括initY, getClass, getY,calc 、、、、,模板引擎主要是輔助的作用, 這邊用Handlebars不是很明智啊, 代碼的可讀性變差了點, 這里面也利用了閉包保存變量, 避免全局變量的污染:
(function() {
var y = 0;
Handlebars.registerHelper("initY", function() {
y = 0;
});
Handlebars.registerHelper("addY", function() {
y++;
});
Handlebars.registerHelper("getY", function() {
return y;
});
Handlebars.registerHelper("calc", function(arg) {
//console.log(arg)
if(arg!==1111) {
return 50*arg + "px";
}else{
return 50*y + "px";
};
});
Handlebars.registerHelper("getClass", function(arg) {
switch( arg ) {
case 0 :
return "bg"
case 1 :
return "block"
case 2 :
return "box"
case 3 :
return "target"
};
});
window.util = {
isMobile : function() {
return navigator.userAgent.toLowerCase().indexOf("mobile") !== -1 || navigator.userAgent.toLowerCase().indexOf("android") !== -1 || navigator.userAgent.toLowerCase().indexOf("pad") !== -1;
}
}
})();
因為要兼容移動端, 我們要檢查是否是手機或者平板,如果是的話,我就添加對應(yīng)的DOM元素(方向鍵DOM元素),然后綁定對應(yīng)的事件, zeptoJS提供了touch模塊,我們要去官網(wǎng)去找,然后額外引用進(jìn)來,打開地址 , 然后就可以使用swipeLeft,swipeUp,swipeDown, swipeRight 這幾個事件:
if( window.util.isMobile() ) {
$(window).on("swipeLeft",function() {
_this.step("left");
}).on("swipeRight",function() {
_this.step("right");
}).on("swipeUp",function() {
_this.step("top");
}).on("swipeDown",function() {
_this.step("bottom");
});
mobileDOM();
$(".arrow-up").tap(function() {
_this.step("top");
});
$(".arrow-down").tap(function() {
_this.step("bottom");
});
$(".arrow-left").tap(function() {
_this.step("left");
});
$(".arrow-right").tap(function() {
_this.step("right");
});
}else{
$(window).on("keydown", function(ev) {
var state = "";
switch( ev.keyCode ) {
case 37 :
state = "left";
break;
case 39 :
state = "right";
break;
case 38 :
state = "top";
break;
case 40 :
state = "bottom";
break;
};
_this.step(state)
});
};
因為要保存用戶的當(dāng)前關(guān)卡, 也額外引用了jQuery-cookies插件, 每一次闖關(guān)成功,我們就保存一次當(dāng)前的闖關(guān)記錄, 當(dāng)用戶不想玩或者別的原因關(guān)閉了瀏覽器, 過幾天想重新玩的時候可以繼續(xù)玩;
if( G.now+1 > G.level.length-1 ) {
alert("闖關(guān)成功");
return ;
}else{
//如果可用的等級大于當(dāng)前的等級,就把level設(shè)置進(jìn)去;
if( G.now+1 > parseInt( $.cookie('level') || 0 )) {
$.cookie('level' , G.now+1 , { expires: 7 });
};
start( G.now+1 );
return ;
};
所有的代碼在這里:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" >
<link rel="stylesheet" />
<script src="libs/jquery-1.9.1.min.js"></script>
<script src="libs/handlebars.js"></script>
<script src="libs/jquery-cookie.js"></script>
<script src="http://sqqihao.github.io/games/rusBlock/libs/Tiny-Alert/js/zepto.alert.js"></script>
<script id="tpl" type="text/x-handlebars-template">
{{#initY}}{{/initY}}
{{#each this}}
{{#each this}}
<div class="{{#getClass this}}{{/getClass}}" data-x="{{@index}}" data-y="{{#getY}}{{/getY}}" style="left:{{#calc @index}}{{/calc}};top:{{#calc 1111}}{{/calc}}">
<!--{{@index}}
{{#getY}}{{/getY}}
-->
</div>
{{/each}}
{{#addY}}{{/addY}}
{{/each}}
</script>
<script>
(function() {
var y = 0;
Handlebars.registerHelper("initY", function() {
y = 0;
});
Handlebars.registerHelper("addY", function() {
y++;
});
Handlebars.registerHelper("getY", function() {
return y;
});
Handlebars.registerHelper("calc", function(arg) {
//console.log(arg)
if(arg!==1111) {
return 50*arg + "px";
}else{
return 50*y + "px";
};
});
Handlebars.registerHelper("getClass", function(arg) {
switch( arg ) {
case 0 :
return "bg"
case 1 :
return "block"
case 2 :
return "box"
case 3 :
return "target"
};
});
window.util = {
isMobile : function() {
return navigator.userAgent.toLowerCase().indexOf("mobile") !== -1 || navigator.userAgent.toLowerCase().indexOf("android") !== -1 || navigator.userAgent.toLowerCase().indexOf("pad") !== -1;
}
}
})();
</script>
</head>
<style>
#game{
display: none;
}
#house{
position: relative;
}
.bg{
position: absolute;
width:50px;
height:50px;
box-sizing: border-box;
}
.block{
position: absolute;
background-image: url(imgs/wall.png);
width:50px;
height:50px;
box-sizing: border-box;
}
.box{
position: absolute;
background: #fbd500;
width:50px;
height:50px;
background-image: url(imgs/box.png);
}
.target{
position: absolute;
background: url(imgs/target.jpg);
background-size: 50px 50px;;
width:50px;
height:50px;
box-sizing: border-box;
}
#person{
background-image: url(imgs/person.png);
width:50px;
height:50px;
position: absolute;
}
#person.up{
background-position: 0 0;
}
#person.right{
background-position:-50px 0 ;
}
#person.bottom{
background-position:-100px 0 ;
}
#person.left{
background-position:-150px 0 ;
}
/*移動端的DOM*/
.operate-bar{
font-size:30px;
}
.height20percent{
height:30%;
}
.height30percent{
height:30%;
}
.height40percent{
height:40%;
}
.height100percent{
height:100%;
}
.font30{
font-size:30px;
color:#34495e;
}
</style>
<body>
<div id="select">
<div class="container">
<div class="row">
<p class="text-info">
已經(jīng)解鎖的關(guān)卡:
<p id="level">
</p>
</p>
<button id="start" class="btn btn-default">
開始游戲
</button>
</div>
</div>
</div>
<div id="game" class="container">
<div class="row">
<button onclick="location.reload()" class="btn btn-info" >
返回選擇關(guān)卡重新
</button>
<div id="house">
</div>
</div>
</div>
<script>
G = {
level: [
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,1,1,1,0,0,0,0],
[0,1,1,3,3,1,0,0,0],
[0,1,0,0,0,0,1,0,0],
[0,1,0,0,0,0,1,0,0],
[0,1,1,1,1,1,1,0,0]
],
person: {x : 2, y : 2},
box: [{x:3, y : 2},{x:4,y:2}]
},
//第二關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,1,1,1,1,1,0,0],
[0,1,0,0,1,1,1,0],
[0,1,0,0,0,0,1,0],
[1,1,1,0,1,0,1,1],
[1,3,1,0,1,0,0,1],
[1,3,0,0,0,1,0,1],
[1,3,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1]
],
person: {x : 2, y : 2},
box: [{x:3, y : 2}, {x:2,y:5} ,{x:5, y:6}]
/*
box : [
{x:3, y : 1},
{x:4, y : 1},
{x:4, y : 2},
{x:5, y : 5}
]
*/
},
//第三關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,0,1,1,1,1,1,1,0],
[0,1,1,1,0,0,0,0,1,0],
[1,1,3,0,0,1,1,0,1,1],
[1,3,3,0,0,0,0,0,0,1],
[1,3,3,0,0,0,0,0,1,1],
[1,1,1,1,1,1,0,0,1,0],
[0,0,0,0,0,1,1,1,1,0]
],
person: {x : 8, y : 3},
box: [{x:4, y : 2}, {x:3,y:3} ,{x:4, y:4},{x:5, y:3},{x:6, y:4}]
},
//第四關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,1,1,1,1,1,1,1,0,0],
[0,1,0,0,0,0,0,1,1,1],
[1,1,0,1,1,1,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,0,3,3,1,0,0,0,1,1],
[1,1,3,3,1,0,0,0,1,0],
[0,1,1,1,1,1,1,1,1,0]
],
person: {x : 2, y : 3},
box: [{x:2, y : 2}, {x:4,y:3} ,{x:6, y:4},{x:7, y:3},{x:6, y:4}]
},
//第五關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,1,1,1,1,0,0],
[0,0,1,3,3,1,0,0],
[0,1,1,0,3,1,1,0],
[0,1,0,0,0,3,1,0],
[1,1,0,0,0,0,1,1],
[1,0,0,1,0,0,0,1],
[1,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1]
],
person: {x : 4, y : 6},
box: [{x:4, y : 3}, {x:3,y:4} ,{x:4, y:5}, {x:5,y:5}]
/*
box : [
{x:3, y : 1},
{x:4, y : 1},
{x:4, y : 2},
{x:5, y : 5}
]
*/
},
//第六關(guān)
{
//0是空的地圖
//1是板磚
//3是目標(biāo)點
state:[
[0,0,0,0,1,1,1,1,1,1,1,0],
[0,0,0,0,1,0,0,1,0,0,1,0],
[0,0,0,0,1,0,0,0,0,0,1,0],
[1,1,1,1,1,0,0,1,0,0,1,0],
[3,3,3,1,1,0,0,0,0,0,1,1],
[3,0,0,1,0,0,0,0,1,0,0,1],
[3,0,0,0,0,0,0,0,0,0,0,1],
[3,0,0,1,0,0,0,0,1,0,0,1],
[3,3,3,1,1,1,0,1,0,0,1,1],
[1,1,1,1,1,0,0,0,0,0,1,0],
[0,0,0,0,1,0,0,1,0,0,1,0],
[0,0,0,0,1,1,1,1,1,1,1,0]
],
person: {x : 5, y : 10},
box: [
{x:5, y:6},
{x:6, y:3},
{x:6, y:5},
{x:6, y:7},
{x:6, y:9},
{x:7, y:2},
{x:8, y:2},
{x:9, y:6}
]
}
],
//map data
mapData : (function() {
var data = {};
return {
get: function () {
return data;
},
set: function (arg) {
data = arg;
},
//穿進(jìn)來的數(shù)據(jù)在界面中是否存在;
collision: function (x, y) {
if( data.state[y][x] === 1)return true;
return false;
},
collisionBox : function(x,y) {
for(var i= 0, len= data.box.length; i< len; i++) {
if( data.box[i].x === x&& data.box[i].y === y)return data.box[i];
};
return false;
}
}
})(),
view : {
initMap : function(map) {
document.getElementById("house").innerHTML = Handlebars.compile( document.getElementById("tpl").innerHTML )( map );
},
initPerson : function(personXY) {
var per = document.createElement("div");
per.id = "person";
G.per = per;
document.getElementById("house").appendChild(per);
per.style.left = 50* personXY.x+"px";
per.style.top = 50* personXY.y+"px";
},
initBox : function(boxs) {
for(var i=0;i<boxs.length; i++) {
var box = document.createElement("div");
box.className = "box";
G.box = box;
document.getElementById("house").appendChild(box);
box.style.left = boxs[i].x*50 + "px";
box.style.top = boxs[i].y*50 + "px";
};
},
deleteBox : function() {
var eBoxs = document.getElementsByClassName("box");
var len = eBoxs.length;
while( len-- ) {
eBoxs[len].parentNode.removeChild( eBoxs[len] );
};
}
},
/*
* 0;向上
* 1:向右
* 2:向下
* 3:向左
* */
direction : 0,
step : function(xy) {
//這里面要做很多判斷
/*包括:
用戶當(dāng)前的方向和以前是否一樣,如果不一樣要先轉(zhuǎn)頭;
如果一樣的話,判斷前面是否有石頭, 是否有箱子;
如果前面有墻壁或者
前面有箱子,而且箱子前面有墻壁就return
把人物往前移動
如果人物的位置上有一個箱子,把箱子也移動一下;
*/
var mapData = this.mapData.get();
//對參數(shù)進(jìn)行處理;
if ( typeof xy === "string" ) {
var x = 0, y = 0, xx = 0, yy = 0;
switch( xy ) {
case "left" :
if(this.direction==0){
x = -1;
xx = -2;
}else{
x = 0;
};
this.direction = 0;
break;
case "top" :
if(this.direction===1){
y = -1;
yy = -2
}else{
y = 0;
};
this.direction = 1;
break;
case "right" :
if(this.direction === 2) {
x = 1;
xx = 2;
}else{
x = 0;
};
this.direction = 2;
break;
case "bottom" :
if(this.direction ===3 ) {
y = 1;
yy = 2;
}else{
y = 0;
};
this.direction = 3;
};
//如果是墻壁就不能走
if( this.mapData.collision(mapData.person.x + x, mapData.person.y+y) ) {
return;
};
//如果碰到的是箱子, 而且箱子前面是墻壁, 就return
if( this.mapData.collisionBox(mapData.person.x+x, mapData.person.y+y) && this.mapData.collision(mapData.person.x+xx, mapData.person.y+yy)) {
return;
};
if( this.mapData.collisionBox(mapData.person.x+x, mapData.person.y+y) && this.mapData.collisionBox(mapData.person.x+xx, mapData.person.y+yy)) {
return
}
//mapData.x+xx, mapData.y+yy
mapData.person.x = mapData.person.x + x;
mapData.person.y = mapData.person.y + y;
this.per.style.left = 50* mapData.person.x+"px";
this.per.style.top = 50* mapData.person.y+"px";
this.per.className = {
0:"up",
1:"right",
2:"bottom",
3:"left"
}[this.direction];
var theBox = {};
if(theBox = this.mapData.collisionBox(mapData.person.x, mapData.person.y)) {
theBox.x = mapData.person.x+x;
theBox.y = mapData.person.y+y;
this.view.deleteBox();
this.view.initBox(mapData.box);
this.testSuccess();
};
//如果碰到了箱子,而且箱子前面不能走就return, 否則就走箱子和人物;
};
},
/*
* return Boolean;
* */
//遍歷所有的box,如果在box中的所有x,y在地圖中對應(yīng)的值為3,全部通過就返回true
testSuccess : function() {
var mapData = this.mapData.get();
for(var i=0; i<mapData.box.length; i++) {
if(mapData.state[mapData.box[i].y][mapData.box[i].x] != 3) {
return false;
};
};
$.dialog({
content : '游戲成功, 進(jìn)入下一關(guān)!',
title : 'alert',
ok : function() {
if( G.now+1 > G.level.length-1 ) {
alert("闖關(guān)成功");
return ;
}else{
//如果可用的等級大于當(dāng)前的等級,就把level設(shè)置進(jìn)去;
if( G.now+1 > parseInt( $.cookie('level') || 0 )) {
$.cookie('level' , G.now+1 , { expires: 7 });
};
start( G.now+1 );
return ;
};
},
cancel : function(){
location.reload();
},
lock : true
});
},
//這里面需要處理 map, 人物數(shù)據(jù), box數(shù)據(jù)
init : function() {
//更新地圖;
//this.level[0].state
this.view.initMap( this.mapData.get().state );
this.view.initPerson( this.mapData.get().person );
this.view.initBox( this.mapData.get().box );
//this.person = this.factory.Person(0,0);
//this.box = this.factory.Box([{x:0,y:1},{x:1,y:1},{x:0,y:2},{x:1,y:2}]);
if( this.hasBind ) {
return
};
this.hasBind = true;
this.controller();
},
controller : function() {
function mobileDOM() {
var mobileDOMString = '\
<div class="navbar-fixed-bottom height20percent operate-bar" >\
<div class="container height100percent">\
<div class="row text-center height100percent">\
<div class="height40percent arrow-up">\
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>\
</div>\
<div class="height30percent">\
<div class="col-xs-6 arrow-left">\
<span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>\
</div>\
<div class="col-xs-6 arrow-right">\
<span class="glyphicon glyphicon-arrow-right" aria-hidden="true"></span>\
</div>\
</div>\
<div class="height30percent arrow-down">\
<span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>\
</div>\
</div>\
</div>\
</div>\
';
+function addDOM() {
$("#game").append( mobileDOMString );
}();
};
var _this = this;
if( window.util.isMobile() ) {
$(window).on("swipeLeft",function() {
_this.step("left");
}).on("swipeRight",function() {
_this.step("right");
}).on("swipeUp",function() {
_this.step("top");
}).on("swipeDown",function() {
_this.step("bottom");
});
mobileDOM();
$(".arrow-up").tap(function() {
_this.step("top");
});
$(".arrow-down").tap(function() {
_this.step("bottom");
});
$(".arrow-left").tap(function() {
_this.step("left");
});
$(".arrow-right").tap(function() {
_this.step("right");
});
}else{
$(window).on("keydown", function(ev) {
var state = "";
switch( ev.keyCode ) {
case 37 :
state = "left";
break;
case 39 :
state = "right";
break;
case 38 :
state = "top";
break;
case 40 :
state = "bottom";
break;
};
_this.step(state)
});
};
}
};
function start( level ) {
G.now = level;
G.mapData.set(G.level[level] );
G.init();
$("#game").show();
$("#select").hide();
};
function init() {
var cookieLevel = $.cookie('level') || 0;
start( cookieLevel );
};
$("#start").click(function() {
init();
});
String.prototype.repeat = String.prototype.repeat || function(num) {
return (new Array(num+1)).join( this.toString() );
};
window.onload = function() {
var cookieLevel = $.cookie('level') || 0;
$("#level").html( function() {
var index = 0;
return "<a href='###' class='btn btn-info' onclick='start({{i}})'>關(guān)卡</a> ".repeat((parseInt($.cookie('level')) || 0)+1).replace(/{{i}}/gi, function() {
return index++;
})
});
}
</script>
</body>
</html>
游戲一共有6關(guān), 每一關(guān)成功通過即可解鎖下一關(guān), 地圖的話其實可以多找些的,哈哈;
推箱子游戲的在線DEMO : 打開
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
相關(guān)文章
將HTML格式的String轉(zhuǎn)化為HTMLElement的實現(xiàn)方法
本節(jié)主要介紹了將HTML格式的String轉(zhuǎn)化為HTMLElement的實現(xiàn)方法,需要的朋友可以參考下2014-08-08
JavaScript直播評論發(fā)彈幕切圖功能點集合效果代碼
這篇文章主要介紹了JavaScript直播評論發(fā)彈幕切圖功能點集合效果代碼的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-06-06
es6 filter() 數(shù)組過濾方法總結(jié)
這篇文章主要介紹了es6 filter() 數(shù)組過濾方法總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
arctext.js實現(xiàn)文字平滑彎曲弧形效果的插件
這篇文章主要介紹了arctext.js實現(xiàn)文字平滑彎曲弧形效果的插件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
JavaScript canvas實現(xiàn)圍繞旋轉(zhuǎn)動畫
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實現(xiàn)圍繞旋轉(zhuǎn)動畫,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11
腳本之家貼圖轉(zhuǎn)換+轉(zhuǎn)貼工具用到的js代碼超級推薦
[紅色]腳本之家貼圖轉(zhuǎn)換+轉(zhuǎn)貼工具用到的js代碼超級推薦...2007-04-04

