前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VUE+WebPack游戏设计:欲望都市城市图层的设计

VUE+WebPack游戏设计:欲望都市城市图层的设计

作者头像
望月从良
发布2018-07-19 17:53:18
6190
发布2018-07-19 17:53:18
举报
文章被收录于专栏:Coding迪斯尼Coding迪斯尼

在上一节,我们设计了游戏的背景图层和UI图层,这一节开始,我们把精力集中到城市图层的开发和设计上,因为整个游戏的动画特效和游戏逻辑都发送在这个图层,因此它的开发是整个项目的难点所在。

我先把中间的城市背景图贴到页面中间,接着要在城市背景图上绘制9*9=81个网格,所有的城市建筑都必须拜访在网格中,代码完成后,页面加载显示如下:

注意,画面上的网格是我们用代码绘制上去的,不是图片自身带有的。首先打开gamescenecomponent.vue,添加如下代码:

代码语言:javascript
复制
create2DArray (rows, cols, initialValue) { 
        var array = [] 
        for (var i = 0; i < rows; i++) { 
          array[i] = [] 
          for (var j = 0; j < cols; j++) { 
            array[i][j] = initialValue 
          } 
        } 
        return array 
      }, 
 tile () { 
    var imagePath = '../../static/images/tile.png' 
    var obj = new this.cjs.Bitmap(imagePath) 
    obj.regX = 0 
    obj.regY = 21 
    obj.width = 86 
    obj.height = 43 
    return obj 
 }

create2DArray的作用是生成一个二维数组,我们将用这个函数生成一个9*9的二维数组,这个数组将对应于上图中的网格。tile函数加载网格对应的图案如下:

我们后面会把这个网格图案绘制到页面上,最终形成我们看到的那样大片网格区域。接着我们回到cityLayer函数的实现中添加相应代码:

代码语言:javascript
复制
cityLayer () { 
        var obj = this.layer() 
        var bg = new this.cjs.Bitmap('../../static/images/city-bg.png') 
        bg.regX = 370 
        bg.regY = 30 
        obj.addChild(bg) 
        // 9 * 9 grids 
        obj.cols = obj.rows = 9 
        var tiles = new this.cjs.Container() 
        obj.addChild(tiles) 

        obj.viewMap = this.create2DArray(obj.rows, obj.cols) 
        obj.x = this.gameWidth / 2 - this.tileWidth / 2 
        obj.y = this.gameHeight / 2 - (obj.rows - 1) * this.tileHeight / 2 
        this.redraw(obj, tiles) 
        return obj 
      }, 
      redraw (layer, tiles) { 
        for (var i = 0; i < layer.rows; i++) { 
          for (var j = 0; j < layer.cols; j++) { 
            var t = this.tile() 
            t.x = (j - i) * this.tileWidth / 2 
            t.y = (j + i) * this.tileHeight / 2 
            tiles.addChild(t) 
            layer.viewMap[i][j] = 0 
          } 
        } 
      },

在cityLayer函数中,它先加载城市图案作为背景图,绘制到页面中间,然后创建一个用于绘制网格区域的容器叫tiles,并通过调用create2DArray,生成一个9*9的二维数组,然后我们生成81个网格位图对象,redraw除了把网格绘制到页面上外,还把这些网格对象存储在这个二维数组里,以便后续管理和使用。完成这些代码后,我们就可以看到带有网格的城市图层背景图会显示到页面上了。

我们先把一些代码调整下,在gamescenecomponent中,添加如下代码:

代码语言:javascript
复制
data () { 
      return { 
         ... 
        coins: 100, 
        diamonds: 0, 
        powerSupplies: 100, 
        populations: 0, 
        consIndicator: null, 
        diamondsIndicator: null, 
        populationIndicator: null 
      }      
  }, 
  .... 
  tick () { 
        this.coinsIndicator.text = this.coins + '' 
        this.diamondsIndicator.text = this.coins + '' 
        this.populationIndicator.text = this.populations + '' 
        this.powerSupplyIndicator.text = this.powerSupplies + '' 
        this.stage.update() 
      },

这些代码的作用是,一旦我们程序逻辑修改了coins, diamonds, populations这三个变量,在UI图层上的控件会根据变化后的数值里面显示到页面上。

