Tiled Map Engine

@Caleb, regarding the gaps on iPad.

We were using our own implementation of a tiled map reader before (moved to tiled.lua since we found this thread…).

In both implementations there was this same issue. We have found the problem, not sure it’s been mentioned on the thread (I went through it but it’s quite long…):

The gaps appear when the tile width/height are not a multiple of display.contentScaleX/Y. And the reason is that when the tiles are converted from Corona “points” to actual device pixels there are fractions involved.

Here is an example:

  1. We are using “letterbox” mode in config.lua, this implies that display.contentScaleX and display.contentScaleY are identical so I’ll refer to their value as “content scale”.

  2. We have a tileset with 32x32 tiles.

  3. When the map is loaded Corona needs to convert 32x32 images to real device pixels. On iPhone 4 it’s converted to 64x64 which is nice a tidy (the content scale is 0.5).

  4. On iPad the content scale is ~0.46. this means that after conversion to device pixels the images are 69.56. Of course device pixels are actual hardware pixels and therefore cannot be expressed with a fraction. This means Corona is forced to round it up or down which causes gaps of 1 pixel. The pattern of the gaps changes depending on the tile size and the content scale.

In our case we did not really care that much about the EXACT size of a tile so our solution was to slightly adjust the size Corona loads the images (we haven’t touched the actual tile size in the imagesheet) so that the size of the image in real device pixels would be a round number while in the size in Corona “points” can be a fraction

We have just added the following lines to tiled.lua:

local pixelWidth, pixelHeight = tileWidth/display.contentScaleX, tileHeight/display.contentScaleY tileWidth, tileHeight = math.floor(pixelWidth)\*display.contentScaleX, math.floor(pixelHeight)\*display.contentScaleY  

This solved the issue but made the tiles a bit larger on iPad which we don’t really mind…

Another solution would be to have a dynamic config.lua like in this post:

http://www.coronalabs.com/blog/2012/12/04/the-ultimate-config-lua-file/

In this manner you can dynamically set the content width and height (we use the default 480x320) depending on the device model or actual resolution (display.pixelWidth/Height). The idea is to modify the width and height in such a way that the content scale would device nicely with your tile size…

The downside of using this method is that your content size is not constant and it’s harder to maintain a consistant layout of the UI across different devices with different screen ratios.

PS, the problem is much more severe once you release to Android because there the fragmentation is huge and you need to be able to support a wide range of different content scales.

@qtt
 
Interesting. It wasn’t the scaling in my project that was covering the gaps it was  the GL_Nearest scaling…
 
[lua]
display.setDefault( “magTextureFilter”, “nearest” )

display.setDefault( “minTextureFilter”, “nearest” )
[/lua]

I went ahead and included a version of your “tile scaling” into the project. I also needed to scale all the other objects by the same percentage in the map so any object-based physics still line up. (I spent an hour trying to scale the objects up, but it always seemed to produce gaps, so closing the gaps is by far the best bet.

I should push out the 0.6 version shortly–it also includes some of the GUI stuff, but that’s not quite ready for primetime yet. :slight_smile:

That was fast :slight_smile:

Can’t wait to test out 0.6, we are working on a fresh new educational plane shooter game and we are using your project to build the terrain map. works great.

In our game the plane is flying up (in portrait mode) and enemies come in from the top flying down. Would you recommend using spawn points to define where and what kind of enemy planes are generated?

Currently the “sky” object that contains all the physics objects is actually totally seperated from the tile map, and all the objects are defined in code and not in Tiled.

I’ve been using Image Objects to place “bad guys.” That way you have some sort of visual representation of where somthing goes and it’s not bound to the grid co-ordinates…

Once you have a layer of image objects you can find them and apply properties like this…

[lua]

        local found = tiled:findObject(“badguy”,map.data)

        count= #found

        for i = 1, countdo

            found[i].image:setLinearVelocity( found[i].image.dx, found[i].image.dy )

            myGroup:insert(found[i].image)

        end

[/lua]

This little piece of code finds all the “Image Objects” in a tiled map, sets their velocity to the dx and dy properties and puts them in a group.

Hey just stumbling upon this source code. Just a few questions:

i see this application uses “tiled” to create the tilesets and map. If i was to create my own RPG can these tilesets be modified to my specifications?

IE make tiles larger, maps bigger etc. 

Im looking to use this as a base for an RPG project want to work on thanks in advance. looks amazing so far guys.

Absolutely - Tiled is simply a level editor. You can specify your own images for tilesets, choose the tile width/height, the map width/height, whatever.

C

Nice, thanks!

I’ll implement something similar. Just so I’m clear, dx and dy are object properties you have set in Tiled Map Editor, right?

Yep, those are custom properties. That’s really the coolest part of this whole setup, you can find all the objects in the scene, read their custom properties and do something with them. 

Or, if you set Corona display object properties like, Xscale, rotation, alpha, blendMode, etc. they just work.

Or, you can set the properties that take colons like shape:, physics:, etc. an those get used when the display object is created.

Again, I really need to do a screencast  :slight_smile:

Caleb and Mike:

http://lime.outlawgametools.com

I didn’t know if you guys had seen this, thought it’d be good to point out it has finally gone Open Source :).

Not sure what all is useable now that Corona has changed so much… 

Yeah, I tried it out… In my opinion, it makes a lot of unneeded(?) globals and is very large.

So I think I’ll stay with this, for the moment :slight_smile:

Looking forward, though, to see what’ll come of it!

C

Okay, version 0.6 is up on GitHub…

https://github.com/superqix/CoronaTiled/archive/master.zip

