Tiled Map Engine

Hey guys,

Sorry, I’ve been working on an HTML5 game project for the past week and then i have the GCD next week–so I won’t be back on Ceramic until April.

However, I had an great idea on how do do the culling without having to change anything with how a user loads a map and should only take me a few days to get working.

Here’s the concept… When you load a map it will return a big transparent display group the size of the map. Inside that display group there will be enough images to cover the screen with and extra row or column on each side. The display group will have an enterFrame() event that tracks it’s x,y vs the screenBounds and will shift the extra row or column around if the x,y changed enough that the any row went offscreen.

So at most you will only need to update a couple of rows and most of the enterFrame() events will be invalid anyway.

I think this will give the maximum performance and will allow for large maps that can be moved easily. Plus no map.update() event would be needed so it would be easy to implement.

@Caleb, I think this is kind of like your approach, but it looks at relative position of the map, rather than rendering the tiles at a position.

@cjc83486 I don’t know how physics objects would be handled yet, but I imagine they would need to be around regardless of where the map is being drawn. You can’t have a floor that’s holding a bunch of objects up dissapear just because it scrolled of screen :slight_smile:

@no2games

haha, very good point, I guess the idea sounded better in my head, :).  Hmm pertaining to my own game though, side from your tile renderer… would making my objects offscreen invisible help game performance?  Like lets say I have 100 characters offscreen because I’m running a battle scene (my game isn’t, cool thought though), would it make it any faster if I gave them the .isVisible=false?  

@cjc83486:

With multiple tilesets, it has to use display groups, which are A LOT slower. If you can compress it into a single tileset, image groups are available, which are faster. It’ll still probably not be ultra-fast, but it will be a bit faster.

Corona already does basic (maybe not basic…) culling - just get a large tilemap and see the FPS difference between it being on the screen and outside the screen. I don’t think “invisibling” objects will do much.

@No2Games:

Great idea - I’m thinking it might be better to use the .draw() and .erase() functions on move - the references could get muddled up with moving+frame changing. For example, tile [“1.1”], when moved to the other side of the screen (let’s say position [“24.1”]) would still have the title “1.1”. So if you tried to .getTile() or something like that, you’d pick up 24.1 instead of 1.1 for the tile you’re trying to get.

C

Hey Caleb, 

 

I’m finally getting to the culling part of my game and (as you have seen) is quite a challenge.  So I took a quick look at your quartz Tile renderer.  

 

Currently, what I’m using for my game is CoronaTiled by no2games for objects and tiles, and Perspective (it put a grin on my face when I saw) by you.  

(I was using my own camera function with scrollviews before, but the scrollviews kept consuming my touch events, so I decided to switch to Perspective which is pretty solid and works the same or better of what I made, but wasn’t having touch event problems.)

 

