原文链接:https://github.com/libgdx/libgdx/wiki/Tile-maps
译者:重庆好爸爸 [email protected]
谢绝转载
术语对照
- 瓦片地图 - Tile Maps
- 基类 - Base Classes
文章中提到的类
- MapProperties
- TiledMap
- TiledMapTileLayer
- TiledMapTile
- TiledMapTileSet
瓦片地图
地图
LibGDX具有通用的地图API。所有与地图相关的类可以在com.badlogic.gdx.maps包中找到。com.badlogic.gdx.maps包含了基类,其下的子包包含了tile地图的其他类型地图的实现。
基类
基类,意味着是一个通用的集合,除了Tiled地图外,也支持其他2D地图格式。
地图由一系统图层组成。每个图层包含了一系统对象。地图,图层,对象都有属性,属性取决于加载方式。对于某些格式,还有专门的地图,图层和对象实现,稍后会有更多的内容。 基类的类层次结构如下所示:
属性
地图,图层,对象的属性在代码中由MapProperties类表现。MapProperties类本质上是一个Hash map。
地图,图层或者对象的属性的可用的Key-value取决于加载的格式。可以使用如下的方式去分别访问地图,图层或者uixiagn的属性:
map.getProperties().get("custom-property", String.class);
layer.getProperties().get("another-property", Float.class);
object.getProperties().get("foo", Boolean.class);
许多受支持的编辑器允许你在地图,图层和对象上指定这些属性。这些属性的类型取决于具体格式。 如有疑问,请在libgdx应用程序中使用一个地图加载程序去实际加载地图,并研究一下你感兴趣的属性。
地图图层
地图中的每个图层有时有排序和索引的,索引从编号0开始。可以用如下方法访问地图中的图层:
MapLayer layer = map.getLayers().get(0);
也可以通过名字查找图层:
MapLayer layer = map.getLayers().get("my-layer");
这些getter方法会返回一个Maplayer对象。有的图层可能被特殊化后提供了更多的功能,这种情况下,你可以进行强制转换:
TiledMapTileLayer tiledLayer = (TiledMapTileLayer)map.getLayers().get(0);
图层有几个属性,我们尝试为所有支持的地图格式归一化:(译者注:名字,透明度,可见性)
String name = layer.getName();
float opacity = layer.getOpacity();
boolean isVisible = layer.isVisible();
你也可以修改这些属性去影响图层的渲染。
除了这几个归一化的属性外,还可以用上面的方法访问更多的通用属性。
可用通过下面的方法,从图层中获取对象:
MapObjects objects = layer.getObjects();
MapObjects实例允许你通过名字,索引或者类型去获取对象,也可用通过它们去插入/删除对象。
Map 对象
API以已经提供了很多特定的MAP对象了,比如CircleMapObject, PolygonMapObject等等。
地图加载器会解析对象,并将它们放入相应的MapLayer中。
针对所有支持的格式,我们尝试针对所有对象,提取出下面归一化的属性:(译者注:名字,透明度,可见性,颜色)
String name = object.getName();
float opacity = object.getOpacity();
boolean isVisible = object.isVisible();
Color color = object.getColor();
特定的Map对象,比如PolygonMapObject,可能有额外的属性等等。
Polygon poly = polyObject.getPolygon();
改变任何一个属性都会影响到对象的渲染。
对象,和地图和和图层一样,你可以访问对象更多的通用属性。
注意: “Tiled”地图工具的tiles,不会保存为map对象。 有特别的图层可用来更有效的保存它们。 上面描述的对象一般用于定义:trigger areas, spawn points, collision shapes 等等。
地图渲染器 MapRenderer
MapRenderer接口,定义了渲染图层和对象的方法。
在你开始渲染前,你必须定义地图的View。把View想象成窗口。实现这一点的最简单的方法是告诉地图渲染器它可以使用的OrthographicCamera:
mapRenderer.setView(camera);
或者,你也可以手动指定投影矩阵和视图边界:
mapRenderer.setView(projectionMatrix, startX, startY, endx, endY);
View的边界由x/y定义,y轴朝上。所使用的单位是特定于地图和从其加载的格式。
通过调用如下方法如渲染所有图层:
mapRenderer.render();
如果你想要更多的控制渲染,你可以指定需要渲染图层的索引。比如:假设你有3个图层,2个背景和1个前景图层,你想渲染处于前景和背景之间的Sprite,可以这么做:
int[] backgroundLayers = { 0, 1 }; // don't allocate every frame!
int[] foregroundLayers = { 2 }; // don't allocate every frame!
mapRenderer.render(backgroundLayers);
renderMyCustomSprites();
mapRenderer.render(foregroundLayers);
通过单独渲染每个图层并修改每个图层的视图,您还可以实现视差效果。
Tiled Map
包含Tiles图层的地图,其处理的相关的类,在包com.badlogic.gdx.maps.tiled中。这个包里面也包括用于不同格式地图的加载器。
瓦片地图被加载到TiledMap类的实例中。TiledMap是通用地图类的子类,TiledMap中增加了额外的方法和属性。
Tiled Map的图层
包含tiles 的图层,是加载到 TiledMapTileLayer 实例。为了访问这些tiles,可以做如下转换
TiledMap tiledMap = loadMap(); // see below for this
TiledMapTileLayer layer = (TiledMapTileLayer)tiledMap.getLayers().get(0); // assuming the layer at index on contains tiles
其他通用的MapLayer有的全部属性,TiledMapTileLayer都有。除此之外,TiledMapTileLayer还有一个包含TiledMapTileLayer.cell实例的二维矩阵。
通过如下方法访问Cell:
Cell cell = tileLayer.getCell(column, row);
column和row指明了cell的位置,都是整数。tiles是在一个y轴向上的坐标系中。左下角的tile是(0,0),右上角的tile坐标为(tileLayer.getWidth()-1,tileLayer.getHeight()-1)
如果指定的位置没有tile,或者如果列/行参数超出范围,则返回null。
可以通过以下方式查询图层中的水平和垂直图块数:
int columns = tileLayer.getWidth();
int rows = tileLayer.getHeight();
Cells
Cell是 TiledMapTile 的容器。cell存储对Tile的引用,还有指定在渲染它时是否应该旋转或翻转瓦片的属性。
Tiles经常在多个cells之间共享。
Tilesets & Tiles
TiledMap包含一个或者多个 TiledMapTileSet 实例。Tileset 包含许多 TiledMapTile 实例。有多种方法实现tiles,比如:静态tiles,动画tiles等。您还可以为特殊目的创建自己的实现。
Tile图层中cells引用这些tiles。 Tile图层中的cells可以可以引用多个tileset中的tiles.为了减少纹理切换,建议每个图层只用一个tileset。
渲染Tiled Maps
为了渲染TiledMap和它的图层,你需要一个特定的MapRenderer实现。对于正交的或者自上而下视角的地图,可以使用OrthogonalTiledMapRenderer. 对于isometric地图,则使用IsometricTiledMapRenderer。其他的渲染器暂时是实验性的,不推荐。
通过下面方法创建渲染器:
float unitScale = 1 / 16f;
OrthogonalTiledMapRenderer renderer = new OrthogonalTiledMapRenderer(map, unitScale);
这个渲染器只能对传入构造函数的地图进行渲染。 这个限制允许渲染器对该特定地图执行优化,并缓存它们。
unitScale告诉渲染器一个游戏世界的unit是多少个像素。在上面的例子中,16个像素等同于1个游戏世界的unit. 如果需要1个像素和游戏世界的1个Unit对应,那么unitScale需要设置为1,以此类推。
unitScale是将渲染坐标系与游戏世界坐标系相结合的一种方式。
一个小例子:
假定你有一个tile地图,每个tile为32×32像素。在你的世界地图中,你想这些tile映射为世界地图的 1×1 unit的方块。你需要设置unitScale = 1/32f. 你现在可以将相机设置为在该单位刻度上。 假设你想在屏幕上查看地图的30x20 tile,那么你可以像这样创建你的相机:
OrthographicCamera camera = new OrthographicCamera();
camera.setToOrtho(30, 20);
如果使用的是IsometricTiledMapRenderer,则:
renderer = new IsometricTiledMapRenderer(isoMap, 1 / 32f);
再次,你必须指定地图(它应该是一个isometric tile地图)和一个unitScale。
注意:isometric渲染器是实验性的,使用风险自负,请报告您发现的任何问题。 从性能角度来看,移动设备上的渲染等距映射是非常昂贵的,因为每个瓦片必须混合。
加载TMX/Tiled地图
Loading TMX/Tiled maps
“Tiled”是一个通用的瓦片地图编辑器,可运行在windows/Linux/MAC OS X上,可以用来创建Tile图层和Object图层,包含用来触发区域的任意形状和其他目的。LibGGX提供一个加载器,可以用来读取“Tiled”生成的文件。
有两个方法可以加载瓦片地图:直接加载或者通过AssetManager。直接加载如下:
TiledMap map = new TmxMapLoader().load("level1.tmx");
这将会从assets文件夹加载这个叫做level1.tmx的文件。如果你想加载另外的文件类型,你必须在TmxMapLoader的构造其中提供一个FileHandleResolver。
TiledMap map = new TmxMapLoader(new ExternalFileHandleResolver()).load("level1.tmx");
我们选择这种机制,因为TmpMapLoader也可以用和AssetManager类一起使用,FileHandleResolvers统计了地址。通过AssetManager加载TMP地图的方法如下:
// only needed once
assetManager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
assetManager.load("level1.tmx", TiledMap.class);
// once the asset manager is done loading
TiledMap map = assetManager.get("level1.tmx");
加载后,你可以把这个地图当成一个新的TiledMap.
注意:如果你通过“直接加载”的方式加载了TMX地图,你需要调用TiledMap#dispose()去释放。这个函数也会释放地图中所有加载的的textures.
注意:如果你想把TMX地图和GWT backend结合使用,你需要保证地图使用pure base64编码。由于GWT的限制,GWT不能使用压缩的TMX格式。
加载 Tide地图
“Tide” 是另外一个通过用的瓦片地图编辑器,只能适用于windows平台。(译者注:考虑程序员用MAC的较多,因此不推荐使用"Tide"). LibGDX也提供了支持Tide工具输出的加载器。
和TMX文件一样,你可以直接加载“Tide”文件或者通过AssetManager加载:
// direct loading
map = new TideMapLoader().load("level1.tide");
// asset manager loading
assetManager.setLoader(TiledMap.class, new TideMapLoader(new InternalFileHandleResolver()));
assetManager.load("level1.tide", TiledMap.class);
注意:如果你直接加载Tide地图,你需要调用TiledMap#dispose()去释放。这个函数也会释放地图中所有加载的的textures.
性能考虑 Performance considerations
我们希望渲染的速度越快越好,有一些东西你可以考虑下,一边加快渲染速度:
- 仅使用图层中单个图块集中的图块。这将减少纹理绑定。
- 将不需要混合的图块标记为不透明。 目前您只能以编程方式执行此操作,我们将提供在编辑器中自动执行的方法。
- 不要超过层数。(Do not go overboard with the number of layers.???)
几个例子
- Simple platformer using a TMX map
- Programmatic creation of a TiledMap
- Tile map asset manager loading/rendering
- Tile map direct loading/rendering
- Tide map asset manager loading/rendering
- Tide map direct loading/rendering