如何存储地牢地图

时间:2014-01-22 20:14:32

标签: actionscript-3

我正在使用AS3,但是AS3非常具体的编程智慧也很棒!

我正在创建我的第一个游戏,一个带有基于图块的导航的自上而下的地下城爬行器,我正在决定如何存储我的地图。我需要能够在任何时间点访问特定的磁贴。我到目前为止唯一的想法是使用嵌套的向量或数组,第一级是行,第二级是列,如下所示:

private var map:Array = new Array(Array(0,1,0,0,1,1,0),Array(0,1,0,1,0,1,0));
private var row2col3:uint = map[1][2];

/*map would display as such:*/
#|##||#
#|#|#|#

最终,我们的想法是构建一个易于扩展的Map类,并允许自由访问任何特定的tile。我正在寻找帮助来确定该Map类的有效/高效设计架构。

谢谢!

3 个答案:

答案 0 :(得分:1)

如评论中所述,我将上传并提供12小时挑战项目的源代码,以创建基于图块的关卡编辑器。源代码位于:GitHub BKYeates

此级别编辑器专注于纹理是2的幂,并使用blitting绘制所有纹理。它可以读取,写入和存储部分图块。还有一些功能可以在碰撞盒上擦除和绘制。

现在关于如何设置存储,这完全取决于您。如果您要存储大量信息,我建议使用Vectors。除了ByteArray(如果使用正确),向量的执行速度比大多数其他容器类型要快。在我的关卡编辑器中,我使用了具有特定设置的Vector

Vector我在名为_map的类中使用了名为tilemodel的{​​{1}}。 tilemodel负责在进行更改时更新所有存储信息。 _map变量的设置如下:

_map = new Vector.<Vector.<Vector.<Object>>>();

这是一个非常嵌套的Vector,在最后的商店,你能相信它,Object!当您为最远的嵌套元素建立索引时,无可否认地使用Vector可以获得性能提升。

但请忽略这一点,因为此设置的索引增益非常关键。它以这种方式设置的原因是因为我可以引用一个图层,一行和一列来抓取特定的图块对象。例如,我在第12行第13列的第2层上有一个磁贴,我想访问:

var tileObject:Object = _map[2][12][13];

这几乎适用于我在基于磁贴的游戏中使用的任何场景,并且当多次访问时,速度比ObjectDictionary的速度要好一些(即 - 在经常发生的循环中。

关卡编辑器旨在使用所有blitting并将onus留给我的管理类进行存储。这样做的速度非常快,而且tilemodel的当前设置方式可以存储部分位图,使其比2纹理阅读器的标准刚度稍微灵活一些。

随意查看源代码。但这里是一些类的功能摘要:

  • tilecontroller - 向tilemanager和tilemodel发布状态更改和更新

  • tilemanager - 负责纹理绘制和移除。

  • tilemodel - 存储和更新状态变化的当前地图。

  • r_loader - 从assetList.txt加载所有资源(路径设置为图像
    那里)。

  • hudcontroller - 目前这是我正在处理的最后一件事,让您可以在地图旁边的单独文件中绘制碰撞框。

  • g_global&amp; g_keys - 使用全局常量和静态方法 遍

  • LevelEditor - 主类,也设计为“视图”类(请参阅MVC模式:MVC Pattern

另外正如我所提到的,它可以读回所有存储空间。用于我的类没有上传到GitHub,但我想在这里会显示重要的方法:

    //@param assets needs to be the list of loaded bitmap images
    public function generateMap( assets:* ):void {
        var bmd:BitmapData = new BitmapData( g_global.stageWidth, g_global.stageHeight, true, 0 );
        _canvas = new Bitmap( bmd, "auto", true );
        _mapLayer.addChild( _canvas );
        _canvas.bitmapData.unlock();

        g_global.echo( "generating map" );

        var i:int, j:int, m:int;
        for ( m = 0; m < _tiles.length; m++ ) {
            for ( i = 0; i < _tiles[m].length; i++ ) {
                for ( j = 0; j < _tiles[m][i].length; j++ ) {
                    //wondering why im type casting in this evaluation?  _tiles[i][j].tile == int( _tiles[i][j].tile ) 
                    //the level editor stores tiles that are larger than the grid size at indices containing values that are a percent of the tile size
                    var tile:Object = _tiles[m][i][j];
                    if ( tile != null && int( tile.tile ) == tile.tile ) {
                        addTile( g_global.GRIDSIZE * tile.column, g_global.GRIDSIZE * tile.row, { index:tile.tile, bitmap:assets[ tile.tile ] }, tile.rotation );
                    }
                }
            }
        }
        _canvas.bitmapData.lock();
    }

无论如何,我希望这些信息能很好地找到你。祝你好运!

答案 1 :(得分:0)

前一段时间我问了一个类似的问题:https://gamedev.stackexchange.com/questions/60433/is-it-more-efficient-to-store-my-tile-grid-as-a-dictionary-or-an-array。我不确定它是一个数组还是一个Vector(FP版本之间的效率差异似乎不同)。

但是,是的,你可能想要使用其中一个(不是字典或任何东西),你可能希望将其编入索引,如[y * width + x],而不是[x][y]。理由:效率,而不是过于复杂的数据结构。

此外,如果您需要能够定期访问该类之外的数组或向量,只需将变量设为内部或公共或其他;把它变成私有的并用功能包裹它,虽然是更加原始的类设计,但仍然有点矫枉过正。

答案 2 :(得分:0)

我现在正在使用的一种方法是将我的瓷砖存储在黑白像素位图中(并在其周围写了一个包装)。我不确定这是多么有效,因为我从来没有对它进行基准测试,只是快速编写它来创建一个用于测试目的的地图,但我发现它确实提供了一个优势,因为我可以在图像中绘制我的地图编辑器并轻松查看它们,同时仍允许随机像素/磁贴访问。

看看你的示例代码,我猜你现在只有两种类型的瓷砖,所以你可以尝试使用黑白像素。

我也完成了2d数组方法(实际上还在其他部分使用它)也可以正常工作,但也许在更大尺寸下可视化更难。期待Bennett的回答。