前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >寿司快卖:实现游戏主流程--制作寿司和客户显示动画特效

寿司快卖:实现游戏主流程--制作寿司和客户显示动画特效

作者头像
望月从良
发布2018-12-05 17:30:28
4930
发布2018-12-05 17:30:28
举报
文章被收录于专栏:Coding迪斯尼Coding迪斯尼

上一节我们搭建了游戏的基本框架。游戏界面被分为若干个板块,其中一个板块显示了各种制作寿司的材料,它的目的是用于玩家根据信息组装各种寿司,本节我们进入游戏的主流程设计阶段,这节我们要完成的是如何将让玩家将各种材料组合成相应的寿司。

首先我们先添加一些辅助函数,在gamescenecomponent.vue中添加代码如下:

代码语言:javascript
复制
resizeCanvas () {
        // change 2
        var customerView = document.getElementById('customer-view')
        var w = this.getBorderView(customerView)
        this.canvas = document.getElementById('canvas')
        this.canvas.width = customerView.offsetWidth - w.left - w.right
        this.canvas.height = customerView.offsetHeight - w.top - w.bottom
      },

...

//change 1
      initDomElement () {
        ....
        this.others = document.getElementById('others')
        this.rices = document.getElementById('rice')
        this.seaweeds = document.getElementById('seaweed')

       // 设置相应寿司的材料组合
        this.recipes['sushiSalmonRoe'] = ['rice', 'seaweed', 'seaweed', 'salmon-roe'].sort()
        this.recipes['sushiOctopus'] = ['rice', 'octopus'].sort()
        this.recipes['sushiSalmon'] = ['rice', 'salmon'].sort()
        this.recipes['sushiEgg'] = ['rice', 'egg', 'seaweed'].sort()
      },   
      getBorderWidths (element) {
        var style = document.getComputedStyled(element)
        return {
          top: parseInt(style.borderTopWidth),
          right: parseInt(style.borderRightWidth),
          bottom: parseInt(style.borderBottomWidth),
          left: parseInt(style.borderLeftWidth)
        }
      },
// change 3
      arrayIsEqual (array1, array2) {
        if (array1.length !== array2.length) {
          return false
        }

        for (var i = 0, len=array1.length; i < len; i++) {
          if (array1[i] !== array2[i]) {
            return false
          }
        }

        return true
      },
      clearChild (node) {
        while (node.lastChild) {
          node.removeChild(node.lastChild)
        }
      },
      clearAllIngredients () {
        this.clearChild(others)
        this.clearChild(rices)
        this.clearChild(seaweeds)
      }
    }

上面代码用于计算可知Dom元素的大小位置,以及在Dom中添加或删除各种元素。在制作寿司时,玩家通过选取相应材料组合起来形成所需要的寿司,相应代码如下:

代码语言:javascript
复制
initDOMElements () {
        // change 6
        var ingredients = document.querySelectorAll('.ingredient')
        for (var i = 0, len = ingredients.length; i < len; i++) {
          var element = ingredients[i]
          element.onclick = this.ingredentOnclick.bind(this)
        }

        var deleteButton = document.getElementById('delete-sushi-btn')
        deleteButton.onclick = this.deleteButtonOnclick.bind(this)

        this.ingredientsNode = document.getElementById('ingredient')
      },
      // change 7
      deleteButtonOnclick () {
        this.trashSushi()
      },

...

// change 5
      trashSushi () {
        this.sushiOnHand.length = 0
        this.clearAllIngredients()
      }

当玩家选取若干种制作寿司的材料后,界面要做相应变化,对应代码如下:

