Hi everyone!
The Tilemap
API is in beta, and as more developers have started to use it, we have started to get some feedback on things that people prefer and don’t prefer about the API.
Change for it’s own sake is not ideal, but we are early enough in this process that I would like to talk about whether we should consider making some changes—API changes now are going to be easier than if we wait.
This is an example of how the Tilemap
API might look in a project:
var bitmapData = Assets.getBitmapData ("tiles.png");
var tileset = new Tileset (bitmapData);
tileset.addTileRect (new Rectangle (0, 0, 100, 100));
var tilemap = new Tilemap (800, 600);
var tilemapLayer = new TilemapLayer (tileset);
var tile = new Tile (0);
tilemapLayer.addTile (tile);
tilemap.addLayer (tilemapLayer);
addChild (tilemap);
There is one Tileset
per BitmapData
, you can add tile rectangles to the tileset, which generates new tile IDs. Anyone who has used drawTiles
or another batch tiling API should recognize this portion.
The Tilemap
object is an OpenFL DisplayObject
, which is later added to the display list. This is what controls where and how all of our tiles will be drawn. The current API allows for any number of TilemapLayer
objects, which contain Tile
instances. Each one of these Tile
instances holds a tile ID, x, y, scale, rotation or other draw information needed when perform the final render.
TilemapLayer
is locked to one Tileset
only, and represents one draw call on the GPU. If you need more than one Tileset
, you will need to separate into multiple layers, increasing the number of draw calls.
Here is one alternative:
var bitmapData = Assets.getBitmapData ("tiles.png");
var tileset = new Tileset (bitmapData);
tileset.addTileRect (new Rectangle (0, 0, 100, 100));
var tilemap = new Tilemap (800, 600);
var tile = new Tile (tileset, 0);
tilemap.addTile (tile);
addChild (tilemap);
In this example, TilemapLayer
has been removed, each Tile
needs to have both a Tileset
and a tile ID value. This complicates the code internally, but allows for the batching mechanism of splitting into one or more draw calls to be done internally, and not passed onto the user. It also lends itself to shorter code, though perhaps with some lost flexibility?
Here is one more alternative:
var bitmapData = Assets.getBitmapData ("tiles.png");
var tileData = new TileData (bitmapData, new Rectangle (0, 0, 100, 100));
var tilemap = new Tilemap (800, 600);
var tile = new Tile (tileData);
tilemap.addTile (tile);
addChild (tilemap);
This extends the concept a bit further, avoiding a Tileset
object to use TileData
objects instead. Then a Tile
needs a TileData
(similar to how Bitmap
requires BitmapData
) but there are no longer tile IDs, and there is no need for an added Tileset
object, as we already have BitmapData
to begin with.
Lastly, here is one more concept:
var bitmapData = Assets.getBitmapData ("tiles.png");
var tileData = new TileData (bitmapData, new Rectangle (0, 0, 100, 100));
var tilemap = new Tilemap (800, 600);
var tile = new Tile (tileData);
tilemap.addTile (tile);
addChild (tilemap);
var tileGroup = new TileGroup ();
var tile2 = new Tile (tileData);
tile2.x = 100;
tileGroup.addTile (tile2);
tilemap.addGroup (tileGroup);
Finally, if there is a benefit to having tile layers, or other forms of built-in grouping within the API, we could consider allowing Tilemap
to define a default group internally, but for us to be able to add other groups as well, manually. This might be unneeded complexity, or we might consider allowing a TileGroup
to have it’s own transformation, slowing the render a bit, but adding convenience for rotating or scaling a set of tiles together.
…or we might be happy as it is, it’s simple and works similar to other APIs in other libraries. We’re open to your feedback, and appreciate your help on this.
Thank you!