Parallax Scrolling

Another popular effect in old games was to make the background scroll at different speeds to give the illusion of depth. Many shoot-em-up games had a slowly scrolling background to give the impression the player was flying somewhere. Platform games had backgrounds that gave the same effect and a foreground that scrolled faster.

Doing this is a bit more complex than merely drawing on the borders. The difficult part is that the screen scroll registers require us to tell them how much to scroll the screen by. They’re not counters to be incremented or decremented. Instead it’s up to our code to keep a count of where the screen should be scrolled to all the time.

Except there are no copper commands to do maths, store variables or read data. The copper can only write specific bytes to Next registers. The page on updating the copper explains two ways to do this, and how to choose between the two methods.

Moving parts of the screen requires it to be organised appropriately. The Next doesn’t have overlapping layers, so you are literally cutting the screen up and sliding those parts. It’s not possible to have a cloud that moves over the top of something static using this method.

This is a short program that will work for scrolling the screen at vertical positions 0, 60 and 160

uint16_t parallaxScroll[] = {
    CU_WAIT(0,48),
    CU_MOVE(REG_LAYER_2_OFFSET_X, 0),
    CU_WAIT(60,0),
    CU_MOVE(REG_LAYER_2_OFFSET_X, 0),
    CU_WAIT(160,48),
    CU_MOVE(REG_LAYER_2_OFFSET_X, 0),

    CU_WAIT(400,0)
};

By itself however this will do nothing. At those three locations we are scrolling the screen zero pixels horizontally.

However, if we have a piece of code in our main loop that does this:

// Variables to keep track of the scroll positions
uint8_t scrollClouds = 0;
uint8_t scrollMountains = 0;
uint8_t scrollGround = 0;
uint8_t frameCounter = 10;

// Update the code in the copper list
parallaxScroll[1] = CU_MOVE(REG_LAYER_2_OFFSET_X,scrollClouds);
parallaxScroll[3] = CU_MOVE(REG_LAYER_2_OFFSET_X,scrollMountains);
parallaxScroll[5] = CU_MOVE(REG_LAYER_2_OFFSET_X,scrollGround);

// Increment the scroll positions accordingly
if (--frameCounter == 0) {  // The copper is quite quick and your code needs slowing down!
    scrollClouds++;
    scrollMountains += 2;
    scrollGround += 3;
    frameCounter = 10;
}

We can now start to reprogram the copper while it is running. Depending on the length and complexity of the copper’s code, use either the method to reupload the whole copper list, or selectively upload parts of it. See the page on updating for more information.