代码语言:javascript
复制
// change 8
      ingredentOnclick (ingredient) {
        console.log('ingredient click:', ingredient)
        var type = ingredient.toElement.dataset.type
        this.sushiOnHand = this.sushiOnHand.sort()
        this.addIngredientToScreen(type)
      },
      addIngredientToScreen (type) {
        var isEqualToAnySushi = false
        var sushiName = ''
        for (var key in this.recipes) {
          if (this.recipes.hasOwnProperty()) {
            // 当前选中的材料是不是属于某个指定的寿司菜单里
            isEqualToAnySushi = this.arrayIsEqual(this.sushiOnHand, this.recipes[key])
            sushiName = key
            if (isEqualToAnySushi) {
              break
            }
          }
        }

        // 把所有选中的材料组合起来形成一个寿司
        if (isEqualToAnySushi) {
          this.clearAllIngredients()
          var sushi = document.createElement('div')
          sushi.classList.add(sushiName, 'sushi')
          this.others.appendChild(sushi)
        } else {
          // 把选择材料拷贝到寿司板块
          var node = this.ingredientsNode.querySelector('.ingredient[data-type=' + type + ']').cloneNode(true)
          node.style.height = '80px'
          if (type === 'rice') {
            console.log('append to rice:', this.rices)
            this.rices.appendChild(node)
          } else if (type === 'seaweed') {
            console.log('append to seaweeds:', this.seaweeds)
            this.seaweeds.appendChild(node)
          } else {
            console.log('append to others:', this.others)
            this.others.appendChild(node)
          }
        }

当上面代码完成后,玩家在寿司面板点击一个图片代表的元素时,如果它属于某个寿司组合菜单中的一部分,那么它就会显示在右边面板上,如下图所示:

当我们点击右上角的trash按钮时,下面选中的元素会被删除掉。接着我们继续添加顾客动画特效,客户将随机的出现在场景中央区域,根据一个随机值它会出现在左上方或右下方,一开始客户出现时它会显示出愉快的表情,如下图:

此时玩家应该根据客户的要求,点击左下方的材料图片组装出客户想要的寿司,如果时间过长没能及时将寿司制作出了,客户就会显示出愤怒的表情,如下图:

我们看看相应代码的实现:

代码语言:javascript
复制
data () {
      return {
        canvas: null,
        // change 4
        sushiOnHand: [],
        recipes: [],
        // change 10:
        view: {},
        queues: [],
        queueIndex: 0,
        leftPos: 0.40,
        rightPos: 0.8
      }
    },
....
 // change 9
      initCustomerView () {
        console.log('this.cjs: ', this.cjs)
        this.stage = new this.cjs.Stage(this.canvas)
        this.cjs.Ticker.setFPS(60)
        this.cjs.Ticker.addEventListener('tick', this.stage)
        this.cjs.Ticker.addEventListener('tick', this.tick)
        // 实现客户队列
        this.view.queueLeft = new this.cjs.Container()
        this.stage.addChild(this.view.queueLeft)
        this.view.queueRight = new this.cjs.Container()
        this.stage.addChild(this.view.queueRight)
      },

通过上面代码,为程序添加一个时钟,我们将根据时钟变化来设置游戏的动画效果,接着我们编写构造客户动画的代码:

代码语言:javascript
复制
 // change 11 设置顾客对象
      Customer (number, leftOrRight) {
        var obj = new this.cjs.Container()
        obj.number = number
        // 随机构造客户想要吃的寿司
        obj.wants = this.randomWants()
        // 客户是否吃到指定寿司
        obj.hasEaten = false
        // 是否把客户放到队列前头
        obj.hasShownUp = false
        // 客户等待了多久
        obj.hasWaitForTicks = 0
        // 在左队列还是右队列
        obj.queueIndex = 0
        if (leftOrRight === 'right') {
          obj.queueIndex = 1
        }

        return obj
      },
      randomWants () {
        var options = ['sushiSalmonRoe', 'sushiOctopus', 'sushiSalmon', 'sushiEgg']
        var index = Math.floor(Math.random() * options.length)
        return options[index]
      },
      customerTick (customer) {
       if (customer.hasShowUp === false) {
          return
        }
        customer.hasWaitForTicks += 1
        if (customer.hasShownUp === true && customer.hasWaitForTicks === 300) {
          // 显示愤怒的顾客图片
          console.log('customer angry')
          customer.graphics.gotoAndStop('angry')
        }
        // 如果等待太久,将顾客从画面上删除
        if (customer.hasWaitForTicks > 500) {
          this.removeCustomer(customer)
        }
        // 如果成功吃到寿司,也将客户图片从页面删除
        if (customer.hasEaten) {
          this.removeCustomer(customer)
        }
      },
      removeCustomer (customer) {
        if (customer.parent === null) {
          console.log('remove customer with null parent:', customer)
        }
        customer.parent.removeChild(customer)
        this.removeFromQueue(customer.queueIndex)
      },

上面代码构建客户对象,并且初始化它相关信息,customerTick用来根据时钟变化调整客户动画的显示,当经过一定时长,如果相关条件没有满足,那么我们就将客户的愉悦动画,通过调用gotoAndStop(‘angry’)来时实现将客户动画转变为愤怒表情,当时长超过500 tick后,我们将客户动画从页面上删除,客户在页面上的显示需要执行下面代码:

代码语言:javascript
复制
 // 将客户图片显示到页面上
      customerShowUp (customer) {
        customer.graphics = new this.assetsLib['Customer' + customer.number]()
        customer.graphics.gotoAndStop('normal')
        customer.graphics.on('click', this.customerOnClick)
        customer.addChild(customer.graphics)

        var bubble = new this.assetsLib.Bubble()
        bubble.x = -40
        bubble.y = -120
        customer.addChild(bubble)
        bubble.sushiType.gotoAndStop(customer.wants)
        customer.hasShownUp = true

        this.customer = customer
      },
      customerOnClick () {
        var isEqual = this.arrayIsEqual(this.sushiOnHand,
        this.receipes[this.customer.wants])
        if (isEqual) {
          this.customer.hasEaten = true
        }

        this.trashSushi()
      },
      removeFromQueue (index) {
        this.queues[index].shift()
      },
      tick () {
        var durationForNewCustomer = 500
        if (this.cjs.Ticker.getTicks() % durationForNewCustomer === 0) {
          console.log('summon customer')
          this.summonNewCustomer()
          var customer = this.queues[0][0]
          if (customer && !customer.hasShownUp) {
            console.log('show up customer left')
            this.customerShowUp(customer)
          }
          customer = this.queues[1][0]
          if (customer && !customer.hasShownUp) {
            console.log('show up customer right')
            this.customerShowUp(customer)
            this.customerTick(customer)
          }
        }
        if (this.queues[0][0] !== undefined) {
          this.customerTick(this.queues[0][0])
        }
        if (this.queues[1][0] !== undefined) {
          this.customerTick(this.queues[1][0])
        }
      },
      summonNewCustomer () {
        var leftOrRight = 'left'
        var queueIndex = 0
        if (Math.random() >= 0.5) {
          leftOrRight = 'right'
          queueIndex = 1
        }

        var customer = this.Customer(1, leftOrRight)
        this.queues[queueIndex].push(customer)
        this.queueIndex = queueIndex
        if (leftOrRight === 'left') {
          this.view.queueLeft.addChild(customer)
          customer.parent = this.view.queueLeft
        } else {
          this.view.queueRight.addChild(customer)
          customer.parent = this.view.queueRight
        }
      },

summonNewCustomer函数用来创建一个客户对象,并根据一个随机数决定客户是出现在页面的左上角还是右下角,时钟每次触发时,函数tick会被调用,在里面代码根据ticks来决定是否创建一个客户对象,每500个ticks就创建一个客户对象,当客户对象出现300个tick后显示愤怒表情,500个tick后自动从页面上删除,完成上面代码后,我们就可以看到前面所示的动画特效了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coding迪斯尼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档