VUE+WebPack游戏设计:实现盒子爆破效果和界面美化

上节,我们完成了数字盒子的下落以及数字键盘的实现,当玩家点击键盘,点击的按键乘机等于下落的盒子数值时,游戏会把盒子给爆破掉,现在我们就来实现这个机制。

要实现爆破效果,我们需要使用另一个第三方库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>

我们把图片引入页面,并通过代码将图片在相应的地方绘制出来,这里的改动有三处,一是把黑色背景换成图片,把左上角的三个方块换成三个心形图片,最后把盒子也换成图片,上面代码完成后,运行效果如下:

这里写图片描述

到此,整个乘法防线的游戏就开发完成了,更详细的讲解和代码调试演示过程,请点击链接

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:


这里写图片描述
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容