继上一节我们已经在画面上完成了数字盒子的绘制,现在我们就启动游戏主循环,在主循环中驱动游戏流程,在此,我们先实现盒子从上往下落的效果。在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把该字符串显示到页面上,完成这些代码后,加载页面,可以看到如下效果:
再下一节,我们将在此基础上完成盒子被爆破的效果,并实现界面美化,最后使得我们的游戏变得像本节刚开始介绍时得样子。
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号: