Javascript編寫(xiě)俄羅斯方塊思路及實(shí)例
俄羅斯方塊這個(gè)游戲也做了移動(dòng)端的兼容, 這個(gè)游戲難點(diǎn)是怎么翻轉(zhuǎn)方塊, 自己實(shí)現(xiàn)的方式是把方塊放到一個(gè)二維數(shù)組, 然后逆時(shí)針旋轉(zhuǎn)二維數(shù)組。
也有別的方法,比如直接用一個(gè)全局變量代表一個(gè)方向, 翻轉(zhuǎn)的時(shí)候根據(jù)這個(gè)變量轉(zhuǎn)動(dòng)方塊, 但是代碼要寫(xiě)更多。
在文庫(kù)搜索到了一篇關(guān)于算法的文章, ....看著好心塞:

游戲截圖PC端:

游戲截圖移動(dòng)端:

模板引擎用了HandlebarsJS, 為了更好的模塊化,也用了requireJS....沒(méi)用好;
運(yùn)行下面代碼
var cfg = {
width:14,
height:20,
time : 400
};
requirejs.config({
baseUrl: 'libs',
paths: {
app: '../app'
}
});
requirejs(["app/controller/mainController","app/view/mobileDOM","app/util"], function(con, mobileDOM, util) {
if(util.isMobile()) {
mobileDOM.addDOM();
};
con();
});
游戲主要有三個(gè)模型層: 游戲方塊的模型層, 游戲分?jǐn)?shù)的模型層, 游戲整體界面結(jié)構(gòu)模型層;
控制層就一個(gè), 就是用戶(hù)點(diǎn)擊游戲開(kāi)始的按鈕, 游戲就開(kāi)始了, 如果是PC,就會(huì)監(jiān)聽(tīng)keydown事件, 如果是移動(dòng)端, 就新建四個(gè)方向鍵的DOM, 監(jiān)聽(tīng)方向鍵的點(diǎn)擊事件,事件會(huì)使當(dāng)前方塊的數(shù)據(jù)模型發(fā)生旋轉(zhuǎn), 至于顯示,那是view層的事情,先不用管, 主要的邏輯包括方塊的隨機(jī)生成, 方塊的碰撞檢測(cè),方塊的消除,分?jǐn)?shù)的增加, 重新隨機(jī)生成方塊等:
運(yùn)行下面代碼
define(["app/util"],function(util) {
//分?jǐn)?shù)模塊,游戲開(kāi)始的時(shí)候會(huì)用到;
var score = {};
require(["app/model/score"],function(defineScore) {
score = defineScore;
});
var startGame = function() {
//把當(dāng)前的input元素禁用;
$(this).attr("disabled","true");
requirejs(["app/model/data","app/view/init","app/model/Block"], function(data, view, Block){
//初始化方塊;
var block = new Block;
var mapData = {};
//方塊發(fā)生改變的時(shí)候,我們用回調(diào)重新渲染界面;
block.onupdate( function() {
var blockData = this.get();
//把數(shù)據(jù)格式轉(zhuǎn)化成map數(shù)據(jù);
mapData = data.extend(blockData);
$("#table").html( view( mapData ) );
});
block.testTouch = data.testTouch;
//如果元素觸底了或者是元素已經(jīng)被卡主不能動(dòng)的情況下;
block.onend(function() {
//這個(gè)說(shuō)明當(dāng)前的block觸底了
data.set( mapData );
//我們需要重新生成一個(gè)方塊, 直接調(diào)用newBlock即可;
block.newBlock();
//通過(guò)data計(jì)算,如果有連接起來(lái)的一條線(xiàn),就執(zhí)行SCORE回調(diào), 隨之會(huì)更新當(dāng)前界面的分值;
//如果方塊跑到了最上面就是游戲失敗了;
data.oncalculate( score.addScore , block.destory.bind(block));
});
//現(xiàn)在才開(kāi)始綁定事件
if(!util.isMobile()) {
$(window).keydown(function(ev) {
if(ev.keyCode === 37) {
block.add(block.moveLeft,"left");
}else if( ev.keyCode === 39 ) {
block.add(block.moveRight,"right");
}else if( ev.keyCode === 40 ) {
block.add(block.moveDown,"down");
}else if( ev.keyCode === 38 ) {
block.rotate();
};
});
}else{
$(".arrow-up").tap(function() {
block.rotate();
});
$(".arrow-down").tap(function() {
block.add(block.moveDown,"down");
});
$(".arrow-left").tap(function() {
block.add(block.moveLeft,"left");
});
$(".arrow-right").tap(function() {
block.add(block.moveRight,"right");
});
};
});
};
//綁定界面事件 ,keyDown;
var bindEvent = function() {
//start....
$("#start").click(startGame)
};
//為移動(dòng)端添加DOM節(jié)點(diǎn),
//然后綁定移動(dòng)端的事件;
return function() {
bindEvent();
};
});
游戲的主要窗口直接看成是二維數(shù)組, 所有要顯示的方塊都是數(shù)組中的數(shù)據(jù), 通過(guò)模板引擎, 一秒鐘更新一次data到view, 模板如下:
運(yùn)行下面代碼
<script type="text/x-handlebars-template" id="tpl-td">
{{#each this}}
<tr>
{{#each this}}
<td class="{{#if this}}block{{/if}}">
</td>
{{/each}}
</tr>
{{/each}}
</script>
為了讓整體的內(nèi)容和提示更加美觀,用了提示插件 zepto.alert和bootStrap;
在線(xiàn)DEMO:打開(kāi)
相關(guān)文章
淺析location.href跨窗口調(diào)用函數(shù)
本文詳細(xì)介紹了location.href跨窗口調(diào)用函數(shù),具體的使用方法及實(shí)例,有需要的朋友可以參考下2016-11-11
JavaScript使用focus()設(shè)置焦點(diǎn)失敗的解決方法
這篇文章主要介紹了JavaScript使用focus()設(shè)置焦點(diǎn)失敗的一個(gè)解決方法 ,需要的朋友可以參考下2014-09-09
js函數(shù)參數(shù)設(shè)置默認(rèn)值的一種變通實(shí)現(xiàn)方法
js函數(shù)中有個(gè)儲(chǔ)存參數(shù)的數(shù)組arguments,因此js版支持參數(shù)默認(rèn)值的函數(shù)可以通過(guò)另外一種變通的方法實(shí)現(xiàn)2014-05-05
JavaScript6 let 新語(yǔ)法優(yōu)勢(shì)介紹
這篇文章主要介紹了JavaScript6 let 新語(yǔ)法優(yōu)勢(shì)介紹的相關(guān)資料,需要的朋友可以參考下2016-07-07
JavaScript中幾種常見(jiàn)排序算法小結(jié)
JavaScript中幾種常見(jiàn)排序算法小結(jié),學(xué)習(xí)js的朋友可以參考下,下面對(duì)多種方法進(jìn)行了簡(jiǎn)單的小結(jié)。2011-02-02
現(xiàn)代 JavaScript 開(kāi)發(fā)編程風(fēng)格Idiomatic.js指南中文版
下面的章節(jié)描述的是一個(gè) 合理 的現(xiàn)代 JavaScript 開(kāi)發(fā)風(fēng)格指南,并非硬性規(guī)定。其想送出的核心理念是高度統(tǒng)一的代碼風(fēng)格(the law of code style consistency)。2014-05-05

