gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > parallax scrolling in mode0, text bg 0

#20346 - tethered - Sat May 08, 2004 5:29 pm

hello,

first of all, since this is my first post on this forum, i'd like to take a moment and introduce myself... my name is chuck, i'm an intermediate-level c programmer, and I have recently gotten sucked into developing for the gba console (its deceptively simple!). i've been lurking around and have collected a lot of information and advice from you guys already, but i've hit a slight road block...

i'm working on creating a multi-layered background in mode 0, text bg 0, but i'm having trouble finding any clearly written documentation on how to do so. at this point, with a single layer, my code looks like this:

Code:
u16* ScreenBB = (u16*)ScreenBaseBlock(8);
u16* CharBB = (u16*) CharBaseBlock(0);

// set video mode
SetMode(MODE_0 | BG0_ENABLE);

// set bg control register
REG_BG0CNT = BG_COLOR_256 | TEXTBG_SIZE_256x256 | (8 << SCREEN_SHIFT) | (0 << CHAR_SHIFT);

// load palette data
for (i = 0; i < 256; i++)
    BG_PaletteMem[i] = stars_Palette[i];
       
// load map data
for (i = 0; i < 1024; i++)
    ScreenBB[i] = stars_Map[i];
       
// load tile data
for (i = 0; i < 128 / 2; i++)
    CharBB[i] = (stars_Tiles[i*2+1] << 8) + stars_Tiles[i*2];

// game loop
while (1)
{
    // 1. detect key presses and change x and y coords accordingly
    // 2. wait for vdraw
    // 3. update bg's x and y registers
}


clearly its not the most efficient way to go about it, but for the time being, as i'm slowly getting comfortable with the console, clarity is more important than optimization.

so, with that said, working within the constructs of my software loop, how would i go about adding multiple layers of parallax scrolling? i understand there's 2 bits for the background priority in the background control register, but i'm not sure how to use it in a practical sense.

any help would be greatly appreciated.

thanks in advance,


chuck

#20347 - abilyk - Sat May 08, 2004 5:59 pm

You're certainly on the right track, you just need to extend what you've already got.

Enable more background layers. Mode 0 lets you use a maximum of 4 layers.
Code:
// set video mode
SetMode(MODE_0 | BG0_ENABLE | BG1_ENABLE | BG2_ENABLE | BG3_ENABLE);


Initialize each background layer. They can all share the same tileset (char base block) if you like. The hardware would allow you to let them all share the same map (screen base block) as well, but since that's not your intent, you should have a separate map for each background.
Code:
// set bg control register
REG_BG0CNT = BG_COLOR_256 | TEXTBG_SIZE_256x256 | (8 << SCREEN_SHIFT) | (0 << CHAR_SHIFT);
REG_BG1CNT = BG_COLOR_256 | TEXTBG_SIZE_256x256 | (9 << SCREEN_SHIFT) | (0 << CHAR_SHIFT);
REG_BG2CNT = BG_COLOR_256 | TEXTBG_SIZE_256x256 | (10 << SCREEN_SHIFT) | (0 << CHAR_SHIFT);
REG_BG3CNT = BG_COLOR_256 | TEXTBG_SIZE_256x256 | (11 << SCREEN_SHIFT) | (0 << CHAR_SHIFT);


For each layer you use, make sure you load its map data into the corresponding section of VRAM. Regarding background priorities, if you don't manually change the priority for the layers, they'll all have a default priority of 0. When layers are set to the same priority, lower-numbered layers are drawn above higher-numbered layers. So, if you don't manually change any priorities, layer 0 will be drawn above layer 1, which will be drawn above layer 2, etc.

For parallax scrolling purposes, you'd want to have your farthest background (layer 3 in this case) a solid image, and all closer backgrounds transparent in places, so you can see through to what's behind. Note that if your farthest background is transparent in any places, the backdrop (bg palette color 0) will show through.

Finally, in your game loop, you'll want to change the x and y coords for all layers. If you change them all at the same rate (like 1 pixel per key press), they'll all scroll at the same rate as well, which isn't what you want. Instead, you should increment/decrement each layer's coords at a different rate. Make sure you update the hardware registers for all layers.
Code:
// game loop
while (1)
{
    // 1. detect key presses and change each bg's x and y coords accordingly
    // 2. wait for vdraw
    // 3. update each bg's x and y registers
}

#20348 - sajiimori - Sat May 08, 2004 5:59 pm

The 4 backgrounds have a default draw order of 3-2-1-0, so you could go with that if you have no reason to do otherwise. Just enable another background, load it with appropriate data as you have done for bg0, and scroll it at a different rate. It's really as simple as that.

Oh, and here:
Code:

CharBB[i] = (stars_Tiles[i*2+1] << 8) + stars_Tiles[i*2];

You could just do this:
Code:

CharBB[i] = ((u16*) stars_Tiles)[i];

Better yet, define stars_Tiles as a u16 array in the first place.

#20350 - tethered - Sat May 08, 2004 6:25 pm

Thanks for your advice, guys. That clears things up quite a bit. However, I have one question regarding transparency...

Quote:
For parallax scrolling purposes, you'd want to have your farthest background (layer 3 in this case) a solid image, and all closer backgrounds transparent in places, so you can see through to what's behind. Note that if your farthest background is transparent in any places, the backdrop (bg palette color 0) will show through.


I read somewhere that the first palette entry is used as the mask color. When drawing a background layer from a bitmap (in this case, a byte array), does anything need to be done to render a pixel transparent or will it automatically be rendered transparent if it references the first palette entry?

Thanks,


Chuck

#20351 - abilyk - Sat May 08, 2004 6:38 pm

tethered wrote:
When drawing a background layer from a bitmap (in this case, a byte array), does anything need to be done to render a pixel transparent or will it automatically be rendered transparent if it references the first palette entry?


It's automatic. Whether you're referencing a 256-color or 16-color palette, palette entry 0 will always be drawn as transparent. The only exception to this is when you can see past all layers to the backdrop, which is solid color 0.

#20352 - tethered - Sat May 08, 2004 6:43 pm

Thanks, abilyk. This gives me a fun Saturday afternoon project. Maybe later I'll post a demo along with my full source as my way of giving back to the community. ;)