我正在使用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类的有效/高效设计架构。
谢谢!
答案 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];
这几乎适用于我在基于磁贴的游戏中使用的任何场景,并且当多次访问时,速度比Object
或Dictionary
的速度要好一些(即 - 在经常发生的循环中。
关卡编辑器旨在使用所有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的回答。