Anyway, I looked through it and I couldn’t get it to load a map right away, I found that it was only the tileset file having a directory not from my computer.  I just removed the extension and made it “open_tileset.old.png” as shown:

 "author":"Silveira Neto" }, "tileheight":32, "tilesets":[ { "firstgid":1, "image":"open\_tileset.old.png", 

 



After that I noticed it had a whole bunch of gaps between the tile (especially when scrolling).  I'm not sure if this is just me or my computer or what.  I saw that your fps is 60 on the Corona Simulator but about 15 on IOS iphone simulator.  Is this just me?  I never know it's me or the code..  Here is a screen shot:



![ScreenShot2013-03-17at11448PM.png](http://i1110.photobucket.com/albums/h455/cjc83486/ScreenShot2013-03-17at11448PM.png)



 



For my game I use a config file that seems to fix the sizing and gaps in the tiles (for Iphone, iphone 4, and Iphone 5 at least..)  I can quick send/post it if you are having these spaces as well. If you aren't, do you have any idea why I'm getting these gaps using the same code you are?



 



Anyways, when I use my config file it looks great and renders about the same (60 on corona, 15 on iOS).  I know that with culling by not loading the entire map it should work way faster.  Also with my config file, it makes the tiles larger, so thus I assume with culling it would work slightly faster because it has less tiles to load per width and height of screen.



 



Oh, one last thing Caleb, I was wondering how we were going to integrate both Quartz and Ceramic (CoronaTiled)?  Are you guys going to eventually merge the code, or will the user have to somehow combine the two? Also, for culling, I was wondering since you created Perspective, if that would be the best way to go about culling.  Since it already has a camera function built in, you could make it so anything out of the screen on the scrolling layers were removed/purged.  I don't know if that makes it easier or adds complexity though.



 



Thanks!



 



-Curt

Firstly, gaps between tiles. I’ve found that it doesn’t happen if the device vs. screen size is the same. So a 320x480 config.lua file won’t have gaps on an iPhone simulator - but it will on an iPad simulator. And a 1024x768 config.lua won’t have gaps on an iPad simulator, but it will on an iPhone simulator. I don’t know what’s causing this.

 

Secondly, FPS. Culling will come. That’s all I can say. But, I had no idea it would go so slowly on the iOS simulator… I expect it’ll be about the same on device. Oh well. I wonder why it went so fast in the simulator…

 

Thirdly, Quartz and Ceramic will, in the end, be in the same library - probably named something straightforward like “CoronaTiled”. You’ll render maps and object layers with CoronaTiled, which will, in turn, use Ceramic and/or Quartz to build the map. I’m not exactly sure how that’ll work at the moment, but we’re not at that point yet.

 

I’m thinking that I’ll use my own camera function for Quartz. Using Perspective will, in my opinion, simply expand the library into a bigger one - I think it’ll be easier just to make a simpler, independent, tile camera.

 

Anyway, you’re a big help with debugging and feedback :slight_smile:

 

C

@Caleb-

The camera function doesn’t really matter to me, but I really like how you did the layers in Perspective. It is a pretty solid camera library!  But I trust you’d make about the same quality either way, so I was just trying to save you some time. :slight_smile:

Culling-  It’s kind of crazy but I’m actually at that point where I’m looking at performance of my game engine.  So far for testing I’ve taken my characters and objects out to see if they are causing a lot of lag, but it seems its more or less the map engine (on my computer it is fine, but if I try to screen record my Corona Simulator or put my game on iOS Simulator, the performance suffers significantly).  This makes sense, because I’m rendering an 11 layer 96x80 tile sized map with 2 pretty big tile sets.  Do I actually need that big of a map/level?  No, but I feel with culling we should hopefully be able to run this at least at 30FPS on the phone.  With culling, map size shouldn’t really make a difference, the performance really would only be affected by the number of layers and tilesets used, correct?  I’m not sure how your guys’ map engines deal with empty tile spaces currently (with multiple layers that don’t use every tile this might be something to look into).

Anyway, I really like your Draw and Erase functions!  Actually, if that was in Corona Tiled right now, I think a lot of my lag would vanish.

@no2games-

I was thinking about culling, and I was wondering how we are going to be handling objects(and physics objects) that are off the screen?  It is basically under the same realm of culling a tile map, are we going to add them when they are close to the display or are you going to leave that up to the user?

Hey guys,

Sorry, I’ve been working on an HTML5 game project for the past week and then i have the GCD next week–so I won’t be back on Ceramic until April.

However, I had an great idea on how do do the culling without having to change anything with how a user loads a map and should only take me a few days to get working.

Here’s the concept… When you load a map it will return a big transparent display group the size of the map. Inside that display group there will be enough images to cover the screen with and extra row or column on each side. The display group will have an enterFrame() event that tracks it’s x,y vs the screenBounds and will shift the extra row or column around if the x,y changed enough that the any row went offscreen.

So at most you will only need to update a couple of rows and most of the enterFrame() events will be invalid anyway.

I think this will give the maximum performance and will allow for large maps that can be moved easily. Plus no map.update() event would be needed so it would be easy to implement.

@Caleb, I think this is kind of like your approach, but it looks at relative position of the map, rather than rendering the tiles at a position.

@cjc83486 I don’t know how physics objects would be handled yet, but I imagine they would need to be around regardless of where the map is being drawn. You can’t have a floor that’s holding a bunch of objects up dissapear just because it scrolled of screen :slight_smile:

@no2games

haha, very good point, I guess the idea sounded better in my head, :).  Hmm pertaining to my own game though, side from your tile renderer… would making my objects offscreen invisible help game performance?  Like lets say I have 100 characters offscreen because I’m running a battle scene (my game isn’t, cool thought though), would it make it any faster if I gave them the .isVisible=false?  

@cjc83486:

With multiple tilesets, it has to use display groups, which are A LOT slower. If you can compress it into a single tileset, image groups are available, which are faster. It’ll still probably not be ultra-fast, but it will be a bit faster.

Corona already does basic (maybe not basic…) culling - just get a large tilemap and see the FPS difference between it being on the screen and outside the screen. I don’t think “invisibling” objects will do much.

@No2Games:

Great idea - I’m thinking it might be better to use the .draw() and .erase() functions on move - the references could get muddled up with moving+frame changing. For example, tile [“1.1”], when moved to the other side of the screen (let’s say position [“24.1”]) would still have the title “1.1”. So if you tried to .getTile() or something like that, you’d pick up 24.1 instead of 1.1 for the tile you’re trying to get.

C

This looks really cool but I’m missing something about the physics.  Is there an option to draw a polygon physics shape around a tile and place it in Tiled?  Can you tie a Polyline shape in Tiled to a tile on an object layer?  Like in the demo scene that comes with the code, if you were to put a non-square tile on the boxes layer, how would you draw the physics shape for it?

Thanks…

Hey Guys,

Since it’s April, and we’ve all been MIA for a long time, I thought I’d post to get us all thinking about Corona Tiled again.

As far as the tile renderer that Caleb is working on, it should be fairly easy to set up a culling system using the draw and erase functions, or using no2games method.  With the latter, you’d have a slightly faster culling system: instead of removing display objects and adding new ones, you’d move display objects to the other side and change the image.  Either method will be much faster than loading the whole map.  

After that is done, all that’s really left is to merge the two tile engines into one so that the user can finally have the best of both in one. This will take you guys having to decide on which little things you want to keep from each, but it needs to get done.

Thanks for both of your guys’ work.  I’m not sure I could have done my game without you two, or at least with a free tiling engine.  When these two things are done I feel like it should cover 90% of peoples’ needs and shouldn’t worry about updating the engine as much.

Right now you would have to set a custom tile type and loop through the map data to set a tiles physics shape to something custom. If its just one or two custom tiles you could draw them as a vector shape.

Really what I should do is support the basic platformer shapes like slopes, ladders, one way platforms, etc. That way you can set a tiles property to “slopeRight” and it would just get the right shape at the scale of the tile.

Here’s the types of tiles a basic platformer should support …
https://github.com/otternq/GamesVirtualEnvironmentsWeb/diff_blob/91899a76c9f0c31e2d263751f41504853f8b4a1f/src/games/homework1/data/area01_tileset/metatiles32x32.png?raw=true

I’m pushing some updates soon, maybe I will implement slope physics in the next release.

Oh, no2games youre on!

How hard do you think it is going to be to merge both of your guys’ engines?  I mean, I could use Caleb’s draw and erase functions to make my own culling system right now, but it seems silly until they are both combined.

Thanks again guys!

I’ve actually been melding them for some time - I should be finished in a day or two.

C

@cjc

Yeah. It’s been a busy few weeks with the GDC, but I have been working on updates that just haven’t been pushed to GitHub yet.

  1. Now you can load just a portion of the map by calling a top, left, width and height tile. This is the basis of a culling engine, because these loads can happen super fast if you are only calling a few tiles.

  2. Started TMX map support.

  3. Physics updates and fixes. Plus I will probably implement slopes like we’re mentioned in the last post. Should be easy to do.

I just need a full day at home to get them organized and push them out. I’m trying to do a top down RPG with some physics, so most of what I’m dropping in will focus on what a Zelda-like game would need.

I have a little shooter project I’m working on first, so it may be a while before CoronaTiled gets “complete” but I agree this is plenty for most people’s needs. Plus it’s open, so I expect others to add what they need for their particular games.

Good stuff! Look forward to seeing it Caleb.

Awesome guys!  Thanks for the update,  I’m hoping to eventually show you guys what i’ve been working on but I want to make sure I’m a good way into it first.  Happy coding!

@JohnPaul Here’s what I’m thinking of…
 
slope_example.png
 
So now you can edit a tile’s properties as part of the tileset. So if you had a glass tile and you wanted it to be at a 50% alpha you could add that property to the tile in the set, and then every time you place that tile it gets the alpha value set.
 
With that I’m adding a “shape” option that will allow for sub-shapes beyond a square tile. I’m thinking slopes could be ne/nw/se/sw and walls could be top/bottom/left/right. If you wanted to go crazy, you could add corner pieces like in the tileset you see here.
 
So adding a custom shape would just require going into Tiled.lua and adding a new shape beyond the default ones…
 
[lua]
– set Physics properties

if layerGroup.physicsData.enabled==true then

local points

if tile.shape == “nw” then

 points = {0,0,tileWidth,0,0,tileHeight)

elseif tile.shape == “ne” then

points = {tileWidth,0,tileWidth,tileHeight,0,0)                                        

elseif

(and so on…)

end

physics.addBody(tile, “static”, layerGroup.physicsData, shape=points)

end

[/lua]
 
Again, I’m trying to get this update out in a few days

Excellent. I think that will work nicely. Would it make sense to be able to define the shape points in the editor and assign it to the tile in the property editor for odd shapes instead of putting them in the code? Something like if you set the shape property to [{0,0}, {0,0}, {0,0}, {0,0}].

I never think the Tiled editor is a good place to put in data, but you are probably right. :slight_smile:

addBody() looks for points like this x1,y1,x2,y2,…xn,yn, so I could just let you set the shape like this 

[lua]

shape = -20,-10, 20,-10, 20,10, -20,10

[/lua]

and just pass it to the addBody() call. That would be a piece of cake.