Tiled (TMX) Loader

Any community contributions to libgdx go here! Some may get included in the core API when permission is granted.

Re: Tiled (TMX) Loader

Postby BurningHand » Tue Nov 23, 2010 1:18 pm

Based on my experience working with Replica Island code, which uses the Mesh per layer approach, I am comfortable with the performance of that setup. I currently have a loader/renderer that sets up the mesh per layer, then has a render method which takes a viewport. In this method, it is determined which tiles need be drawn and then uses that info to offset into the Mesh. Now, because at most times the entire x or y distance of the map will not be visible, it performs multiple render calls per layer (assuming horizontal scan lines, we can expect up to ScreenSizeY / TileSizeY or, in an HVGA/32px scenario, up to 10 render calls per layer). I have this working already and am seeing good performance. Though I wouldn't be opposed to trying the SpriteCache approach, it just isn't actually clear to me how that works exactly.
IRC: nexsoftware / mobidevelop; GitHub: MobiDevelop;
BurningHand
 
Posts: 2812
Joined: Mon Oct 25, 2010 4:35 am

Re: Tiled (TMX) Loader

Postby BurningHand » Tue Nov 23, 2010 1:44 pm

OK, I lied... it would be up to (ScreenSizeY / TileSizeY) + 1 to account for scrolling partial rows..
IRC: nexsoftware / mobidevelop; GitHub: MobiDevelop;
BurningHand
 
Posts: 2812
Joined: Mon Oct 25, 2010 4:35 am

Re: Tiled (TMX) Loader

Postby aksarfevad » Tue Nov 23, 2010 3:42 pm

BurningHand: I had implemented the same method after deciding I should do some culling.

Nate: As for rendering, I will have to investigate the sprite cache option. I am just worried that it would take more CPU time to recalculate where the tiles should be drawn on screen any time a tile boundary is passed. I would also be worried about how you would drop off old non-visible tiles and add the visible ones. I assume that is why you allow for reassigning cache ids now. I haven't used the sprite cache much yet, so I'll have to study up.

As for combining the tiles for each layer into one image, I agree that it would be best to grab each tile individually and put them on a texture per layer. This does seem to be the best balance of reusing tiles and still limiting the size of the texture. This setup would warrant rearranging the xml as well it seems, or swapping it for a different format.

For now I will probably be lazy and just tell the user only one tileset per layer since I have already gotten almost all the parsing done. I guess I could use that code to write the reformatting/rearranging program if worse came to worse. The Tiled format is extremely general. There are so few limitations that it is really up to the game designer how to use it. Since gdx also tries to be as general as possible, it is hard to balance all the available options.
aksarfevad
 
Posts: 275
Joined: Fri Nov 19, 2010 4:19 am

Re: Tiled (TMX) Loader

Postby mzechner » Tue Nov 23, 2010 4:46 pm

just for the record: rebuilding the tile mesh of one or more layers due to a new viewport is a bad idea imo. break up each layer into smaller chunks, e.g. 10x10 tiles or whatever is fitting for the overall layer size. Throw all those chunks of a layer into a single Mesh or SpriteCache. When it's culling time determine which chunks are visible and only render those. You get a constant number of draw calls and have no geoemtry uploads ever. If you are worried about drawing tiles that are outside of the viewport: don't be, the hardware is got to cull those. Of course, your layer chunks shouldn't be too big, so the chunk size should be configurable dependent on the context.

my 2 cents.
mzechner
Site Admin
 
Posts: 4879
Joined: Sat Jul 10, 2010 3:50 pm

Re: Tiled (TMX) Loader

Postby BurningHand » Tue Nov 23, 2010 4:54 pm

Oh, I'm definitely not rebuilding the mesh due to a change in viewport.
I am just doing a series of calls to mesh.render(int primitiveType, int offset, int count).
IRC: nexsoftware / mobidevelop; GitHub: MobiDevelop;
BurningHand
 
Posts: 2812
Joined: Mon Oct 25, 2010 4:35 am

Re: Tiled (TMX) Loader

Postby NateS » Tue Nov 23, 2010 5:35 pm

BurningHand wrote:Based on my experience working with Replica Island code, which uses the Mesh per layer approach, I am comfortable with the performance of that setup. I currently have a loader/renderer that sets up the mesh per layer, then has a render method which takes a viewport. In this method, it is determined which tiles need be drawn and then uses that info to offset into the Mesh. Now, because at most times the entire x or y distance of the map will not be visible, it performs multiple render calls per layer (assuming horizontal scan lines, we can expect up to ScreenSizeY / TileSizeY or, in an HVGA/32px scenario, up to 10 render calls per layer). I have this working already and am seeing good performance.

