GC DevKit 快速入门 -- 游戏概览(三)
生活随笔
收集整理的這篇文章主要介紹了
GC DevKit 快速入门 -- 游戏概览(三)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
接上節(jié) http://www.cnblogs.com/hangxin1940/archive/2013/04/11/3015553.html ## 啟動(dòng)流程 在構(gòu)造函數(shù)`init`中,我們通過監(jiān)聽`'app:start'`事件來處理上層的通知,然后調(diào)用 `start_game_flow` 方法來播放動(dòng)畫序列,最后調(diào)用`play_game`來開始游戲。 function start_game_flow () { var that = this; animate(that._scoreboard).wait(1000) .then(function () { that._scoreboard.setText(text.READY); }).wait(1500).then(function () { that._scoreboard.setText(text.SET); }).wait(1500).then(function () { that._scoreboard.setText(text.GO); //開始游戲 ... game_on = true; play_game.call(that); }); } `Ready, Set, Go!`這三個(gè)單詞在切換時(shí),有一個(gè)短暫的停頓,每次都會(huì)更新計(jì)分板的內(nèi)容,并且加載下一步動(dòng)畫。在最后一步動(dòng)畫,會(huì)調(diào)用`play_game.call(that)`方法。`that`只是`this`的一個(gè)引用而已,只是方便在不同的上下文中進(jìn)行正確的引用。 ## 游戲開始 `play_game` 函數(shù)包含了幾個(gè)定時(shí)器,`tick`函數(shù)用來隨機(jī)的讓鼴鼠從洞中冒出來,一個(gè)計(jì)時(shí)器有來每秒鐘在一個(gè)`TextView`更新倒計(jì)時(shí),并且在超過時(shí)間時(shí)結(jié)束游戲。 function play_game () { var i = setInterval(bind(this, tick), mole_interval), j = setInterval(bind(this, update_countdown), 1000); //復(fù)位所有定時(shí)器、標(biāo)記以及倒計(jì)時(shí) setTimeout(bind(this, function () { game_on = false; clearInterval(i); clearInterval(j); setTimeout(bind(this, end_game_flow), mole_interval * 2); this._countdown.setText(":00"); }), game_length); //讓倒計(jì)時(shí)可見,并且刪除開始提示信息 setTimeout(bind(this, function () { this._scoreboard.setText(score.toString()); this._countdown.style.visible = true; }), game_length * 0.25); //沒有時(shí)間時(shí),置紅倒計(jì)時(shí)文字 setTimeout(bind(this, function () { this._countdown.updateOpts({color: '#CC0066'}); }), game_length * 0.75); } function tick () { //隨機(jī)選擇一個(gè)鼴鼠 var len = this._molehills.length, molehill = this._molehills[Math.random() * len | 0]; //如果選擇鼴鼠已經(jīng)是激活的,那么選擇另一個(gè) while (molehill.activeMole) { molehill = this._molehills[Math.random() * len | 0]; } molehill.showMole(); } function update_countdown () { countdown_secs -= 1; this._countdown.setText(":" + (("00" + countdown_secs).slice(-2))); } ## 結(jié)束序列 在游戲倒計(jì)時(shí)結(jié)束后,游戲的結(jié)束動(dòng)畫就會(huì)開始,由`end_game_flow`函數(shù)播放,它會(huì)檢查游戲得分,并且將它顯示出來,而鼴鼠則持續(xù)不斷的冒出就好像它在嘲笑你。 function end_game_flow () { var isHighScore = (score > high_score), end_msg = get_end_message(score, isHighScore); this._countdown.setText(''); //清除倒計(jì)時(shí)信息 //重設(shè)記分牌 this._scoreboard.updateOpts({ text: '', x: 10, size: 17, verticalAlign: 'top', textAlign: 'left', multiline: true }); //檢查是否是最高分并播放相應(yīng)動(dòng)畫 if (isHighScore) { high_score = score; this._molehills.forEach(function (molehill) { molehill.endAnimation(); }); } else { var i = (this._molehills.length-1) / 2 | 0; //居中鼴鼠 this._molehills[i].endAnimation(true); } this._scoreboard.setText(end_msg); //短時(shí)間的延遲再允許觸摸復(fù)位 setTimeout(bind(this, emit_endgame_event), 2000); } 一旦新的記分板被設(shè)置,并且鼴鼠動(dòng)畫正在播放,會(huì)在2秒的時(shí)間后來監(jiān)聽用戶的觸摸事件 function emit_endgame_event () { this.once('InputSelect', function () { this.emit('gamescreen:end'); reset_game.call(this); }); } 用戶點(diǎn)擊后,一個(gè)`gamescreen:end`事件會(huì)被發(fā)送,上層程序所處理這個(gè)事件,之后視圖堆棧會(huì)彈出并關(guān)閉這個(gè)游戲視圖,顯示出標(biāo)題視圖,以便用戶重新開始游戲。 ## 鼴鼠資源:`MoleHill.js` `MoleHill`類是另外一個(gè)比較大的類,它存放于`./src/MoleHill.js` ## 對齊組件 一個(gè)鼴鼠洞是由3種圖像堆疊而成的:底層的鼴鼠洞,鼴鼠,以及上層的鼴鼠洞。鼴鼠的動(dòng)畫是在Y軸進(jìn)行上下活動(dòng),并且會(huì)給它一個(gè)矩形遮罩,用以蓋住鼴鼠圖片超出的部分。鼴鼠看起來就像跳出洞口等待敲它一樣。 this.build = function () { var hole_back = new ui.ImageView({ superview: this, image: hole_back_img, //... }); this._inputview = new ui.View({ superview: this, clip: true, //... }); this._moleview = new ui.ImageView({ superview: this._inputview, image: mole_normal_img, //... }); var hole_front = new ui.ImageView({ superview: this, canHandleEvents: false, image: hole_front_img, //... }); //... this._inputview.on('InputSelect', bind(this, function () { if (this.activeInput) { sound.play('whack'); this.emit('molehill:hit'); this.hitMole(); } })); }; 這副圖形象的說明了三個(gè)`ImageView`是如何摞成一個(gè)鼴鼠的:  如果鼴鼠的身體下方伸出了鼴鼠洞那就完蛋了,我們必須讓人感覺鼴鼠的身體下部分在草地下面。這里可以使用剪貼蒙板來創(chuàng)建一個(gè)新的`View`,只需要將`clip`屬性置為`true`,這樣任何附加于這個(gè)視圖的子視圖將只顯示它范圍內(nèi)的圖像。在上面的圖中,鼴鼠只顯示它所附加的剪貼蒙板中自己的圖像(黑色方框內(nèi))。 我們同樣也將這個(gè)剪貼蒙板視作一個(gè)按鈕區(qū)域,用來檢測是玩家否敲到正確的鼴鼠身上,只要觸摸落在矩形區(qū)域內(nèi),并且鼴鼠是被激活的,都視為一次成功的敲擊。但是,還有一個(gè)問題,用戶的輸入被鼴鼠圖像捕獲,但是在它之前還有一個(gè)鼴鼠洞的圖像,它遮住了下面的區(qū)域,這樣使得事件不能被正常的處理。我們可以通過將上層圖像的`canHandleEvents`屬性設(shè)置為`false`,來讓觸摸事件達(dá)到預(yù)期效果。它可以讓事件`穿過`這個(gè)視圖,繼而讓下方的控件捕獲。 此外,在`build`函數(shù)中,我們給`Animator`對象賦了一個(gè)函數(shù)引用,我們將在游戲過程中使用到它。 this._animator = animate(this._moleview); 我們可以在任意時(shí)間執(zhí)行這個(gè)函數(shù),用來播放鼴鼠動(dòng)畫,當(dāng)然它不會(huì)視為有效的游戲動(dòng)作。這樣引用有個(gè)好處,每次想播放動(dòng)畫時(shí)是要調(diào)用它就行,不必每次都創(chuàng)建一個(gè)新的`Animator`對象。 ## 鼴鼠動(dòng)畫 `MoleHill`類中定義了三個(gè)動(dòng)畫序列:鼴鼠跳出洞、鼴鼠回洞以及結(jié)束動(dòng)畫中鼴鼠慢慢的出來并"嘲笑"玩家。它們都使用`Animator`對象進(jìn)行定義: //鼴鼠出洞 this.showMole = function () { if (this.activeMole === false) { this.activeMole = true; this.activeInput = true; this._animator.now({y: mole_up}, 500, animate.EASE_IN) .wait(1000).then(bind(this, function () { this.activeInput = false; })).then({y: mole_down}, 200, animate.EASE_OUT) .then(bind(this, function () { this.activeMole = false; })); } }; //打鼴鼠 this.hitMole = function () { if (this.activeMole && this.activeInput) { this.activeInput = false; this._animator.clear() .now((function () { this._moleview.setImage(mole_hit_img); }).bind(this)) .then({y: mole_down}, 1500) .then(bind(this, function () { this._moleview.setImage(mole_normal_img); this.activeMole = false; this.activeInput = false; })); } }; //結(jié)束動(dòng)畫 this.endAnimation = function () { this.activeInput = false; this._animator.then({y: mole_up}, 2000) .then(bind(this, function () { this._interval = setInterval(bind(this, function () { if (this._moleview.getImage() === mole_normal_img) { this._moleview.setImage(mole_hit_img); } else { this._moleview.setImage(mole_normal_img); } }), 100); })); }; `animate`函數(shù)插入了一個(gè)JavaScript對象屬性,如果它傳入了一個(gè)`View`對象,那么會(huì)為其插入這個(gè)對象的樣式屬性。這種方式十分的便利,因?yàn)楹苡锌梢晕覀儠?huì)基于當(dāng)前樣式進(jìn)行動(dòng)畫。 舉個(gè)例子,如果一個(gè)鼴鼠在洞中,我們讓它出洞,一下是`showMole`函數(shù): this._animator.now({y: mole_up}, 500, animate.EASE_IN) .wait(1000).then(bind(this, function () { this.activeInput = false; })).then({y: mole_down}, 200, animate.EASE_OUT) .then(bind(this, function () { this.activeMole = false; })); 首先,動(dòng)畫對象調(diào)用 `.now({y: mole_up}, 500, animate.EASE_IN)` 函數(shù),它會(huì)立即操作動(dòng)畫對象的Y軸屬性,并且把它定義為`this._moleview`對象。因?yàn)橹饕膭?dòng)畫是一個(gè)`View`類的實(shí)例,我們實(shí)際上實(shí)在操作他的 `style.y` 屬性,或者說鼴鼠圖像在屏幕上的垂直位置。`mole_up`變量在文件一開始被設(shè)置為5,它是想對于父視圖`this._inputview`的偏移量。這個(gè)動(dòng)畫的第一步執(zhí)行了半秒鐘/500毫秒,緩慢的移動(dòng)到最終位置,最終鼴鼠露出了頭。 然后,第二部分的動(dòng)畫會(huì)執(zhí)行`.wait(1000)`方法暫停1秒,然后繼續(xù)下一個(gè)動(dòng)畫。這樣看起來,鼴鼠會(huì)鉆出洞后然后飛快的又進(jìn)到洞里。如果這段時(shí)間點(diǎn)擊鼴鼠,就會(huì)被記上分?jǐn)?shù)。 最后 `.then( ... )` 被調(diào)用,它通過一個(gè)回調(diào)函數(shù)被立即執(zhí)行,這個(gè)方法將鼴鼠洞的`activeInput`置為`false`,這樣這個(gè)鼴鼠洞就不會(huì)接受輸入事件。這個(gè)動(dòng)作結(jié)束,動(dòng)畫會(huì)進(jìn)入下一個(gè)動(dòng)畫序列。 我們現(xiàn)在期望鼴鼠能回到洞里,所以調(diào)用 `.then({y: mole_down}, 200, animate.EASE_OUT)` ,正如我們看到的那樣,` .then`函數(shù)可以用多種方式來調(diào)用。這里,我們通過之前的` .now() `來調(diào)用,這把鼴鼠在Y軸的位置進(jìn)行改變,使之緩慢的降低,進(jìn)入洞中。 整個(gè)動(dòng)畫結(jié)束后,我們最后使用一次 `.then( ... )` 來讓這個(gè)鼴鼠的屬性`activeMole`變?yōu)?#96;false`,整個(gè)動(dòng)畫流程就結(jié)束了。 ## 聲音 我們使用一個(gè)單獨(dú)的控制器來加入聲音,它位于`./src/soundcontroller.js`: import AudioManager; exports.sound = null; exports.getSound = function () { if (!exports.sound) { exports.sound = new AudioManager({ path: 'resources/sounds', files: { levelmusic: { path: 'music', volume: 0.5, background: true, loop: true }, whack: { path: 'effect', background: false } } }); } return exports.sound; }; 在這里,我們在程序啟動(dòng)時(shí)創(chuàng)建了一個(gè)`AudioManager`對象,并且在任何時(shí)候調(diào)用`getSound`函數(shù)都會(huì)返回這個(gè)對象。 我們回到 `./src/Application.js` 文件的 `initUI` 函數(shù)來看看它的使用細(xì)節(jié)。 this.initUI = function () { //... var sound = soundcontroller.getSound(); //... titlescreen.on('titlescreen:start', function () { sound.play('levelmusic'); GC.app.view.push(gamescreen); GC.app.emit('app:start'); }); gamescreen.on('gamescreen:end', function () { sound.stop('levelmusic'); GC.app.view.pop(); }); }; 當(dāng)用戶按下開始按鈕后,`titlescreen:start`事件會(huì)被觸發(fā),背景音樂就會(huì)被播放。如果`levelmusic`的 `loop` 屬性為`true`,那么整個(gè)聲音會(huì)被循環(huán)播放,直到游戲結(jié)束,這些都在 `./src/soundcontroller.js` 文件中的`new AudioManager(...)`中設(shè)置 ## 總結(jié) 打鼴鼠游戲很簡單,但它是一個(gè)可工作的完整的游戲,我們通過它學(xué)習(xí)了引擎的api如何組織到一起。
轉(zhuǎn)載于:https://www.cnblogs.com/hangxin1940/archive/2013/04/13/3017640.html
總結(jié)
以上是生活随笔為你收集整理的GC DevKit 快速入门 -- 游戏概览(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sql删除重复数据
- 下一篇: asp.net中缓存Cache类的使用案