实现盒子动画和键盘特效

继上一节我们已经在画面上完成了数字盒子的绘制,现在我们就启动游戏主循环,在主循环中驱动游戏流程,在此,我们先实现盒子从上往下落的效果。在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把该字符串显示到页面上,完成这些代码后,加载页面,可以看到如下效果:

再下一节,我们将在此基础上完成盒子被爆破的效果,并实现界面美化,最后使得我们的游戏变得像本节刚开始介绍时得样子。

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

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

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据结构笔记

Django搭建博客(七):form的使用

不过 form只提供输入框,外层的 form标签和提交按钮都需要自己添加,我们加上 form标签和提交按钮看看:

1493
来自专栏阮一峰的网络日志

Redux 入门教程(三):React-Redux 的用法

前两篇教程介绍了 Redux 的基本用法和异步操作,今天是最后一部分,介绍如何在 React 项目中使用 Redux。 为了方便使用,Redux 的作者封装了一...

3495
来自专栏james大数据架构

在ASPNET中使用JS集锦

(一).确认删除用法: 1. BtnDel.Attributes.Add("onclick","return confirm('"+"确认删除?"+"')")...

2197
来自专栏杂七杂八

selenium使用

pip insatll selenium 由于如果需要使用selenium的话,需要为本机配置对应浏览器的驱动,下面以chomedriver为例,首先安装ch...

1373
来自专栏互联网杂技

JavaScript面试问题:事件委托和this

JavaScript不仅门槛低,而且是一门有趣、功能强大和非常重要的语言。各行各业的人发现自己最混乱的选择是JavaSscript编程语言。由于有着各种各样的背...

3345
来自专栏互联网杂技

React数据流和组件间的通信总结

首先,我认为使用React的最大好处在于:功能组件化,遵守前端可维护的原则。 先介绍单向数据流吧。 React单向数据流:   React是单向数据流,数据主要...

3737
来自专栏听雨堂

电子签名实现的思路、困难及解决方案

        在办公自动化的流程中希望实现电子签名。         思路:             1、图片的存放:安全起见存放在库中为宜。最好不能被轻易下...

2465
来自专栏liulun

自己动手写客户端UI库——创建第一个控件

在上一篇文章中我们主要讲了C#如何和JS通信, 这一篇文章中,我们将创建一个最基础的Button控件 WUI库中控件的继承机制 我们先解释最简单的继承...

1947
来自专栏IMWeb前端团队

也谈 setTimeout

也谈 setTimeout setTimeout ,延迟一段事件执行代码,当然这是最基本的用法,这里不说基本用法。 jQuery 中的轮询 轮询,可能是 set...

21510
来自专栏HT

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

之前在拓扑上的应用都是些静态的图元,今天我们将在拓扑上设计一个会动的图元——叶轮旋转。 我们先来看下这个叶轮模型长什么样 ? 从模型上看,这个叶轮模型有三个叶片...

2035

扫码关注云+社区

领取腾讯云代金券