本节开始,我们将基于上一个项目所学到的知识,利用createjs 和 Tween两个图形绘制库开发一款新的游戏,名为欲望都市。这个游戏具备一个特点就是2.5D,它是一种经济系统构建型游戏,开始时玩家得到的是一个空白的城市地图,玩家以市长的身份选择在城市中构建各种设施,通过不同设施的组合何以产生金币,基本情况如下:
玩家可以在每一个小格配置一种建筑,总共可以有三种建筑可以选择,一种是电厂,建造电厂可以增加人口,有了人口才能建造其他建造,依据上图,黄色带有闪电标识的建筑就是电厂,第二种建筑胶钱币工厂,有了这种建筑,城市才会有收入,但是建筑钱币工厂会消耗人口,右上角的标识意思是当前城市可以容纳70人口,其中50个人口已经被钱币工厂消耗掉了。第三种建筑是商店,有了商店就可以使用金币购买钻石,玩家的任务是配置三种建筑,最终使得城市具有的金币和钻石数量最大化,三种可供选择的建筑如下:
选取其中一种建筑后,就可以通过鼠标把建筑拖拽到城市土地的小格子中,建筑的建造过程跟‘红警’类似,经过一系列形态变化后才最终形成相应模样,因此玩起来时也是饶有趣味。
在游戏开发时,我们把整个设计分成三部分,一部分叫背景图层,第一张图中,蓝色的背景加上飘动的云朵就是背景图层;第二部分叫城市图层,最上图中中间部分,用来配置各种建筑图案区域就是城市图层,第三部分叫UI图层,第一张图中,画面上的各种按钮,标志,例如右上角的人口数量标志,右下角的按钮,左上角的钱币数量标志和钻石数量标志,他们合在一起形成了UI图层,整个游戏的开发将分别处理三个图层,然后再通过底层逻辑把三个图层整合成一个整体。
首先我们先动手开发背景图层的功能。先像以前项目一样启动一个新的VUE工程,然后在index.html里面把createjs和tween这两个库引入项目,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta 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>Isometric City</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
接着再components目录中,创建gamecontainer.vue这个容器组件,它的内容跟上一个项目一样,这里就不详述了,我们看看gamecomponent.vue的代码实现,首先我们需要给页面添加一个canvas控件,因为所有的游戏动画都需要绘制在canvas控件上:
<template>
<div>
<canvas id="canvas" width="960" height="480"></canvas>
</div>
</template>
接着我们实现游戏的逻辑代码,由于我们先实现背景图层,游戏的背景是一个大蓝天,同时有两朵白云动态的从右边慢慢飘向左边,因此我们要实现这个动画效果,首先我们设置组件的内部数据:
<script>
export default {
data () {
return {
gameWidth: 960,
gameHeight: 480,
cjs: null,
canvas: null,
stage: null
}
},
....
}
游戏的宽和高分别是960和480像素,cjs将用来对应createjs的库对象,canvas对应画布控件对象,stage是用来容纳一切动画元素的容器对象,它的具体说明在上一个项目详细讲解过。
接下来实现组件的初始化,当组件被页面加载时,他需要做一系列的数据初始化操作,代码如下:
init () {
this.cjs = window.createjs
this.canvas = document.getElementById('canvas')
this.stage = new this.cjs.Stage(this.canvas)
var backGround = this.bgLayer()
this.stage.addChild(backGround)
this.cjs.Ticker.setFPS(40)
this.cjs.Ticker.addEventListener('tick', this.tick)
},
tick () {
this.stage.update()
},
其中的backGround就是我们一会要开发的背景图层对象,我们设置画面的更新频率是每秒40帧。接下来我们看看背景图层是如何设计的,代码如下:
layer () {
var obj = new this.cjs.Container()
return obj
},
cityLayer () {
var obj = this.layer()
return obj
},
bgLayer () {
var layer = this.layer()
var bitmap = new this.cjs.Bitmap('../../static/images/bg.png')
layer.addChild(bitmap)
var cloud1 = new this.cjs.Bitmap('../../static/images/cloud1.png')
cloud1.y = 30
cloud1.alpha = 0.4
layer.addChild(cloud1)
this.cjs.Tween.get(cloud1, {loop: true}).to({x: this.gameWidth + 300}, 0).wait(15500).to({x: -300}, 50 * 1000)
var cloud2 = new this.cjs.Bitmap('../../static/images/cloud2.png')
cloud2.y = 300
cloud2.alpha = 0.4
layer.addChild(cloud2)
this.cjs.Tween.get(cloud2, {loop: true}).to({x: this.gameWidth + 50}, 0).wait(500).to({x: -300}, 50 * 1000)
return layer
}
layer函数是所有图层对象的基础,它返回的是一个容器对象,cityLayer返回的是城市图层,这里我们先简单返回一个容器对象,以后再进行详细的代码添加。bgLayer()函数绘制的就是背景图层了,它先加载两张图片,作为位图对象,这两张图片对应两片云彩,代码分别设置两片云彩图案在页面上绘制的位置y坐标为30和300,透明度是0.4,其中两个语句:
this.cjs.Tween.get(cloud1, {loop: true}).to({x: this.gameWidth + 300}, 0).wait(15500).to({x: -300}, 50 * 1000)
this.cjs.Tween.get(cloud2, {loop: true}).to({x: this.gameWidth + 50}, 0).wait(500).to({x: -300}, 50 * 1000)
第一个语句的作用是,先让第一张图片处于画布最右方再向右偏移300像素的位置,然后等待大概15秒,也就是wait(15500)的作用,然后产生动画效果,把图案从原来的位置平移到x坐标为左边-300像素的地方,这个渐变过程持续50秒,也就是to的第二个参数50*1000。
第二句代码的作用是一样的,上面代码完成后,加载页面,可以得到如下效果:
两片白云图案慢慢的从右边挪动到左边,完了后这个过程不断重复。这就完成了我们想要的背景图层的设计。接下来我们完成UI图层的设计,继续在组件中添加如下代码:
uiLayer () {
var obj = this.layer()
this.setupHUD(obj)
return obj
},
placeBitmap (layer, path, x, y) {
var bitmap = new this.cjs.Bitmap(path)
bitmap.x = x
bitmap.y = y
layer.addChild(bitmap)
},
placeText (layer, textStr, size, x, y, align) {
var text = new this.cjs.Text(textStr, size + 'px Arial', '#222')
text.x = x
text.y = y
text.textAlign = align
layer.addChild(text)
return text
},
setupHUD (layer) {
this.placeBitmap(layer, '../../static/images/candies.png', 28, 16)
this.placeBitmap(layer, '../../static/images/diamonds.png', 154, 14)
this.placeBitmap(layer, '../../static/images/populations.png', 810, 14)
this.consIndicator = this.placeText(layer, '12345', 12, 123, 34, 'right')
this.diamondsIndicator = this.placeText(layer, '0', 12, 250, 34, 'right')
this.populationIndicator = this.placeText(layer, '100', 16, 845, 32, 'center')
}
}
上面代码加载了几个图片,并生成了几个字符串对象,然后把他们添加到一个图层容器中,最后我们在初始化函数中,把UI图层对象添加到舞台容器中:
init () {
....
var uilayer = this.uiLayer()
var citylayer = this.cityLayer()
this.stage.addChild(backGround)
this.stage.addChild(uilayer)
this.stage.addChild(citylayer)
....
}
完成上面代码后,我们得到的游戏场景如下:
到这里,我们就完成了第一阶段的背景图层和UI图层的设计,接下来我们将把精力集中到游戏图层以及游戏主逻辑的设计之中。
更详细的讲解和代码调试演示过程,请点击链接
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号: