Lunar Limit Technical: Part 2

My entry into the compo is called Lunar Limit. It’s a 80s-style arcade shooter programmed for the NES. This is part 2 of a technical write-up on the game. Part 1 can be found here.

Double Buffering

Updating one-fourth of the background per frame comes with an unfortunate tearing effect where the top half of the screen is a few frames ahead of the bottom half. This is noticeable, ugly, and worth fixing.

For Lunar Limit, a double buffering strategy was used, made possible by the NES having enough memory to hold two screens worth of background data. The game alternates the background displayed every four frames, always updating the background screen not currently visible.

ludum5.gif

Not many NES games use or would benefit from double buffering. In fact, most NES games would be worse with double buffering as it adds a frame of latency. But in the right situations, double buffering is great!

Framerate

The NES outputs video at 60 frames per second, but given that it takes 4 frames to update the background, the speed of the bullets is reduced to 15 frames per second. As one may expect, 15 FPS looks awfully jerky.

An improvement can be made by taking advantages of palettes. In the NES world, a color palette consists of 4 colors. By changing a color palette, the colors of all things using the palette will change too. Changing color palettes is a very fast operation.

The previous tileset for bullets I showed used only 2 colors. If you've forgotten, here it is again:

ludum7.png

To improve the framerate, the tileset can be modified to convey additional information using colors. Specifically, it can convey the position of bullets two frames into the future using a different color. A fourth color can be used to mark positions shared by the present and the future. That's enough colors to fully utilize the color palette.

  • Color 1 = No bullet.
  • Color 2 = Bullet exists now.
  • Color 3 = Bullet exists 2 frames into the future.
  • Color 4 = Bullet exists now and it also exists 2 frames into the future.

Applying this to the tileset results in the following:

ludum8.png

Note that adding this extra information increases the amount of tiles needed from 16 to 256. There are lots of color combinations!

Anyway, here's how rendering works:

  • On frames 1 and 2, set the color palette so that colors 2 and 4 are non-black and colors 1 and 3 are black. This displays the bullets in the present.
  • On frames 3 and 4, set the color palette so that colors 3 and 4 are non-black and colors 1 and 2 are black. This displays the bullets in the future, which is actually the present now as two frames have passed since the background was updated.

This technique effectively doubles the framerate to 30 FPS, all by combining the information of 2 frames into 1.

If that explanation did not work, just think of this as being similar to anaglyph 3d.

anaglyph.jpg

With anaglyph 3d, the color red stores information from the left eye camera, while the color blue stores information from the right. In Lunar Limit, one color stores information from frame N, while a second color stores information from a frame N+2. Changing the palette changes the information displayed.

Collisions

That's it for the rendering! Now let's talk briefly about collision checking.

To perform collision checking, an obscure feature of the NES's graphical hardware can be used. During rendering, the NES always checks whether the first sprite in memory, "sprite 0", overlaps with the background layer. A status bit is set based on the result. This makes collision checks trivial in Lunar Limit; all that needs to be done is a check of the status bit!

It may seem at first that this feature is extremely useful and applicable to many games, but oddly enough that isn't true. Out of the NES's entire 700+ game library, I haven't heard of a single game to use this feature for its collision checks. The reason is because only a single 8x8 sprite can be checked per frame, and most games use larger characters made up of several 8x8 sprites. Also, while this feature makes it possible to detect whether a sprite overlaps with the background, it's not possible to determine what the sprite overlaps with. It's impossible to discern colliding with a cloud with colliding with a spike, for example, and that makes it useless for most games.

Interestingly, a great many of games use this feature for another use: screen splits, but I won't get into that.

Conclusion

Anyway, that's about it.

Using these techniques, it's possible to display around 100 objects on the screen without slowdown and without flicker. A bit more than the 20 to 40 most NES games cap out at.

And hey! Now when you play my game you'll have an answer to "Why are the bullets so pixilated and jittery?" The answer is because a lot of thought went into making them look that pixilated and jittery. In actuality they could look much worse! Hah.

Cheers, (and good luck!)

- Pubby