用字节数组存放二维地图数据

来源:互联网 发布:淘宝关闭订单规则 编辑:程序博客网 时间:2024/04/25 16:22

一 二维地图数据内容

在RPG的大地图中,我们往往会分割成很多小块(逻辑上),用于玩家行走,比如使用A星寻路等等,就需要的二维地图数据。一般情况,存放的是数值,主要是指每个格子里的数值,这里的数值是指我们赋予他的需要表示的内容。例如:

0,0,0,0,1,1,0,0,1,1,1,0,0,0,2,0,1,1,2
  • 0表示为可行走区域
  • 1表示不可行走
  • 2表示可飞行
  • 3表示传送点
  • 4表示出生点
  • 等等根据需要来扩充

当然有人说我要采用对象的形式来存放,这也是可以的,但是存储对象就大太多了,一般情况是没有这个必要的。关于这点,也不在这篇文章的讨论范围。(曾经和同事关于使用数值和对象争论过,事实上,都有道理,完全可以根据实际情况选择使用,或者两者都使用)

二 地图数据的存放方式

  1. 一般采用数组Array或者Vector来进行存放
array[0][1]或者 vector[0][1]

那么读取数值的时候也是直接传入相应的二维坐标即可。

/** * 返回指定的点是否可行走 * @param row 行 * @param col 列 * @return 是否可行走 */public function isWalk(row:int,col:int):Boolean{    //实际这里还需要做边界检测    return array[col][row] == 0;}
  1. 用ByteArray存储

之所以需要采用ByteArray,是因为AS3没有byte这个数值类型。最小数值是int或者uint,占用4个字节,而使用ByteArray可以直接使用1个字节。

由于ByteArray是一维的,所以整个二维地图的数值是写成一个ByteArray里。那么获取的时候,则需要使用 列 * 行 + 行的方式来获取。有两个方式读取,
一个是采用readByte

byteMap.position = col *  rowMax + col;byteMap.readByte();

另外是采用[]的方式

byteMap[col *  rowMax + col]

完整的判断一个点是否可走的方法:

/** 最大行数 **/private var rowMax:int;/** * 返回指定的点是否可行走 * @param row 行 * @param col 列 * @return 是否可行走 */public function isWalk(row:int,col:int):Boolean{    return byteMap[col *  rowMax + col] == 0;    //byteMap.position = col *  rowMax + col;    //return byteMap.readByte() == 0;}

三 测试例子

接下来是一个简单的测试例子,主要是测试存放对象和读取的速度。
最终的结果证明是两个的读取速度几乎是一样的。但是带却相差4倍。(4个字节肯定是1个字节的4倍了:)

row = 600;col = 400;

是比较中间的数值了,一般情况下,一个格子可以是30 * 30像素或者30 * 60像之类的。所以一般 10000 * 8000像素的场景,纵和列也就是几百的数值。

占用字节的计算方式:

//行 * 纵 * 4个字节 / 1024 = 字节row * col * 4 / 1024600 * 400 * 4 / 1024 = 937.5 KB
/** * 用ByteArray存放二维地图数据 * @author sodaChen */public class ByteArrayMapTest extends Sprite{    /** 字节数值集合 **/    private var byteMap:ByteArray = new ByteArray();    /** 二维数组 **/    private var maps:Vector.<Vector.<int>> = new Vector.<Vector.<int>>();    /** 行数 **/    private var row:int = 600;    /** 列数 **/    private var col:int = 400;    public function ByteArrayMapTest()    {        //初始化地图信息        //列        for (var i:int = 0; i < col; i++)        {            var vec:Vector.<int> = new Vector.<int>();            maps.push(vec);            //纵            for (var j:int = 0; j < row; j++)            {                var value:int = RandomUtils.randomInt(0,1);                byteMap.writeByte(value);                vec.push(value);            }        }        //测试读取性能        var count:int = 0;        var t:Number = getTimer();        for (var k:int = 0; k < col; k++)        {            for (var i2:int = 0; i2 < row; i2++)            {                count += maps[k][i2];            }        }        trace("Vector" + count + "耗时:"  + (getTimer() - t));        count = 0;        t = getTimer();        for (var i3:int = 0; i3 < col; i3++)        {            for (var i4:int = 0; i4 < row; i4++)            {                count += byteMap[i3 *  row + i4];//              byteMap.position = i3 *  row + i4;//              count += byteMap.readByte();            }        }        trace("byteMap" + count + "耗时:"  + (getTimer() - t));        //计算体积大小        var bytes:ByteArray = new ByteArray();        bytes.writeObject(maps);        trace("数组大小:" + bytes.length / 1024 + "KB");        trace("字节:" + byteMap.length / 1024 + "KB");    }}

最终输出结果是:

Vector120139耗时:15byteMap120139耗时:15数组大小:939.0673828125KB字节:234.375KB

当然,那个毫秒数有时会变化的,但是相差不大。不过如果加大数值,比如都超过1000,ByteArray的性能会差一点。比如设置成

/** 行数 **/private var row:int = 1600;/** 列数 **/private var col:int = 1400;

输出结果是:

Vector1120119耗时:143byteMap1120119耗时:146数组大小:8755.4736328125KB字节:2187.5KB

体积比例不变,大毫秒数变化了。因为具体要怎么选择使用,就得看实际情况和需要了。

0 0
原创粉丝点击