It’s got the tile gap fix, as well as the new GUI stuff with a simple example of a opening menu. The new GUI stuff looks like this… (it looks seamless on the device, the simulator still shows some gaps…)

You call the GUI just like you would a native.showAlert() with a onComplete() listener…

[lua]

    local function onComplete(event)

        if event.action == “clicked” then

            if event.name == “launch” then 

                menu:removeSelf()

                startGame()

            end

        end

    end

    menu = tiledMap:loadGUI(‘menu.json’,onComplete)

[/lua]

That listener has an “event.action” just like native.showAlert() with “clicked” as the action for a button being touched. (I know it’s a silly name, but that’s what native.showAlert() uses…) Then the event.name is the name of the button object.

This stuff is VERY basic right now, but still pretty powerful for building a quick UI. For a more complicated UI, you could use an image layer that you built in photoshop and use buttons to trace the outlines.

As always, testing and bug reports are welcome.

Quick question - beginning to dig into Corona Tiled a fair bit now and like what I’m seeing, congrats guys.

I began developing a basic tile engine a while back, primarily to test out my A* implementation for a stealth-esque game.

The A* worked primarily on a 2D array representing the map - does Corona Tiled provide this raw data anywhere (essentially a grid of x,y cells)? I’ve dug into MapData but can’t see anything that could possible help out.

Cheers…

It’s buried in the “data” table that’s returned with the display object…
 
This is how you would find a GID value by x,y of the tile…
 
[lua]
local map = tiledMap:load(“demo.json”)
local x,y,layer = 15,20,1 – find the tile ID (GID) of the tile at 15,20 on layer 1
local item = ((y-1) * map.data.mapWidth-1) + x
local tileGID = map.data.layers[layer].data[item] or 0
[/lua]

The GID is tiled “universal” ID for a tile in the set. It’s basically a running count of every tile in every tileset.

There are a few functions I’m planning on writing to help things out and this should probably be one of them, because if the layer isn’t a tile layer then map.data.layers[layer].data[item] would be nil and probably throw an error.

These are the functions I’m finding I need now…
[lua]
function tiled:findLayer(layerName)
function tiled:showLayer(layerName)
function tiled:hideLayer(layerName)
function tiled:findTiles(GID or Name)
function tiled:getTileGID(tilex,tiley,layer)

[/lua]

There are probably some more too…

Thanks for the info. I think having “accessor” functions is a good idea, thus expanding the library’s versatility. I’m needing to carry out plenty of logic on the environment, the more data I can squeeze into the map and handle through game logic the better :slight_smile:

The more I use CT the more comfortable I feel, if I make any notable additions Ill make sure to push them over.

Thanks. 

I’m still working on moving the work Caleb P into the library. Once I get that done, I will spin out a 1.0 release and try to normalize all the naming conventions, clean up the code, etc.

Part of adding Caleb’s stuff in there will be a split from the Loader function and the Render function, so you would be able to load a map up and get access to all the data/physics/etc but not have to render it–or use a different function to render.

Anyway, one day at a time…  :slight_smile:

Taking a look at the City map you posted a few pages back I think that will probably help as the map runs pretty slow, so I was planning to take a look at what culling could go on. Before I took a look at Corona Tiled I was following a Javascript Tile Engien tutorial (http://nielsgrootobbink.com/wokflok/jte/) - that uses the concept of a Viewport to handle what gets rendered onscreen.

Although the tutorial so far is re-rendering each image whenever the viewport/camera is moved - a direct implementation in Corona was replicating the tiles all over the place, so I was working on improving that. If it has any application to what you’re doing let me know and we might be able to work on it. The only problem I cant get my head around at the moment is what’s the best practise:

Start by only rendering tiles in the viewport.

When the viewport/camera moves I was running through all tiles, deleting them and then rendering the appropriate tiles. However this was slow, so trying to look at a better way - I know some people have mentioned using an ImageSheet and changing the frame so I began implementing that but didn’t notice any speed improvement - I believe my issue is the time taken to remove all tiles and the re-render.

On another matter I noticed you’ve used ImageGroups for maps with only one tile set; however reading Walter’s comments in this blog post (http://www.coronalabs.com/blog/2013/04/29/corona-weekly-update-starter-vs-pro-plugins-and-graphics/#comments) it seems they’re planning to remove ImageGroups with the implementation of Graphics 2.0 - perhaps something to keep in mind. It looks as though ImageGroups were merely a workaround to squeeze some efficiency and the new “groups” will be vastly improved.

Yep, ImageGroups are on the way out for sure. I have them commented out of my dev version because you can’t add them to a Storyboard Scene…

I’ve looked at using just enough tiles to cover the screen and just moving them around when they go off screeen. This is the way to go, but right now it’s a little complicated with all the layers and physics options a map can have. It’s a long term feature for sure, but for maps up to 10x size of the device screen, what it here is works. 

Again breaking out the loading/physics/render routines is the first step–and that’s well underway.

Hey just stumbling upon this source code. Just a few questions:

i see this application uses “tiled” to create the tilesets and map. If i was to create my own RPG can these tilesets be modified to my specifications?

IE make tiles larger, maps bigger etc. 

Im looking to use this as a base for an RPG project want to work on thanks in advance. looks amazing so far guys.

Absolutely - Tiled is simply a level editor. You can specify your own images for tilesets, choose the tile width/height, the map width/height, whatever.

C

Caleb and Mike:

http://lime.outlawgametools.com

I didn’t know if you guys had seen this, thought it’d be good to point out it has finally gone Open Source :).

Not sure what all is useable now that Corona has changed so much…