虚拟实验室引擎的开发和实现(九、地图和人物)

虚拟实验室引擎的需求之一就是人物漫游功能:即用户操纵人物在场景中移动。这就意味着在开发引擎的时候,要考虑到场景的某些地方,人物是无法移动到上面去的(例如河流,花坛)。我们还需要在场景上做一些“手脚”,来标记哪些区域允许移动,哪些区域不允许移动。例如,下图中,蓝色部分(用1表示)的区域是允许用户移动的区域,而红色(用0表示)则是不允许。

image

VGridPlace

扩展VPlace

我扩展了VPlace类,增添了一些变量和方法:

image

 

下表给出了这些属性或方法的定义及说明: 

属性名 类型 说明
Value Int32[] 地图每一个网格的值,1表示可行,0表示不可通行
PlaceWidth Int32 地图横向有几个格,PlaceWidth=Width/GridSize
PlaceHeight Int32 地图纵向有几个格,PlaceHeight=Height/GridSize
GridSize Int32 每一个格的大小,默认为20像素
Person VPerson 用户操作的人物
Persons VPerson集合 所有人物,包括用户操作的人物(1个)和其他人物
AStar AStar 寻路算法辅助实现,详见寻路


方法名 说明
FindPath(Point from,Point to) 是用A*寻路算法找到从点from到点to的最短路径
AddPerson (VPerson person) 添加角色
RemovePerson (VPerson person) 删除角色

扩展VPlace的属性文件

在VPlace属性文件基础上,添加一个Attribute:gridsize,和GridSize对应;添加一个Element:mapdata,和Value对应。扩展后的属性文件如下:

<gridplace name='中大商业街' width='1700' height='1200' centerx='0' centery='0' x='0' y='0'
    file='engine2/sysu/sysu.xml' gridsize='20'>
    <mapdata><!-- Map Data --></mapdata>
</gridplace>

 

压缩mapdata

在地图中,网格的值只有两种情况(1-可行走,0-不可行走),如果在XML属性文件中用一个整型来表示这个地图中一个网格的值,在传输过程中会带来很大的数据开销(例如上面的属性文件,一共有1700/20*1200/20=5950个格,如果按照0,0,1,……1,1的形式来保存,则需要5950+5949=11899个字节)。我采用以下形式来压缩这些数据:用一个整数(32位)来表示相邻的32个格的值(例如相邻的32个格值分别为1,1,1,0,1,0,……,0,0,1,那么该整数的二进制为111010……001,最多需要10个字节,4294967295=11111……111,因此,按照上面的属性文件,最多只需要5950/32+1+5950/32=371个字节)。

解压缩算法如下:

//uint compress 为需要解压缩的32位整数
var mask = 0x80000000;

for (int j = 0; j < 32; j++)
{
    if ((compress & mask) == 0)
    {
        Value[j] = 0;
    }
    else
    {
        Value[j] = 1;
    }
    mask >>= 1;
}

VPerson和UIPerson

VPerson继承自VItem,表示虚拟实验是中的人物角色;UIPerson继承自UIItem,是VPerson的表现形式。

当鼠标在地图上某点点击时,虚拟实验室引擎会将鼠标点击的位置转换成目标网格,然后计算出用户控制的人物所在的网格和目标网格之间的最短路径(调用VPlace的FindPath方法),如果该路径存在,则将人物移动到目标网格。

VPerson的ActionID

约定用以下ActionID来表示一个人物角色在引擎中的动做:

ActionID 动作描述
faceright 人物面向右侧站立
facerightdown 人物面向右下站立
facedown 人物面向下方站立
faceleftdown 人物面向左下站立
faceleft 人物面向左侧站立
faceleftup 人物面向左上站立
faceup 人物面向上方站立
facerightup 人物面向右上站立
moveright 人物面向右侧移动
moverightdown 人物面向右下移动
movedown 人物面向下方移动
moveleftdown 人物面向左下移动
moveleft 人物面向左侧移动
moveleftup 人物面向左上移动
moveup 人物面向上方移动
moverightup 人物面向右上移动

寻路

在处理人物在移动时,采用了A*寻路算法来寻找最短路径,关于A*寻路算法,请参考:A* Pathfinding for Beginners

posted on 2011-05-06 14:55  carekee  阅读(335)  评论(0)    收藏  举报