isometric projection

等角投影制作egret伪3D游戏

2015/9/3 by DKZ thx. May

最近在制作一款类似cubejump的游戏伪3D游戏,接下来cubex3的手机版也要想要使用等角投影制作。

感谢剑龙写的egret版本的等角投影库,我简单研究了下原理,可能下面的笔记会有错误,具体请参考《Flash ActionScript 3.0 动画高级教程》

简单的说等角变换是将三维世界的点变化成为二维平面上的坐标来确定对象的位置,在游戏中实现伪3D效果

原理

三维空间点p(px,py,pz)沿y轴旋转angleY沿x轴旋转angleX得到二维平面上点(x,y)和深度z

x=pxcos(angleY)-pzsin(angleY)

tempz=pzcos(angleY)+pxsin(angleY)

y=pycos(angleX)-tempzsin(angleX)

z=tempzcos(angleX)+pysin(angleX)

等角变换angleY=45°,angleX=-30°带入消去tempz再乘2的平方根(变为2等角,w=h*2)

最终化简为:

x=px-pz

y=py1.2247+(px+pz)0.5

z=(px+pz)0.886-y0.707

二维变三维将py设为0可计算px,pz

px=y+x*0.5

py=0

pz=y-x*0.5

使用

可以前往egretInit获得这个库

其中主要包括

Point3D.ts

三维空间点类

IsoUtils.ts

换算坐标类

isoToScreen(p3d:Point3D):egret.Point

三维到二维

XYZToXY(x,y,z)

三维到二维

screenToIso(p2d:egret.Point):Point3D

二维到三维

IsoObject.ts

等角投影对象类,所有显示对象都要扩展这个类

_px:number
_py:number
_pz:number
_position:Point3D

三维坐标和三维点

_width:number
_height:number

显示对象宽和高用于碰撞检测或显示对象排布

_walkable:boolean = false
_vx:number = 0
_vy:number = 0
_vz:number = 0

三维空间中三个方向的运动速度

updateScreenPosition():void

调用IsoUtils计算并更新二维平面中的位置

setPosition(x,y,z):void

设置三维空间中位置

get depth()

获得深度

update(p:number = 1):void

更新位置(用在frame loop中)

IsoWorld.ts

等角投影世界

_floor:egret.DisplayObjectContainer

地面容器(不参与深度排序)

_world:egret.DisplayObjectContainer

世界容器(参与深度排序)

_objects:IsoObject[] = []

等角变换对象数组

addChildToWorld(child:IsoObject):void

添加一个等角变换对象到世界中

removeChildFromWorld(child:IsoObject):void

从世界删除一个等角变换对象

addChildToFloor(child:IsoObject):void

添加一个等角变换对象到地板中

removeChildFromFloor(child:IsoObject):void

从地板删除一个等角变换对象

sort():void

对等角变换世界排序

BitmapTile.ts

等角投影位图 extends IsoObject

设计师注意位图使用二等角长宽比1:2(或根据需要定制此类)

其他还有几个扩展IsoObject的类可以用作参考