bug1:在已经有box的地方,再点击,将会重复创建box新实例。
bug2:后面添加的box,会挡住前面添加的box。
bug3:在边缘部分,如果用鼠标小心的点击,可以创建出很多超出world范围之外的盒子(即:看起来好象挂出去了)
我们按轻重缓急来处理吧:
bug2最严重,它直接影响了最终的3D视觉效果。产生它的原因是显示列表中,后添加的物体,其index值会比 前面添加物体的index值 要大,所以就挡住了前面的box。
仔细看一下IsoObject类
其实这里已经预留了“深度”属性,根据这个对所有的box进行depth属性排序即可。另外为了实现排序,我们应该把所有box类实例存放到一个数组里,这样才能利用Array的SortOn方法。(代码会在后面一起给出)
再来看bug1,重复创建的问题,这个解决起来比较容易:在创建box前,先检查对应的位置是否已经有box了,如果有,就不用处理了,这样就把问题转化为Point3D的坐标位置比较,所以我们得在Point3D中添加一个判断是否相等的方法
注:as3不象c#那样有操作符重载,所以只能显式定义equal方法
最后来处理bug3,即box实例超出地图范围之外的问题(产生这个问题的根源就是as3.0的事件冒泡机制,在box实例上点击时,world会响应Click事件)
如上图,很明显:地图是有边界的,如果盒子超出地图的范围,其x,z坐标肯定也会大于某一个阈值,所以在创建box实例前对坐标检测就能处理了.
完整代码:
设置行数,列数,画地板,添加子元素时的种种处理(深度排序,位置检查...)这一堆东东,以后会经常用到的,为了方便起见,干脆封装起来吧,另外:我们的as文件越来越多了,为了保持清晰的结构,把这些等角投影所用的基类新建一个iso的包来管理吧,结构如下图:
IsoWorld封装类:
有了这个类,刚才的示例写起来就简练多了
接下来考虑一下如何在地板上移动物体:
要移动当然要有速度,先在IsoObject上添加vx,vy,vz速度属性
测试一下用键盘控制移动
用鼠标点击上面的Flash,box将随机向上弹起并落下,同时下面的阴影也会随之变化。
下一个问题:碰撞检测
把前面那个用键盘控制box移动的示例稍做修改,另外再增加一个静止不动的box
用键盘控制红色的box,尽量去碰灰色不动的box,会发现红色box径直穿过灰色box,太假了。
仔细思考一下:如果红色box在移动的过程中,前方遇到了障碍物,而且这个障碍物是不可穿越的(可能有朋友会问:障碍物还有能穿越的么?确实有,比如在一些游戏中,允许角色穿墙而过),那么红色box就应该不能再前进。
让我们回过头来再看看IsoObject.as的定义,注意里面有二个属性:walkable,rect。这时候该它俩派上用场了,walkable表明该物体是否允许被穿越(默认为false),而rect用于返回该物体在等角空间中占用的矩形区域。
问题解决了:在IsoWorld中,每个物体去跟其它物体做个检测,检测二者的矩形区域是否有交集,如果有就表示碰上了,另外再看看其它物体是否允许穿越,如果不允许,则应该不能再向前运动了。
将这个方法加入到IsoWorld.as中即可,然后刚才碰撞示例的Enter_Frame处理函数改为:
现在再试试,碰撞检测的处理应该起作用了。
如果一个游戏里都是些单调的纯色盒子,很快就会看腻味了,所以下面我们会学习如何利用图片创建更好看的box,为了使用图片,我们需要一个新的基类:GraphicTile.as
代码很短,但是“简约而不简单”,首先要注意是Class类型的参数,classRef:Class表明参数classRef必须是一个类的引用,即传一个类进去(初次接触可能感觉很怪,没关系,多看几遍就顺眼了),其次是偏移量参数,为什么要有偏移量?因为在之前的基类IsoObject中,sprite的注册点是正中心,所以无需偏移量校正,而使用图片时,图片默认的注册点是左上角,要想把图片正好校对到中心,就必须要用偏移量来调整。
另外一个问题:图片如何嵌入到as文件中?使用Embed标记--类似c#中的特性语法(attribute),废话了一堆,还是直接来看测试代码吧:
拿鼠标在地图上点二下试试!
注:这里用到了二张图片,放在这里,方便大家下载回去测试
实际的游戏开发中,不可能所有地图都是用代码写死的,这样维护起来很麻烦,所以下面将学习到如何利用外部文件来存储地图信息,然后根据该配置文件来自动生成地图:
// this is a comment.
# 0 type:GraphicTile graphicClass:MapTest_Tile01 xoffset:20 yoffset:10 walkable:true
# 1 type:GraphicTile graphicClass:MapTest_Tile02 xoffset:20 yoffset:30 walkable:false
# 2 type:DrawnIsoBox color:0xff6666 walkable:false height:20
# 3 type:DrawnIsoTile color:0x6666ff walkable:false
0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 0
0 1 0 0 0 0 0 0 1 0
0 1 0 3 3 3 3 0 1 0
0 1 0 3 2 2 3 0 0 0
0 1 0 3 3 3 3 0 0 0
0 1 0 0 0 0 0 0 0 0
这个是一个典型的地图描述信息,可以直接把它存储到txt记事本文件里,分析一下:
“// ”行表示注释,不用管,是给人看的,不是给代码看的
“#”行表示的是类型定义,即数据字典,这里1表示GraphicTile,2表示DrawnIsoBox,3表示DrawnIsoTile,后面为具体的实例生成参数(代码读取这些参数后,传到相应的构造函数中,以方便生成实例)
再下来的数字,就是地图的实际描述。
为了能正常解析地图配置信息,需要专门弄一个地图解析类(MapLoader):
关键的地方已经加了注释,应该不难懂,然后来测试一下:
建议大家修改一下map.txt中的信息,然后重新运行看看效果。如果一切正常的话,只要地图信息修改了,as代码不用改一行就能自动生成新地图。最后再回过头来看一下地图信息中的graphicClass:MapTest_Tile01,我们在MapTest中对于的Tile01的定义是这样的:
[Embed(source="img/tile_01.png")]
private var Tile01:Class;
注意这里并没有MapTest_前缀,但是as3经过编译后,内部的名称会自动变成"类名_属性",所以在地图中一定要加上该前缀。