I guess my idea to load smaller chunks of tiles was half baked. Loading all the data into memory and just drawing portions of it is nice. :) I would guess a render call per layer per row of tiles is fine. The only downside I can think of is that a sparsely populated layer will be mostly degenerate triangles.

What benefits are there to using more than one mesh? Couldn't you have a single mesh that has all the data for the first layer, then all the data for the second layer, etc? Edit: Mario pointed out that indexed geometry uses shorts, which could limit the number of tiles if only a single mesh was used.

Though I wouldn't be opposed to trying the SpriteCache approach, it just isn't actually clear to me how that works exactly.

It's really just an API over Mesh, to try to make it easy to store a bunch of textured rectangles and draw them repeatedly, without changing the geometry. You could use it instead of Mesh to do the same thing you are doing now. It would go something like this...

Code: Select all
cache = new SpriteCache(tileMapWidth * tileMapHeight);
for (int y = 0; y < tileMapHeight; y++) {
   cache.beginCache();
   for (int x = 0; x < tileMapWidth; x++)
      cache.add(...); // The sprite or texture to add for x,y.
   cache.endCache();
}

This creates a "cache" for all the images in each row. The endCache method returns a handle, but the handle is sequential, so will be the same value as y. There are two draw methods: draw(handle) which draws all the cached images for that handle, and draw(handle, offset, length) which draws only a subset of the cached images for that handle. When drawing the tile map, you can just pass y for the handle:

Code: Select all
for (int y = startY; y < endY; y++)
   cache.draw(y, startX, screenWidthInTiles);

Honestly, I wrote SpriteCache for kicks after some discussion with Mario, not to solve an actual problem I had. I think it is neat though, so if someone can find a use for it, that would be great. :)

SpriteCache supports adding multiple textures to the same cache handle. If you do this, the SpriteCache#draw method will render the underlying Mesh multiple times, so that the different textures can be bound. However, if all images for a cache handle are from the same texture, one call to SpriteCache#draw will result in one Mesh render.

BurningHand, how are you handling that Tiled allows tile images from multiple backing "tileset" images to be used on the same layer?
Last edited by NateS on Tue Nov 23, 2010 5:57 pm, edited 2 times in total.
NateS
 
Posts: 1980
Joined: Fri Nov 12, 2010 11:08 am

Re: Tiled (TMX) Loader

Postby BurningHand » Tue Nov 23, 2010 5:47 pm

Ah, ok I will give it a shot. Thanks for the quick tutorial. :)

As far as multiple tilesets per layer, I am ignoring that and will just force the restriction of one tileset per layer. For my own purposes, I don't need to consider the possibility of more than one tileset per layer as I will be creating all maps myself.
IRC: nexsoftware / mobidevelop; GitHub: MobiDevelop;
BurningHand
 
Posts: 2812
Joined: Mon Oct 25, 2010 4:35 am

Re: Tiled (TMX) Loader

Postby mzechner » Tue Nov 23, 2010 5:59 pm

SpiteCacue uses indexed geometry internally so you have 64k/6 tiles agailable at most. I think going witu Mesh is actually a hetter idea now that i tapked a little witu Nate
mzechner
Site Admin
 
Posts: 4879
Joined: Sat Jul 10, 2010 3:50 pm

Re: Tiled (TMX) Loader

Postby BurningHand » Tue Nov 23, 2010 6:22 pm

Well, hmm...
I just tried drawing the same layer 4 times, so it used the same mesh each time and I dropped to about 20 fps.
Oddly, I am using for the most part the same setup as Replica Island, except the Replica Island grid is indexed.
I think using sprite cache would be fine, assuming the limitations are similar to that of the Replica Island Grid.
IRC: nexsoftware / mobidevelop; GitHub: MobiDevelop;
BurningHand
 
Posts: 2812
Joined: Mon Oct 25, 2010 4:35 am

Re: Tiled (TMX) Loader

Postby BurningHand » Tue Nov 23, 2010 8:31 pm

So, I just tried using SpriteCache as indicated above, and I am thinking there is something off in there.
When I go to render out rows which I added, I loop through sequentially from say Row0 to Row10, and it skips a row every time... I get a row of sprites, then no row, then a row of sprites, then no row, and so on. I'm not sure if there is something off in the offsets, or if the values going in are off, although I have confirmed I am sending the right y values in.
IRC: nexsoftware / mobidevelop; GitHub: MobiDevelop;
BurningHand
 
Posts: 2812
Joined: Mon Oct 25, 2010 4:35 am

PreviousNext

Return to Libgdx Contributions

Who is online

Users browsing this forum: No registered users and 1 guest