# 2d very large tile based game, zoom and pan considerations

what's a sensible way of implementing zoom and panning for my game?

each tile is very large, 100,000 x 100,000 pixels, with some objects possibly being only a single pixel at maximum zoom (small objects in a vast vast space).

I want to be able to zoom out so the view encompasses the entire chunk/tile, possibly two chunks if objects are near the border, I also want to replace the image used for the objects with an icon past a certain level of zoom.

I'd like to have this drawn on a jpanel in an applet with a swing based ui. graphically I was aiming to keep it simple and just use graphics2d functions. should I be looking at using LWJGL or is this overkill.

I realise these sorts of questions get asked a lot, but I'm concerned there are special considerations for having such large tiles.

Thanks

• Are you saying each TILE is 100kx100k or the whole map is that large? – Richard Marskell - Drackir Sep 21 '11 at 12:24
• each tile 100kx100k, mostly empty but large, looking at having a total play area of several hundred tiles, mostly not loaded, whether the tiles need to be that large I'm unsure but total play area in the region of 10^9 pixels. though display area will only be 800x600. – BetaScoo8 Sep 21 '11 at 12:54
• @BetaScoo: Please redo your math or your terminology. If the total play area is 1e10 and each tile is 1e5 x 1e5 = 1e10, then the entire play area is one tile, and it's no longer a "tile" in any meaningful sense. Also, if each tile is actually 1e10 pixels, I hope you have some excellent (= magical, nonexistent) texture compression. – user744 Sep 21 '11 at 13:36
• +1 for magical texture compression, seriously if you can turn textures that size into accessable small data, fax me google maps okay? – Adrian Seeley Sep 21 '11 at 14:01
• tile isn't perhaps the correct word, lets say grid, and yes, sorry, order of magnitude wrong (can't update comments more frequently than 5min and then I had to "work". total play area is ~1e13 times the smallest unit (1 pixel), also there are no textures except for the small objects. – BetaScoo8 Sep 21 '11 at 14:06

Tiles are a way to stretch large or repeatable data from a massive file onto a display. The only reason to use tiles is to increase that efficiency.

Solution A:

Make your original tiles far smaller, and use a simple tile only to outside screen boundaries system. Although I have a fairly good idea what you're trying to do, and this won't work.

Solution B:

Every X interpolation. Let's assume we have enough memory to store 4 notice I didn't say 2, when the user is in a corner of one tile, you will need to render 4 tiles. (1) the tile the user is in then the (3) possible tiles that could be moved to in one screen.

Now let's pretend we are maximum possible zoom on one tile, we are so close that one pixel on the tile = one pixel on the screen.

int ScreenPositionX = -1;
int ScreenPositionY = -1;
for(int X = TopLeftPixel.X; X < BottomRightPixel.X; X++)
{
ScreenPositionX++;

for(int Y = TopLeftPixel.Y; Y < BottomRightPixel.Y; Y++)
{
ScreenPositionY++;
PutPixelOnScreen[ScreenPositionX, ScreenPositionY] = GetPixelFromMemory[X, Y]
}
}


So we keep track of which pixel we are putting on screen (blitting) and the location we are at in the texture. We start the for loops at the top left pixel of the texture to be drawn, and we iterate through to the last (bottomright) pixel of the texture to be drawn.

But once the user zooms out to a ratio of say 10 pixels on the tile = 1 pixel on the screen, we need to handle what should and shouldn't be drawn. The easiest method is to simply skip pixels: (assuming you can find the topLeft and bottomRight * scale pixels)

int ScreenPositionX = -1;
int ScreenPositionY = -1;
int SkipTen = 10;        //This is our scale value, 10 on texture = 1 on screen
for(int X = TopLeftPixel.X; X < BottomRightPixel.X; X += SkipTen)
{
ScreenPositionX++;
for(int Y = TopLeftPixel.Y; Y < BottomRightPixel.Y; Y += SkipTen)
{
ScreenPositionY++;
PutPixelOnScreen[ScreenPositionX, ScreenPositionY] = GetPixelFromMemory[X, Y]
}
}


That's the simplest way, and has little overhead. You complicate things more if some pixels should be represented always over others. Say in a 10 pixel space you have one black pixel, the rest white. You could choose of the 10 pixels which has the highest count and represent the pixel as that color, but then we lose our black pixel. So we can instead check if there is a black pixel in those 10, to always draw black. You can complicate things more by converting this into a symbol on screen after a certain zoom ratio has been reached. Keep in mind this kind of a realtime system starts to slow down quite quickly if you throw in averaging, weighted systems for every pixel to be drawn. Ideally the textures should be prerendered to depth, or if this is a gargantuan system like google maps, you could render on demand and save renders.

Also sorry this isn't in java, it's not my language, but the concepts are all there. I can clear up anything just comment questions.

You could use the same algorithm as the one used by Google Maps or Giga pixel, ie : have different resolution of your image, and only load the image corresponding at both your position and zoom level.

so for example when you're at maximum zoom, you display a detailed 512x512 image, and whent you zoom out, blend with another 512x512 image with a different view.

• I'll investigate this, but I wonder how this would work with animating the objects (probably should have made that more clear in the question) would I need to draw the objects to a particular bufferimage for each zoom level? seams a bit wasteful of resources or am I missing something? – BetaScoo8 Sep 21 '11 at 13:14
• No you just need to draw the object corresponding at the current zoom level. When animating the zoom, fade in/out the image while changing the zoom – XGouchet Sep 21 '11 at 13:27