Tilemap Techniques

Monkey Forums/Monkey Programming/Tilemap Techniques

ElectricBoogaloo(Posted 2013) [#1]
It seems that, as the technology and coding methods "improve", 95% of the technology is being targeted at making the next version of Call of Duty have 32% more grit on the screen..

Which is nice, for people who like that sort of thing, but completely useless when you want to scroll a tilemap.
It's getting harder and harder to draw layer-upon-layer of scrolling background, simply because, for whatever reason, modern techniques pretty much suck at it.

Today I attempted to replicate an Amstrad CPC's Mode 1, before realising that 40x25 screen resolution is in fact 1000 sprites.
Yikes!!
Sure, Monkey can cope with it, but on various targets, you're not going to have any leftover system to play any sort of game in.
Sucks..
and that's only one layer!

So far, my best techniques have revolved around larger chunkier background tiles, and scrolling over the larger areas, but in this case I wanted to do lots of small tiles onscreen at once, and that's not turning out very well.

What are your favourite techniques for shoving oodles of tiles on the screen at once?
What's the best way to wrangle the monkey?

(And, before anyone says "Why don't you use X/Y/Z framework.. That's not the question. The question is method, learning, and style, not "Give up and use something else")


Why0Why(Posted 2013) [#2]
Most of what I do uses tiles. Have you looked at the code I just posted here?

http://www.monkeycoder.co.nz/Community/posts.php?topic=5078

In my experience, even with a very large number of tiles, the speed is fine, even on debug mode in html 5.

I have also been playing with fantomEngine and I asked Mike this same question about tiles. He just implemented a dynamic tilemap in the 1.51 preview. It is worth diving into the source just to look at how he works it. Our discussion about it is at the end of the long fantom thread.


Shinkiro1(Posted 2013) [#3]
Have you packed all your tiles into 1 image? Doing so avoid texture switching which might be pretty costly on some platforms.


Why0Why(Posted 2013) [#4]
My basic way is to load an image with a strip of tiles, assign an integer value to the tile in an array and then in the draw routine just use the integer to access the appropriate tile in the strip. Fast and seems to work well.


silentshark(Posted 2013) [#5]
Concur with Why0why - that seems to work fine, although there may be crafty ways to further optimise things..


Gerry Quinn(Posted 2013) [#6]
I usually put all the tiles in a 2D image and use a pair of coordinates to pick one. You can either blit directly from the appropriate rectangle on the main image, or else produce an array of images using GrabImage(). The grabbed images will still all be on the same surface.


Nobuyuki(Posted 2013) [#7]
baking small tiles into larger tile chunks to "cache" them can sometimes be useful. This is what Photoshop does when you scroll in a large document, afaik. You can do this by drawing all of the tiles you need on screen that aren't prerendered yet, plus some slack, and then using readpixels/writepixels to bake the tiles into chunks of optimal texture size (depends on platform). Then, when the user scrolls into an area where tiles haven't been baked yet, calculate out the next chunk based on your optimal tile size, generate that tile in the backbuffer, read the pixels and write it into a new texture, and blit it.

Seems like it would work nicely if there's a lot of layers and super tiny tiles and lots of texture thrash going on, your chunk size is adequately large, and WritePixels is faster on your target platform than the speed you want to scroll new chunks in at. You would, of course, need some sort of chunk manager to flag cached chunks which the user hasn't been near in a while for deletion...


zoqfotpik(Posted 2013) [#8]
Agreed about baking the backgrounds at runtime. There's no reason whatsoever not to do that. In fact, you can bake the portions of your foregrounds that are not dynamic or modifiable. There are numerous ways of doing this.


ElectricBoogaloo(Posted 2013) [#9]
Yeah, going the "Sonic - Blast Rendering" method is nice when you've got a solid renderable scene that stays more or less static, but that wasn't what I was after in this case.

I think this is going to simply be a case of "think of something else to do", because I'm not entirely sure I can wrap my head around a quick way to do it..

To put it into perspective..
If I'm coding DS Homebrew, I can have 4 layers, of 32x24 onscreen tiles, all at the same time, whilst constantly changing each and every tile, and still keep the framerate up..
.. On two screens at once!!

This is because it's all a case of memory-shifting. The layer's aren't thousands of sprites, they're just memory locations.
It constantly amazes me that, with all this processing/graphical power, something like that isn't easily do-able.

.. Except, I kinda know it is, because the DS emulators can handle it just fine, which annoys me to no end!!


Nobuyuki(Posted 2013) [#10]
Even if you can't bake large chunks in 2d for whatever reason (animation?), you can still try doing some of the caching on the Z layer to reduce the number of tiles you have to draw (provided you use many layers). If a lot of layered combinations are repeated, or the number of total tiles is small, you could sacrifice VRAM for blit speed and make a lookup table of images for each combination, possibly even generating that as an atlas at runtime and reducing the amount of texture thrash in addition to the number of total blits made.

Each situation calls for a slightly different solution, as you pointed out before yourself in the original post. There are many tools to use in the toolkit, and caching (or "blast processing", as apparently I didn't know that's what that marketing term was actually referring to) is a pretty good and versatile one.

Games on old systems often had hardware tile-based blitters to be able to achieve stuff we can do today with more general-purpose hardware. The constraints on mobile platforms are simply different than the previous generations, and require new angles or sometimes incorporating old techniques in a new way.

(I totally was going to post this yesterday morning, but went off to run some errands and forgot to hit "Post"!)


zoqfotpik(Posted 2013) [#11]
http://m.youtube.com/#/watch?v=zlulSyBI2aY&desktop_uri=%2Fwatch%3Fv%3DzlulSyBI2aY

Anyone have any good ideas for batching?

My maps are 128x128, my tiles are 48x48. I'm going to try prerendering 8x8 tile clusters.

I am not currently running into any slowdown though, but I am only going to have two layers, the foreground and background, and the BG is going to be rendered as one large texture.

Boogaloo, what exactly are you trying to do? Do you have a representative video?


Erik(Posted 2013) [#12]
If you want to draw several millions of tiles in one draw call, you could use a shader with one texture for the tilemap, and one for the tiles. (Perhaps you could even animate the map in the pixelshader with colorcycling)

Here's an example:
http://blog.tojicode.com/2012/08/more-gpu-tile-map-demos-zelda.html

It's to bad there's nothing built in right now in monkey for shaders, but you can always extend it like skn3 has done here:
http://www.monkeycoder.co.nz/Community/posts.php?topic=5285