接下来我们要实现右下角按钮,玩家点击这个按钮后,系统会根据实际条件,显示出当前玩家可以建造的建筑物。要显示的界面如下:

我们将创建一个新组建来实现这个功能,在component路径下新建一个文件名为buildingpanelcomponent.vue并添加如下代码:

代码语言:javascript
复制
<template> 
</template> 

<script> 
  export default { 
    data () { 
      return { 
        show: false, 
        buildingData: {}, 
        cjs: null 
      } 
    }, 

    mounted () { 
      this.cjs = window.createjs 
      this.init() 
    }, 

    methods: { 
      init () { 
        this.buildingData['CoinsGenerator'] = { 
          className: 'ConsGenerator', 
          needCoins: 20, 
          needPopulations: 10, 
          power: 0 
        } 
        this.buildingData['PowerSupply'] = { 
          className: 'PowerSupply', 
          needCoins: 10, 
          needPopulations: 0, 
          power: 15 
        } 
        this.buildingData['Merchant'] = { 
          className: 'Merchant', 
          needCoins: 150, 
          needPopulations: 20, 
          power: 0 
        } 
      } 
    } 
  } 
</script> 

<style scoped> 
</style>

buildingData 用来包含要显示在界面上的三种建筑物的信息。接着我们要创建几个按钮,由于按钮有三种形态,正常状态,鼠标滑动状态,点击状态,不同的状态需要显示不同的背景图,这样按钮看起来才有动感,因此我们专门为按钮的生成设计相关代码:

代码语言:javascript
复制
createButton (spriteImage, width, height) { 
        var data = { 
          images: [spriteImage], 
          frames: {width: width, height: height} 
        } 
        var spritesheet = new this.cjs.SpriteSheet(data) 
        var button = new this.cjs.Sprite(spritesheet, 1) 
        this.cjs.ButtonHelper(button, 0, 1, 2) 
        return button 
      }

为了让按钮具备鼠标移动时的变换效果,需要对stage容器调用enableMouseOver()函数,默认情况下,绘图容器是不支持按钮的鼠标移动变换效果的,因为它会消耗很多CPU资源。先回到gamescenecomponent.vue,在init函数中添加代码:

代码语言:javascript
复制
init () { 
  .... 
  this.stage.enableMouseOver() 
  .... 
}

为了让buildingPanel组件把界面绘制出来,我们需要向它发送一个消息,这就需要用到VUE的组件通讯机制,因此我们像以前一样,创建一个Constant组件,代码如下:

代码语言:javascript
复制
<template> 
</template> 

<script> 
  import Vue from 'vue' 
  export default { 
    Event: new Vue(), 
    MSG_CREATE_BUILDINGS: 'msg-create-buildings' 
  } 
</script> 

<style> 
</style>

回到BuildingPanelComponent.vue, 我们在组件里添加绘制建筑选择界面的代码, 先为三个按钮初始化相关数据:

代码语言:javascript
复制
data () { 
      return { 
        .... 
        buildings: [] 
      }, 
      .... 
      init () { 
        .... 
        this.buildings[0] = { 
          name: 'PowerSupply', 
          image: 'power-supply', 
          x: 20 
        } 
        this.buildings[1] = { 
          name: 'CoinsGenerator', 
          image: 'coins-generator', 
          x: 338 
        } 
        this.buildings[2] = { 
          name: 'Merchant', 
          image: 'merchant', 
          x: 650 
        } 
        this.setupBuildingPanel() 
      } 
    },

接下来,我们根据按钮数据,分别构造出按钮对象,代码如下:

代码语言:javascript
复制
setupBuildingPanel () { 
        this.buildingPanel = new this.cjs.Container() 
        this.buildingPanel.visible = false 
        for (var i = 0; i < 3; i++) { 
          this.setupBuildingButton(i) 
        } 
      }, 
setupBuildingButton (i) { 
        var b = this.buildings[i] 
        var button = this.createButton('../../static/images/build-' + b.image + '-sprite.png', 286, 396) 
        button.x = b.x 
        button.y = 16 
        this.buildingPanel.addChild(button) 

     var _this = this 
     button.on('click', function () { 
       _this.buildingTypeToBePlaced = b.name 
       _this.readyToPalceBuilding() 
     }) 

     var buttonDisabled = new this.cjs.Bitmap('../../static/images/build-' + b.image + '-disabled.png') 
     buttonDisabled.x = button.x 
     buttonDisabled.y = button.y 
     buttonDisabled.visible = false 
     this.buildingPanel.addChild(buttonDisabled) 
      }

