Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Rendering huge tilemaps

edited July 2016 in Questions Posts: 502

@Ignatz @yojimbo2000 I'm currently working on a roguelike 8bit open-world rpg. I decided not to generate my maps but rather design them by hand. Therefore I need to create a map editor. My question is somewhat similar to @Slashin8r in his thread: https://codea.io/talk/discussion/3058/utility-rpgenerator-v0-7-23-build-your-own-rpg-in-codea/p1


image

What I currently do

  • Editor gets one tilesheet (128x128px)
  • Each tile on spritesheet is 8x8px
  • Each tile can have a flag (similar to PICO-8). It's really just a number which can be interpreted as anything (for example as a layer name)

The coloured circles are sprite flags for the current sprite.
Each one can be true (on) or false (off).
They are indexed from 0, from the left (0,1,2,4,8,16,32..).
The initial state of flag are settable in the sprite editor, using the line of little colourful buttons.
The meaning of sprite flags is up to the user, or can be used to indicate which group ('layer') of sprites should be drawn by map.

For my game I assume that the world has regular tiles (floor, wall, water, lava) and special placeholder tiles (enemy, player, guard, treasure, light source,..) which will be replaced by the engine at runtime with real interactive objects. These objects have states, animations and actions (attack, breath, idle around, protect sth., etc). Plus the world is drawn in layers (one layer per ground, walls, obstacles, players, etc).

Right now the editor saves drawn tiles into projectData like `saveProjectData("x y flag", spriteIndex)
When I start my game, the editor does some work for me. It calculates which tiles should be on screen and loads them in. Then it setups these tiles for me - initially, each tile as an object on its own (internally its a class with a mesh and one rect, textured by spriteIndex).

Now, I know about my world (as I have drawn it). I know that a have created a "layer" of tiles for enemies, say this layer has the flag number 25! I can now support my editor with a table World{["25"] = Ork,...} which specifies which "layer" gets setup with which class. And now they automatically have props! I thought that would be very easy to manage.. This way each tile can respond easily to touches and draw updates and I can keep the relevant code in the right place.


image
image

The issue

My problem is now that the editor is somewhat inefficient at rendering. I mean, I still get 60fps on an iPad Pro, but the memory consumption is way to high (~1.3Mb)! The editor has to draw, say 5 layers, and each of them has ~100 tiles, which in turn are all separate objects (meshes). So to say: I it makes 500 draw calls each frame!

I can not come up with an effective infrastructure for this whole thing. How to store the map efficiently into projectData. How to load and batch the tiles, but still be able to "speak" to each of them. Like, when I batch the ground and wall tiles into one mesh, but the ground has grass and dirt tiles, how could I easily say which sound to play on each? With my current setup, I could just make two classes (Dirt, Grass) and inside the touched method I would fire a sound. Another concern is how to batch, but still have animations and states?

Tagged:

Comments

  • edited July 2016 Posts: 502

    Addition: The question is not so much about technical solutions (they are still welcome though), but rather how to wire this whole thing!

    I know how I could batch tiles or how I would identify on which tile the player currently is. But what I'm interested in is how to give the editor information and let him figure out what goes where and how. The communication between everything. The infrastructure. The bigger picture.

    I want to make this editor flexible, so that every kind of pixel-art game can be done with it, no matter how big or complicated. The editor just creates and displays the map. It also redirects touches to objects on screen. But everything should come from the outside (plugged-in by classes).

    I hope this makes more sense..

  • Posts: 2,020

    My problem is now that the editor is somewhat inefficient at rendering. I mean, I still get 60fps on an iPad Pro, but the memory consumption is way to high (~1.3Mb)! The editor has to draw, say 5 layers, and each of them has ~100 tiles, which in turn are all separate objects (meshes). So to say: I it makes 500 draw calls each frame!

    500 draw calls sounds a little too high. You mentioned 5 layers. Try batching things that belong in the same layer onto a single mesh (especially if they're relatively static). If you have bitmap animation frames, try batching those together into a single texture too. It looks like your assets are square and the same size, so should be easy to put them all in a mesh and retrieve them.

    Is 1.3Mb too high? That sounds OK for a texture-intensive game? Just curious how you decided what the ram-usage should be. (you are storing those pixel-art assets at the lowest possible resolution and then blowing them up, I assume?) Doesn't an iPad Pro have 1gb RAM?

    TBH, this kind of thing is kind of hard to do in Codea, compared to a desktop-class IDE, which have built in support for texture-atlases, tile-map editors etc. You don't have to think too hard about how to wire it up and concentrate instead on the good stuff, like gameplay (Xcode 8 now has a built-in tilemap editor. The other IDE I've been looking at is Defold, http://www.defold.com it's made by the creators of Candy Crush, free, Lua-based, cross-platform)

  • edited July 2016 Posts: 502

    @yojimbo2000

    500 draw calls sounds a little too high. You mentioned 5 layers. Try batching things that belong in the same layer onto a single mesh (especially if they're relatively static). If you have bitmap animation frames, try batching those together into a single texture too. It looks like your assets are square and the same size, so should be easy to put them all in a mesh and retrieve them.

    Since right now everything is just an object (a mesh inside) the animations are just a table of spriteIndices which I swap at certain fps. The "breathing" animation from the video above is an endless tween().

    I could batch every layer into one mesh object. But how would I then update each tile (position, states, sounds, etc)? Would I have to re-render the whole mesh then? Or are there other possibilities?

    Is 1.3Mb too high? That sounds OK for a texture-intensive game? Just curious how you decided what the ram-usage should be. (you are storing those pixel-art assets at the lowest possible resolution and then blowing them up, I assume?) Doesn't an iPad Pro have 1gb RAM?

    Yes. I store every animation and every tile at lowest resolution inside the same tilesheet. - What I meant by memory here is the Lua memory usage! Storing everything as a separate object understandably raises the memory. And I recall hearing that Codea only supports up to 2MB of Lua memory.

    TBH, this kind of thing is kind of hard to do in Codea, compared to a desktop-class IDE, which have built in support for texture-atlases, tile-map editors etc. You don't have to think too hard about how to wire it up and concentrate instead on the good stuff, like gameplay (Xcode 8 now has a built-in tilemap editor. The other IDE I've been looking at is Defold, http://www.defold.com it's made by the creators of Candy Crush, free, Lua-based, cross-platform)

    I think Codea could handle such a game performance-wise but coding would be a pain as code grows.

    I tried defold a while ago. Seemed quite nice! But I still would need to come up with my own batching and structure anyway.. I don't think they have management for this thing built in. Would you recommend switching defold for this game?

  • Posts: 2,020

    But how would I then update each tile (position, states, sounds, etc)? Would I have to re-render the whole mesh then?

    Use setRect to move it, and setRectTex to change the texture for animation. You only draw() the mesh once per frame. With rects, think of draw() as a class method, not an instance method.

    I tried defold a while ago. Seemed quite nice! But I still would need to come up with my own batching and structure anyway.. I don't think they have management for this thing built in. Would you recommend switching defold for this game?

    I just worked through the defold tutorial, about 6 months ago. It's had quite a few releases since then. It seemed to have a nice editor for arranging 2D assets.

    What you have looks great though, and Codea is still hard to beat for rapid, on-device iteration. Or for coding on the train.

    You could also have a look at iPad apps for creating sprites. There's a few now. Pixartu (free, looks promising but has quite a few rough edges still), Sprite Something, Sprite Creator. The last two apparently also support tilemaps, I've not tried them. You'd need to work out what formats they export in, and how easy it would be to bring that in to Codea.

Sign In or Register to comment.