Well, I’ve been away a while and haven’t been able to do as much with “Caravan” as I’d have liked. But I have started the work on some features, which you can see below.
First off, I’m getting closer to the cartographic look I want. Colour makes a huge difference and compared to my fractal terrain generation (which needs a lot of work, too … it doesn’t generate terrain with enough unique-ness yet) the processing doesn’t take too long. But it is a shame it can’t be hardware accelerated, as the blendmodes I use (like the LightingColorFilter, PorterDuffXfermode and ColorMatrixColorFilter) aren’t yet supported.
Still, it surprised me how fast you can process 10×10=100 tiles that way if you do it correctly.
One trick has to do with looping and bitmap pixels. It’s always faster to operate on a sinbgle dimensional array of pixeldata, an int[x times y] (or byte[x times y] or whatever) than on a two dimensional array of int[x][y].
So much so that it’s actually worth it to loop over your int[x][y] to fill a (previously created and re-used) int(x-times-y], and operate on that. And then use that to either fill an int[x][y] or use the int[xy] to fill a bitmap.
But be carefull: always loop first over the x and then the y. The fastest way to do this is to have the y in the outer loop and the x in the inner loop:
for (y=0 …)
for (x=0 …)
Anyway, I have done a lot of optimisation on the backend, too, as well as completely re-written the tilehandler and caching.
One really interesting thing I came across was when I tried to speed up my rendering mechanism when scrolling.
Instead of re-drawing all the tiles which where onscreen (even if they were cached), I wanted to use the picture which was on my canvas already, shift it by a tile and only draw the new line of tiles which had appeared. Kind of like:
bufferCanvas.draw(bufferCanvasBMP, posx+offset, posy+offset)
bufferCanvas.draw(either horizontal or vertical strip of new tiles to the left/right/top/bottom)
Which worked perfectly. If I was scrolling my map down or to the left. But as soon as I scrolled to the right or up, I got major corruption. Which turned out to be because in Android, drawing the canvas bitmap over itself doesn’t check to see which direction it is offsetting itself but always gets it’s data from the top/left and re-writes itself at the same time.
So scrolling and re-writing to the bitmap itself works if you’re replacing the pixel data from the left/top with the data from a bit to the right. But do that the otherway around and you’re trying to over write data with data which is already re-written!
Turns out, many implementations of such a bitmap copy-to-itself do a check to see in which direction you’re doing the offset. But Android doesn’t.
The solution to all this is to use the fast copy-canvas-bitmap-to-itself method if you’re scolling to the right or down, but to do a (slower) copy-canvas-to-another-canvas-then-copy-that-canvasbitmap-to-the-first when you’re scrolling/offsetting to the left or up.
As you can see, I’ve also done some work on river generation, but that deserves a post on it’s own. Especially since this map is per-pixel and fractal, making things difficult for me 🙂
And I’ve done some work on rendering points-of-interest on the map, like cities/huts/whatever. Because they’ll be changing during the course of the game (cities grow, resources/treasures get picked up), they need a seperate render pass and it would be handy if they only get rendered when they’re on the screen.
Turns out you run into an interesting problem depending on how you scroll over the border of your map (when you go from til 9 to tile 0 or from tile 0 to tile 9): it totally borks up your tests to see if the absolute world location of the point is within the tiles being drawn on screen!
So you need different parameters to test against (different if statements) when you cross over the ends of your tile-array, depending on your scrolling direction! This surprised the heck out of me 🙂