Parallax scrolling gives a 2D game a greater sense of depth and immersion by creating the illusion of a third dimension. There are three main methods of parallax scrolling on video game console systems.

The layer way

If your display system supports multiple background layers, you can scroll them by simply changing each layer's horizontal offset by a different amount. However, you don't want to place too much in front of the layer containing the objects with which the player interacts; otherwise, you'll obscure the action, which is annoying, and annoying games don't sell.

Most of the time, in a side-scrolling platform game, you apply parallax only to the x dimension. This gives the illusion that the camera is panning up and down while dollying sideways. In an overhead-view game, apply parallax equally to both dimensions.

pseudocode

This pseudocode assumes a display system with three layers (such as that of the Super NES), numbered 0 to 2, and a library function set_scroll() that takes a pair of pixel coordinates, pokes the proper values into the display and (if necessary) rewrites the tiles at the edges of the scroll area. layer_depth[] is an array containing the distance of each layer from the camera. The layer_depth of the player's layer is defined as 256. camera_x and camera_y are what you'd expect, variables that follow the hero(ine).
external function set_scroll(size_t layer_idx, int x_off, int y_off);

for layer from 0 to 2:
  set_scroll(layer, camera_x * 256 / layer_depth[layer], camera_y);
Use of a fixed-point variable to store camera_x provides a smoother scroll when the hero(ine) is moving slowly.

The raster way

To parallax-scroll within one layer (necessary on classic 8-bit systems such as Nintendo Entertainment System and the original Game Boy), divide the layer into sub-layers and change the layer's horizontal scroll value just before the display system begins to draw each scanline. This shifts the entire scanline and thus lets you scroll parts of a layer at different rates. For example, scroll the scanlines at the top of the screen (clouds) slowly, the middle of the screen (playfield) at normal speed, and keep the bottom of the screen (status bar) fixed.

In general, poking at the hardware before each scanline is called a raster effect. It's also useful for changing the system palette to provide a gradient background. Some platforms (Super NES, Sega Genesis, Game Boy Advance) provide horizontal-blank raster interrupts or DMA mechanisms for automatically setting the registers at the right times; others, such as the NES and Game Boy, require the use of cycle-timed code, where the main loop takes exactly as long as a display cycle. Many NES games such as the classic Super Mario Brothers use this technique to draw their status bars, and Teenage Mutant Ninja Turtles II: The Arcade Game and Vice: Project Doom for NES use it to scroll background layers at different rates.

More advanced raster techniques can produce interesting effects. You can achieve breathtaking depth of field if you combine layers with rasters; Sonic the Hedgehog 2, ActRaiser, and Street Fighter II used this effect well. If you make each scanline its own sub-layer, you get the Pole Position effect, which creates a pseudo-3D road (or in NBA Jam's case, a pseudo-3D ball court) on a 2D system. If your display system supports rotation and scaling in addition to scrolling, changing the rotation and scaling factors can draw a projection of a plane (F-Zero, Super Mario Kart) or can warp the image to create an extra challenge factor (Tetanus On Drugs). Source code for this "Mode 7" technique is available at www.pineight.com and www.gbadev.org.

The sprite way

If you have a lot of sprites (individually controllable moving objects drawn by hardware on top of or behind the layers) available on your display system, you may want to make a pseudo-layer out of sprites. Star Force, an overhead-view vertically-scrolling shooter for for NES, used this for its starfield, and Final Fight for Super NES used this technique for the layer immediately in front of the main playfield. But watch out for sprite flicker; you'll want to heed these tips for preventing sprite flicker on old consoles.

To implement this, treat each sprite as a layer, as described above. If you have several sprites at the same depth, you may be able to arrange your data structures in such a way as to minimize the time spent in slow divisions.

©

Copyright © 2002 Damian Yerrick.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the writeup entitled "GNU Free Documentation License".