上节,我们完成了数字盒子的下落以及数字键盘的实现,当玩家点击键盘,点击的按键乘机等于下落的盒子数值时,游戏会把盒子给爆破掉,现在我们就来实现这个机制。
要实现爆破效果,我们需要使用另一个第三方库tweenjs-0.5.1.min.js,先在index.html中添加对该库的引入:
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="text/javascript" src="./static/tweenjs-0.5.1.min.js"></script>
<script type="text/javascript" src="./static/easeljs-0.7.1.min.js"></script>
<script type="text/javascript">
window.createjs = createjs
</script>
<title>Multiply Defense</title>
</head>
接着我们在页面下方画一条分界线,盒子一旦落入分界线下面,盒子应该自动消失掉,相应代码实现如下:
export default {
data () {
....
boundaryY: 320
....
}
我们把这条分界线放在y坐标为320个像素单位处,然后我们在指定位置绘制一条红线:
methods: {
init () {
....
var line = this.rectShape(this.gameWidth, 3, {fillColor: '#600'})
if (line.y === undefined) {
console.log('line.y is null')
}
line.y = this.boundaryY
this.stage.addChild(line)
....
}
}
完成这些代码后,加载页面会看到有一条红线横躺在界面上:
当盒子越过红线时,我们需要把盒子从页面上抹去。负责盒子下落的是函数moveObjects, 因此我们需要在该函数中判断每个盒子的y坐标,如果坐标超过了红线所在的位置,那么我们就得把它从页面上清除掉,相应的代码如下:
moveObjects () {
var p = 0
while (p < this.numberBoxes.length) {
var box = this.numberBoxes[p]
if (box.y > this.boundaryY) {
this.removeNumberBox(box)
} else {
box.y += this.fallingSpeed
p++
}
}
},
removeNumberBox (target) {
for (var i = 0, len = this.numberBoxes.length; i < len; i++) {
var box = this.numberBoxes[i]
if (box === target) {
this.numberBoxes.splice(i, 1)
this.stage.removeChild(box)
return
}
}
}
在moveObjects中,我们会循环查看所有盒子的坐标,如果盒子坐标没有超过红线,那么我们让盒子继续下降,如果超过了,则调用removeNumberBox()来实现盒子的清除,在removeNumberBox中,我们把超过红线的盒子在数组中找到,并把它从数组中移除,由于原来盒子是作为stage的孩子添加的,为了让页面不再显示给定盒子,我们通过removeChild把盒子从stage容器中去除,这样当页面再次调用stage.update()刷新时,被移除的盒子将不会再出现在页面上。
接着我们要实现盒子的爆破效果,当玩家点击数字键盘,按键的乘机等于给定盒子的数值时,我们要在盒子表明实现一个绿色的圆圈,等圆圈消失后,把盒子从页面上移除,这样就实现盒子的爆破效果,具体效果如下:
绿色圆圈处原来是一个数字盒子,当盒子被爆破时,圆圈出现,然后盒子消失。我们看看它的代码是如何实现的:
methods: {
....
controlClicked (e) {
var value = e.target.dataset.value
var string = this.addInput(value)
this.updateText(string)
this.checkResult()
},
....
findNumberBoxWithValue (value) {
for (var i = 0, len = this.numberBoxes.length; i < len; i++) {
var box = this.numberBoxes[i]
if (box.value === value) {
return box
}
}
},
checkResult () {
var box = this.findNumberBoxWithValue(this.result)
if (box) {
this.showCircle(box.x, box.y)
this.removeNumberBox(box)
this.clearInputs()
}
},
showCircle (x, y) {
var circle = new this.createjs.Bitmap('../../static/circle.png')
circle.x = x || 0
circle.y = y || 0
this.stage.addChild(circle)
this.createjs.Tween.get(circle).wait(500).to({alpha: 0}, 1000).call(function () { this.stage.removeChild(circle) }.bind(this))
},
....
}
当玩家点击数字键盘后,controlClicked 接口会被调用,我们在里面获得玩家按键的乘机值,接着调用checkResult()判断乘机值是否与某个下落的盒子相等,checkResult调用findNumberBoxWithValue()函数,该函数变量存储所有数字盒子的数组numberBoxes,如果有盒子的数值跟给定数值一样,那么就把这个盒子对象返回,拿到要爆破的盒子对象后,代码调用showCircle(x,y),其中x,y是盒子当前坐标,它会在合作表明显示出一个绿色的圆圈图案,然后把盒子从页面上删除掉,为了显示爆破效果,绿色圆圈图案出现在画面上后,再以渐变的方式慢慢消失,实现这个效果的就得依赖我们刚引入的Tween类,代码:
this.createjs.Tween.get(circle).wait(500).to({alpha: 0}, 1000).call(function () { this.stage.removeChild(circle) }.bind(this))
作用是把circle变量对应的图片先在页面上正常显示500毫秒,有就是wait(500)的作用,到第1000毫秒,也就是一秒钟时,把图片的透明的转换成0,也就是to({alpha: 0}, 1000),接着调用我们提供的回调函数,在回调函数里,我们知道此时展现爆破效果的绿圈图案要消失了,于是我们通过removeChild的方式把绿圈图案从stage上移除,这样下次界面刷新时,它就不会在显示出来,由于该功能是一种动态的显示效果,请点击链接 来观看实际效果。tweenjs库可以实现很多图片显示效果,具体说明可以参看以下链接:
http://www.createjs.com/Docs/TweenJS/classes/Ease.html
至此,游戏的基本流程我们都做完了,接下来我们完成收尾工作,然后把界面美化成我们最初显示的样子。我们要给玩家三次机会,当有三个数字盒子落到红线以下,游戏就该结束了,我们先在左上角绘制三个标记,在script标签处添加一下代码:
export default {
data () {
return {
...
initialLifes: 3,
lifes: 3,
hearts: [],
heartsContainer: null,
....
},
methods: {
init () {
....
this.initHearts()
....
},
initHearts () {
this.heartsContainer = new this.createjs.Container()
this.heartsContainer.x = 5
this.heartsContainer.y = 5
this.stage.addChild(this.heartsContainer)
this.resetHearts()
},
resetHearts () {
this.heartsContainer.removeAllChildren()
this.hearts.length = 0
for (var i = 0; i < this.initialLifes; i++) {
var heart = this.rectShape(18, 18, {fillColor: 'red'})
heart.x = i * 20
this.heartsContainer.addChild(heart)
this.hearts.push(heart)
}
},
deduceLife () {
this.lifes -= 1
var heart = this.hearts[this.lifes]
this.heartsContainer.removeChild(heart)
console.log(this.lifes)
if (this.lifes <= 0) {
this.gameOver()
}
},
gameOver () {
this.createjs.Ticker.setPaused(true)
},
moveObjects () {
....
if (box.y > this.boundaryY) {
this.removeNumberBox(box)
this.deduceLife()
}
....
},
},
....
}
initHearts会在页面的左上角绘制三个红色的小正方形,当有数字盒子落入红线下方时,deduceLife会在moveObjects函数中被调用,每调用一次,它会把界面左上角的红方块减去一个,当三个红方块减完后,调用gameOver(),把整个游戏设置为暂停状态,上面代码完成后,效果如下:
一旦三个方块减完,游戏进入暂停,此时我们可以在页面中间显示一个'replay'按钮,玩家点击后,游戏能重新开始,所以我们添加一下代码:
<template>
<div>
....
<div id="game-over" :class="{'hide': !gameOverShow,
'show': gameOverShow}"
@click="gameOverClicked">
</div>
</div>
</template>
新增的div元素能由于在页面上展示'replay'按钮,接下来我们增加对应的css样式代码:
<style scoped>
....
.show {
display: block;
}
.hide {
display: none;
}
#game-over {
background: url(../../static/images/replay.png); width: 100px;
height: 60px;
margin: auto;
position: absolute;
left: 100px;
top: 200px;
}
#game-over:hover {
background-image: url(../../static/images/replay_hover.png);
}
#game-over:active {
background-image: url(../../static/images/replay_active.png);
}
</style>
然后我们在script标签中也添加控制代码,使得游戏结束后在页面上出现一个'replay'按钮,玩家点击按钮后,游戏又能重新进行:
gameOver () {
this.createjs.Ticker.setPaused(true)
this.showGameOver()
},
showGameOver () {
this.gameOverShow = true
},
hideGameOver () {
this.gameOverShow = false
},
gameOverClicked () {
this.lifes = this.initialLifes
this.removeAllNumberBoxes()
this.hideGameOver()
this.resetHearts()
this.createjs.Ticker.setPaused(false)
console.log(this.gameOverShow)
},
removeAllNumberBoxes () {
for (var i = 0, len = this.numberBoxes.length; i < len; i++) {
var box = this.numberBoxes[i]
this.stage.removeChild(box)
}
this.numberBoxes.length = 0
},
当showGameOver被调用是,变量gameOverShow设置为true,那么前面我们添加的div元素就会被显示出来,当div元素对应的'replay'按钮被点击后,gameOverClicked()会被调用,它会清空页面上所有数字盒子,同时重新在左上角绘制三个红色方块,然后把游戏从暂停状态转换为进行状态,于是游戏又能得以重新进行。上面代码完成后,效果如下:
我们完成最后的工作,把游戏界面美化成最开始介绍的样子,美化其实就是贴图,添加如下代码:
methods: {
init () {
....
// change
var line = new this.createjs.Bitmap('../../static/images/line.png')
line.y = this.boundaryY
this.stage.addChild(line)
this.initHearts()
},
resetHearts () {
....
for (var i = 0; i < this.initialLifes; i++) {
// change
var heart = new this.createjs.Bitmap('../../static/images/heart.png')
....
}
},
box () {
// change
var obj = new this.createjs.Container()
var bitmap = new this.createjs.Bitmap('../../static/images/box.png')
obj.addChild(bitmap)
return obj
},
}
<style scoped>
#canvas {
background: #333 url(../../static/images/bg.png);
}
.control {
....
background: gray url(../../static/images/input_button.png);
....
}
</style>
我们把图片引入页面,并通过代码将图片在相应的地方绘制出来,这里的改动有三处,一是把黑色背景换成图片,把左上角的三个方块换成三个心形图片,最后把盒子也换成图片,上面代码完成后,运行效果如下:
到此,整个乘法防线的游戏就开发完成了,更详细的讲解和代码调试演示过程,请点击链接
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号: