Sunday, March 8, 2015

Wrapping Worlds

In the classic game Pac-Man, there is a tunnel in the middle of the level, when you go in on one side, you emerge on the other side of the screen. It plays an important part in gameplay, as you can use it to evade the fast red ghost.
In the classic Defender, if you fly your spaceship far enough to the right (or left, as you can go both ways), space will wrap around and you will eventually return to the same point. The game world of Defender is cylindrical.

You will find this technique of wrapping worlds a lot in classic 2D games. It doesn't work well for 3D games, because of their level of realism and immersiveness, it feels weird if a 3D world wraps. [The irony is that the real world does seem to wrap around, as observed by a traveller on the ground]On the other hand, I always I feel weird when reaching the edge of the obviously square world in 3D games.
Anyway, wrapping worlds are a lot of fun for 2D retro style games, and I couldn't find much information on the net how to go about and implement such a thing. So I devised a couple of methods and wrote them down here.

1. The straightforward way
Wrapping is simply achieved by using the modulo operator. If the player moves off the map, her new position is mod the world width. Consequently, when a player moves off the map on the right, she re-emerges on the left. That was easy.
But not so fast. A monster chasing the player will effectively see the player being teleported from the right side of the map, to the far left side of the map. The monster will now change direction, and has to travel all the way across the map in order to get near the player again. So to fix this, you might set a flag that a monster is not allowed to turn if ... But there is more. A similar problem exists for monsters that live in the left side of the map. They will not see that the player is actually close nearby, until the player is teleported in over the right edge of the map. By now it's becoming clear that wrapping is not as easy as it looks.

2. Overscan areas
Rather than having the map just be the map, allow the player (and everything else) to exist in a boundary outside the world. The boundary area is like an overscan area.
This region is a copy of the other side of the world. Once the player ventures too far, teleport everything in the overscan area to the other side.
The overscan area should at least be a screen wide to work properly. Maps should also be at least two screens wide. This method is relatively costly on memory because it duplicates large parts of the map.

3. Far offset
The previous method still has a problem with the direction of monsters that are outside the screen.
A way to solve this is to have the game take place at a far offset. The problem with wrapping is partly because we're too close to zero. By translating the origin to, say, 100,000, we're largely preventing the problem of monsters heading the wrong way. It's mostly a band-aid though as the situation still does exist. Eventually the player may reach the zero line, at which everything needs to be rebased at the far offset again. It is unlikely that any player will venture so far that she wrapped around the world a dozen times, but nevertheless possible.

4. Sliding window
Let the area around the player be a sliding window that glides over the map. The area should at least be what's visible on screen, but may be larger to allow off-screen monsters to come in and attack.
The sliding window uses ‘stripping’ to phase in and phase out relevant parts of the map. For example, as the window slides to the right, a vertical strip slides into the window on the right, and a vertical strip slides out of view on the left. This works particularly well for tiled maps. Monsters can be frozen into the tile map, and come to life as soon as they come into view. The coordinates of alive objects are relative to the sliding window (they are no longer in ‘map’ space) and therefore there is no directional problem when the world wraps.

I implemented each of these and they all work. What seems to me the best method however is the sliding window technique. Even for games that are not tile based at all, you may want to consider adding a tile grid anyway. The sliding window technique makes a clear distinction between objects that are alive, and objects that are not worth spending time on. You can enjoy a massive world with millions of objects without breaking a sweat. And what's fun, the world wraps.