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>

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

原文发布于微信公众号 - Coding迪斯尼(gh_c9f933e7765d)

原文发表时间:2017-10-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏.Net移动开发

.Net语言 APP开发平台——Smobiler学习日志:开发APP时,如何快速地实现屏幕自适应

当AutoHeight属性为“True”时,Mobile Form的Scrollable属性将失去效果,以GridView控件的下面两种情况为例(以下两种情况的...

942
来自专栏LeoXu的博客

[读书笔记]响应式web设计 转

@media screen and (max-device-width:400px){ 

811
来自专栏HT

基于HT for Web矢量实现3D叶轮旋转

在上一篇《基于HT for Web矢量实现2D叶轮旋转》中讲述了叶轮旋转在2D上的应用,今天我们就来讲讲叶轮旋转在3D上的应用。 在3D拓扑上可以创建各种各样的...

1926
来自专栏IMWeb前端团队

重构不完全教程集之二

本文作者:IMWeb 结一原文出处:IMWeb社区未经同意,禁止转载 故不登高山,不知天之高也;不临深溪,不知地之厚也。--摘自《劝学》 ::before &...

24110
来自专栏非典型技术宅

iOS动画系列之六:利用CABasic Animation完成带动画特效的登录界面1. 画风突变的笑脸2. 心跳3. iOS实践:实现一个带动效的登录界面

1366
来自专栏hightopo

原 基于HTML5 WebGL实现3D飞机

1655
来自专栏HT

基于HTML5 WebGL实现3D飞机叶轮旋转

在上一篇《基于HT for Web矢量实现2D叶轮旋转》中讲述了叶轮旋转在2D拓扑上的应用,今天我们就来讲讲叶轮旋转在3D上的应用。 在3D拓扑上可以创建各种各...

2368
来自专栏Sorrower的专栏

Android绘制(三):Path结合属性动画, 让图标动起来!

1642
来自专栏偏前端工程师的驿站

CSS魔法堂:再次认识font

一、前言                                 文字承载着站点内涵,而良好的字体、排版则为用户提供舒适的阅读体验。本文打算对字体稍微深...

28110
来自专栏hightopo

基于HT for Web矢量实现3D叶轮旋转

1224

扫码关注云+社区