setupBuildingButton函数用来在建筑选择面板上显示不同建筑的选择按钮,例如setupBuildingButton(0), 那么函数将从数组buildings[0]中取出信息来构建按钮,于是b.imange的内容是’power-supply’,于是代码从static目录下加载图片build-power-supply-sprite.png作为按钮背景,如果你进入static/images目录,打开对应的图片,你会看到如下情况:

我们在createButton函数中使用createjs库提供的函数来创建按钮:

代码语言:javascript
复制
var spritesheet = new this.cjs.SpriteSheet(data) 
var button = new this.cjs.Sprite(spritesheet, 1) 
this.helper = new this.cjs.ButtonHelper(button, 0, 1, 2)

第一句代码把图片加载到页面,作为按钮的背景图,第二句代码把图片中的中间图案作为按钮在正常状态,也就是鼠标没有滑动到按钮时,按钮该显示的状态,第三句设置按钮状态,当鼠标滑动到按钮上时,显示上图的第一部分作为按钮背景,当鼠标被点击时,选取第三部分作为按钮的状态背景,于是当我们的鼠标滑动到按钮上或者点击按钮时,按钮会显示不同状态,因此整个过程就有一种动态的感觉。

完成上面代码后,我们就可以尝试显示建筑选择面板的显示了,回到gamescenecomponent.vue, 把Constant组件加载进来,并依靠它向buildingPanel组件发送一个消息,让后者把面板在页面上显示出来:

代码语言:javascript
复制
import Constant from './constant' 
  export default { 
  .... 
  mounted () { 
  this.init() 
      Constant.Event.$emit(Constant.MSG_CREATE_BUILDINGS, this.stage) 
    },

接着再buildingpanelcomponent.vue中,也把Constant组件引入,并接收消息,然后把面板容器加入到舞台容器,也就是stage对象:

代码语言:javascript
复制
import Constant from './constant' 
  export default { 
  .... 
  mounted () { 
      this.cjs = window.createjs 
      this.init() 
      Constant.Event.$on(Constant.MSG_CREATE_BUILDINGS, function (stage) { 
        console.log('receive panel msg') 
        this.buildingPanel.visible = true 
        stage.addChild(this.buildingPanel) 
      }.bind(this)) 
    }, 
    ....    
}

上面代码完成后,加载页面看到的效果如下:

我们原本设计是在页面的右下角有个按钮,点击后才会出现选择面板的,所以我们在把上面的代码修改一下,我们先创建右下角按钮,代码如下:

代码语言:javascript
复制
mounted () { 
      this.cjs = window.createjs 
      this.init() 
      Constant.Event.$on(Constant.MSG_CREATE_BUILDINGS, function (stage) { 
        stage.addChild(this.buildingPanel) 
        this.createCancelBuildButton(stage) 
      }.bind(this)) 
    }, 

    .... 

createCancelBuildButton (stage) { 
        this.cancelBuildBtn = this.createButton('../../static/images/cancel-sprite.png', 128, 62) 
        this.cancelBuildBtn.x = 820 
        this.cancelBuildBtn.y = 400 
        this.cancelBuildBtn.visible = false 
        var _this = this 
        this.cancelBuildBtn.on('click', function () { 
          _this.cancelBuildBtn.visible = false 
          _this.buildingPanel.visible = false 
          _this.newBuildingBtn.visible = true 
        }) 
        stage.addChild(this.cancelBuildBtn) 

        this.newBuildingBtn = this.createButton('../../static/images/add-building-sprite.png', 124, 42) 
        this.newBuildingBtn.x = 820 
        this.newBuildingBtn.y = 420 
        this.newBuildingBtn.on('click', function () { 
          _this.buildingPanel.visible = true 
          _this.cancelBuildBtn.visible = true 
          _this.newBuildingBtn.visible = false 
        }) 
        stage.addChild(this.newBuildingBtn) 
      }

上面代码加载后,页面显示如下:

右下角多了一个按钮,点击后建筑选择面板就会出现在页面上:

如果再次点击’cancel’按钮,面板就会消失,同时按钮会恢复成原来的’+Building’按钮。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档