繼上一節我們已經在畫面上完成了數字盒子的繪制,現在我們就啟動游戲主循環,在主循環中驅動游戲流程,在此,我們先實現盒子從上往下落的效果。在gamescenecomponent.vue中添加一下代碼:
<script>
export default {
data () {
return {
fallingSpeed: 0.8,
ticksPerNewBox: 80
....
}
代碼中添加的兩個變量將用來控制數字盒子下落的速度。createjs庫給我們提供一種有效的動畫實現機制,它會導出一個Ticker類,該類提供了一個接口setFPS, 例如通過調用createjs.Ticker.setFPS(40), 那么createjs就能對頁面在一秒內進行40次刷新,每次刷新時會發出一個'tick'消息,我們只要監聽這個消息,并提供會調函數,那么createjs就會在一秒內回調我們的函數40次,在該函數中,我們再通過createjs提供的其他接口繪制頁面就能實現動畫效果了。因此我們繼續添加相關代碼:
methods: {
init () {
this.createjs = window.createjs
this.canvas = document.getElementById('canvas')
this.stage = new this.createjs.Stage(this.canvas)
this.createjs.Ticker.setFPS(40)
this.createjs.Ticker.addEventListener('tick', this.tick)
},
tick (e) {
this.stage.update()
if (!e.paused) {
this.moveObjects()
var ticksCount = this.createjs.Ticker.getTicks(true)
if (ticksCount % this.ticksPerNewBox === 0) {
this.generateNumberBox()
}
}
},
moveObjects () {
for (var i = 0, len = this.numberBoxes.length; i < len; i++) {
var box = this.numberBoxes[i]
box.y += this.fallingSpeed
}
},
....
}
在初始化函數init中,我們讓createjs一秒內回調我們提供的tick回調函數40次,createjs不斷的回調我們的tick函數,這個情況實質上構成了游戲的主循環,在上一個游戲神廟逃亡中,我們是通過一個for循環來實現游戲主循環的,這里我們通過createjs的定時回調機制實現游戲的主循環。
在tick函數被回調時,createjs會給它傳遞一個參數,我們通過讀取這個參數的paused值用于判斷游戲是否處于暫停狀態,如果不是,那么我們調用moveObjects,移動頁面上各個成員的位置,這種移動就構成了一種動畫效果,由于頁面里的成員都是數字盒子,因此調用moveObjects將實現數字盒子從上往下落的效果。
通過getTicks接口,我們能獲得當前函數被回調了多少次,如果回調的次數正好是80的倍數,也就是this.ticksPerNewBox的值的倍數時,我們通過this.generateNumberBox()在頁面上繪制新的數字盒子。
moveObjects()接口的實現邏輯是,遍歷當前所有數字盒子,分別把他們的y坐標加上this.fallingSpeed,也就是0.8, 于是每次頁面刷新時,頁面上的數字盒子坐標總往下挪動0.8個單位。以上所有代碼完成后,加載頁面得到效果如下:
可以看到有很多數字盒子在單位時間內從頂部紛紛往下落。
接下來我們需要完成的,是在底部添加一個數字鍵盤,游戲的玩法是,玩家在底部數字鍵盤點擊選取兩個值后,如果兩個值的乘機與盒子中的數值相等,那么盒子就會被爆破掉。首先在template標簽中添加以下代碼:
<template>
<div>
<canvas id="canvas" width="300" height="480">
</canvas>
<div id="control-box">
<a class="control" v-for="n in 12" :data-value="n" href=# @click="controlClicked">
{{n}}
</a>
</div>
</div>
</template>
我們通過VUE的v-for指令,循環生成12個下面代碼所描述的DOM元素:
<a class="control" data-value="1" href="#" @click="controlClicked"></a>
這些元素將在頁面上被繪制成兩排數字鍵盤,接著再style標簽區域添加樣式代碼:
<style scoped>
#canvas {
background: #333;
}
#control-box {
width: 100%;
overflow: auto;
position: absolute;
bottom: 0;
}
.control {
display: block;
float: left;
width: 50px;
height: 50px;
background: gray;
text-align: center;
line-height: 50px;
font-size: 24px;
font-family: impact;
}
.control.active {
background: white;
color: red;
}
</style>
代碼完成后,加載如瀏覽器,你可以看到如下效果:
現在點擊鍵盤的話,頁面是沒有反應的,接下來我們添加鍵盤點擊后的響應函數,在script標簽中添加如下代碼:
export default {
data () {
return {
....
calculationText: null,
controlHeight: 100,
inputs: [],
result: 1
}
},
methods: {
init () {
this.createjs = window.createjs
this.canvas = document.getElementById('canvas')
this.stage = new this.createjs.Stage(this.canvas)
this.createjs.Ticker.setFPS(40)
this.createjs.Ticker.addEventListener('tick', this.tick)
this.calculationText = new this.createjs.Text('1X1=1', '18px Impact', 'White')
this.calculationText.textAlign = 'center'
this.calculationText.x = this.gameWidth / 2
this.calculationText.y = this.gameHeight - this.controlHeight - 30
this.stage.addChild(this.calculationText)
},
updateText (string) {
this.calculationText.text = string
},
controlClicked (e) {
var value = e.target.dataset.value
var string = this.addInput(value)
this.updateText(string)
},
addInput (value) {
if (this.inputs.length >= 2) {
this.clearInputs()
}
this.inputs.push(value)
this.result *= value
return this.inputs.join('X') + '=' + this.result
},
clearInputs () {
this.inputs.length = 0
this.result = 1
},
....
}
}
calculationText是顯示在頁面上的字符串對象,在init函數里初始化后加入到stage容器中,當鍵盤的按鍵被點擊時,由于我們通過@click指令進行綁定的緣故,一旦按鍵點擊后,controlClicked函數會被調用,該函數調用時會把點擊事件對象當做參數傳給我們,通過該對象的target成員,我們就能獲得按鍵的DOM對象,注意我們在前面實現的12個按鍵對象時,在里面添加一個屬性叫data-value,該屬性的值就是按鍵在頁面上顯示的值,通過e.target.dataset就是在讀取data-value屬性,e.target.dataset.value就是獲得data-value對應的屬性值。
讀取到按鍵的data-value屬性值后,我們就知道用戶點擊了哪個按鍵,并獲得了按鍵的數值,然后把該數值傳遞給addInput函數,這個函數的作用是把用戶點擊的按鈕值構建成一個字符串,加入用戶點擊了按鈕"1"和"2",那么addInput就會構造出字符串"1X2=2",接著調用updateText把該字符串顯示到頁面上,完成這些代碼后,加載頁面,可以看到如下效果:
再下一節,我們將在此基礎上完成盒子被爆破的效果,并實現界面美化,最后使得我們的游戲變得像本節剛開始介紹時得樣子。
更多技術信息,包括操作系統,編譯器,面試算法,機器學習,人工智能,請關照我的公眾號: