Tiled Map Engine

An 0.5 Update is now live that fixes a bug in Objects being lower than they should have been. Also starting support for Sprites as ImageObjects and/or Tiles. Right now you can set the Corona sequenceData for an ObjectLayer and any image object will become a sprite…

An example is in the demo.tmx

@No2Games:

As much as I hate to say it, you might want to start melding them. I’ve got a personal project that’s taking up most of my coding time, and I really don’t want this just to go downhill on account of me. I work on the melding here and there, but if you want it to be actively worked on, you might want to do it.

I am floored that this project has gone this far, and will be willing to do upkeep (or melding still, if you don’t want to do it). As of today, I’m still melding them - if you’re willing to start working on it, though, I’ll stop.

C :slight_smile:

Just wanted to offer some enthusiasm on this - it’s great to see community led, open source projects filling the gaps of Corona. I’m viewing the project and hopefully might be able to offer some input, but feel that what I’ve seen so far is already flying over my head. Without wanting to interfere, what was the breakdown of tasks - as far as I can see it’s only no2Games and Caleb working on it so far???

Yep - Me and No2Games are really the only makers.

I’ve done some rendering code work and created Gridmap (which was one of the two basises for this project), and he’s done everything else (porting Gridmap + Tiled.lua code together, object layers, image layers, physics, etc.). This project couldn’t have even gotten off the ground without No2Games :slight_smile:

By the way - that post above is not a resignation. I still want to be an active maker/creator/editor. I really enjoy this open-source communication and collaborative work :slight_smile:

C

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.

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, I will give it a shot if you want to post what you’ve got. I started working on culling, but it’s one of those things I don’t really need for my project (and it’s really hard) so I didn’t spend much time on it. If your stuff gets me half way there, maybe I can get it working.
 
Otherwise, I’ve picked up the pace on this project as of late because of some of the updates to Tiled are letting me use the Object Layers as a level builder in my latest project. So, I’m really focused on TileObjects, Sprites and the like, but I’m happy to add other features that people want.
 
If people want to help, there’s really a few things that are bugging me:
 

  1. This bit of code shows up a twenty or so times in the module…
     
    [lua]
                if properties then
                    for k, v in pairs(properties) do
                        if string.find(string.lower(k), “physics:”)~=nil then
                            layerGroup.physicsData[strRight(k, “:”)]=properties[k]
                            if layerGroup.physicsData[strRight(k, “:”)]==“true” then
                                layerGroup.physicsData[strRight(k, “:”)]=true
                            elseif layerGroup.physicsData[strRight(k, “:”)]==“false” then
                                layerGroup.physicsData[strRight(k, “:”)]=false
                            elseif isNumeric(layerGroup.physicsData[strRight(k, “:”)])==true then
                                layerGroup.physicsData[strRight(k, “:”)]=tonumber(layerGroup.physicsData[strRight(k, “:”)])
                            end
    [/lua]

…and we use this bit to turn a “physics:enabled” : “true” in the JSON into…

[lua]layerGroup.physicsData.enabled = true[/lua]

…in Corona. I would love a local function that could replace all the occurrences. It would make debugging a ton easier.

  1. Maps and Tilesets need to be in the root folder, because Tiled will include directory info with the tileset… I’m stripping it like this:

[lua]imageSheets[sets] = graphics.newImageSheet(string.match(tileSet.image,’([%w_]+%.%w%w%w)$’), options )[/lua]

…but there’s got to be a better way to look for that tileSet.image in the same directory as the JSON file.

And some big things that need to get done…

  1. Documentation. Next week I’m going to spend the time to do a screencast of how to build the demo project. Maybe someone could volunteer to transcribe that howto into the Wiki here on GitHub?

  2. Sample projects. I’d love to see a small physics-based platformer made from some open tile set. Maybe this one…

http://opengameart.org/content/updated-generic-platformer-tiles

 …it would be nice to have a larger project to come up with use cases from. An RPG too maybe… I did a little RPG in HTML5 and JavasScript that the graphics/maps could be used from…

http://michaelwilson.tv/pq/

  1. Other than that, just Fork the Repository, make some updates and send pull requests. I’m sure there’s more speed to be gained in the map loading.

So far on the melding, I’ve added the ability to render, erase, create object layers, image layers, and add tile physics to maps (the physics part still isn’t finished). I’ve got a library called “Glass” that loads a map into an easier format.

Here’s the Glass load format:

mapData

    tilesets - Not used, just a reference table

        tilewidth - Width of the tiles

        tileheight - Height of the tiles

        image - Image path

        imagewidth - Width of the image

        imageheight - Height of the image

        numCol - Number of tiles that fit from left to right across the image

        numRow - Number of tiles that fit from top to bottom across the image

    tileref - A numerical index of the tilesets, each number in it corresponds to a number in a tile layer’s “data” table and the resulting tile image can easily be found

        1-#tiles in the map - Table containing tile data

            tileset - Not used, a reference to the tileset (see above)

            sheet - The imageSheet for the tile

            frame - The frame for the tile

            data - The sequence data for the tile

            EXTRA: With the tileref, you’re able to create tiles easier by simply collecting the associated “data” number and using the tileref references

                

                local thisTile=display.newSprite(tileref[theDataNumberYouHave].sheet, tileref[theDataNumberYouHave].data)

                    thisTile:setFrame(tileref[theDataNumberYouHave].frame)

    width - Width of the map in tiles

    height - Height of the map in tiles

    tilewidth - Tile width

    tileheight - Tile height

    layoutCount - Number of tiles (total) in the map

    layout - Table containing grid positions (not exactly needed, but I use it in Quartz - it can be removed)

        [1-height][1-width] - Grid tables

            tileX, tileY - The position in tiles of the grid unit

            pixelX, pixelY - The position in pixels of the grid unit

    layers - Table containing layer data for the map

        tile - Table containing tile layer data for the map

            tilewidth - Width of the layer’s tiles

            tileheight - Height of the layer’s tiles

            data - Layer data table

            properties - Converted properties for the layer (see the “helper.convertProperties()” function)

        object - Table containing object layer data for the map

            objects - Layer object data table

        image - Table containing image layer data for the map

            image - Image path for the layer

Be warned that my code is by no means complete, nor the best that it could be - it’s just a prototype :slight_smile:

You can download it here: https://www.dropbox.com/s/s33yk4tm61f2ne5/CoronaTiled.zip

  1. I’ve created a basic function, called “convertProperties”, that arranges values into a table. Here’s what’s returned:

tileProperties

 -Physics

   -All properties preceded by “physics:”

 -Tile

   -All properties preceded by “tiles:”

 -Layer

    -All properties preceded by “layer:”

You’ll find it in the “helper.lua” file. If you can think up a good name for it, you can name it.

  1. I’m not exactly sure what you’re asking, here, but I think you’re attempting to strip the prefix of the tileset image path that Tiled adds (something like “/…/users/somebody/documents/whatever/tile.png”). Is that right?\

Big projects:

  1. Documentation (transcript) - Sure! (that is, if I figure out GitHub, which I’m getting closer to doing :))

  2. Sample projects - I’m willing to work on it/them :slight_smile: (nice RPG, by the way!)

  3. Ok - great :slight_smile:

(note the triple emoticons of eternal power)

C

By the way, if you can get the melding finished, I’ll be more than glad to work on culling.

C

Hey all

I’ve not read through the whole thread but I was working on a tile map that could load mega textures gigabytes in size. It was all quite complicated so I wont go into it now.

But the solution to gaps between tiles showing on movement or different screen resolutions is to load a low res image, ( 1024 x 1024, or even tile a few images together ) of the entire level and put it behind the tile map layer. This has the effect of even if gaps appear the right colours show through and it makes it a lot less noticeable.

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:

@Matthew

Thanks for the advice. I’ve been looking at making the tiles 0.5 units bigger to help cover those seams too, but in my projects I start at the max res (2048-by-1536) and scale my way down, which seems to work also.

I know it’s been quiet here, but there has been some progress. I’m making my way through the code @CalebP posted, and I’m trying to rework the loader to make the whole thing more modular.

Also, I had an interesting idea for the GUI in my current project…

This seems to work pretty well with the “type” of the object corresponding to the Widget 2.0 object and 9-slice tiles acting as the borders. I HATE hand coding menus and the like, but this makes it a little more fun… Like building a level…

I don’t know if this will just be an example with the current build, or a separate Module.

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.