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 > Transparent backgrounds above sprites

#33894 - ymalik - Mon Jan 10, 2005 10:10 pm

In the following code I have a star background and on top of it I have a transparent cloud background. The star background (background 0) is composed of 4 8x8 8 bit tiles randomly placed. The cloud background (background 1) is a 240x256 8 bit image. In between I want to have a sprite that is above the star background but you can see through it through the cloud background. The sprite is a 32x32 8 bit image. I can only seem to make the sprite either above the star background or transparent below the clouds, but not both, and the black area around the sprite shows through the clouds. Also, the cloud image seems to be torn into two pieces down the middle vertically and stretched. How can I accomplish all of this?

Thanks,
Yasir

Code:

int main(void)
{
   int i;
   Sprite sprite;
   s16 stars_x = 0, clouds_x = 0, ship_x = 104, ship_y = 126;
   SetMode(MODE_0 | BG0_ENABLE | BG1_ENABLE | OBJ_ENABLE | OBJ_MAP_1D);

   // star background
   DMA_Copy(3, (void *) palette_Palette, BGPaletteMem, 256, DMA_16NOW);
   DMA_Copy(3, (void *) stars_Tiles, (void *) CharBaseBlock(0), 256, DMA_16NOW);
   generate_stars();

   // clouds
   DMA_Copy(3, (void *) clouds_Tiles, (void *) CharBaseBlock(1), 12224/2, DMA_16NOW);
   DMA_Copy(3, (void *) clouds_Map, (void *) ScreenBaseBlock(30), 960, DMA_16NOW);

   // ship
   DMA_Copy(3, (void *) palette, (void *) OBJPaletteMem, 256, DMA_16NOW);
   DMA_Copy(3, (void *) obj0, (void *) OBJ_GFXMem, 512, DMA_16NOW);

   sprite.attribute0 = COLOR_256 | ship_y | SQUARE;
   sprite.attribute1 = SIZE_32 | ship_x;
   sprite.attribute2 = 0 | BIT(10);

   //       where to look for tiles                                  where to look for map
   REG_BG0CNT = 0 << CHAR_SHIFT | BG_COLOR_256 | TEXTBG_SIZE_256x256 | 31 << SCREEN_SHIFT | 0;
   REG_BG1CNT = 1 << CHAR_SHIFT | BG_COLOR_256 | TEXTBG_SIZE_256x256 | 30 << SCREEN_SHIFT | 1;
   REG_BLDMOD = BIT(0) | BIT(9) | BIT(6) | BIT(12);

   while(1)
   {
      process_buttons(&ship_x);

      stars_x++;
      clouds_x--;

      sprite.attribute1 = SIZE_32 | ship_x;

      wait_vblank();
      OAMMem[0] = sprite.attribute0;
      OAMMem[1] = sprite.attribute1;
      OAMMem[2] = sprite.attribute2;
      REG_BG0VOFS = stars_x >> 4;
      REG_BG1VOFS = clouds_x >> 2;
   }

   return 0;
}

#33941 - Cearn - Tue Jan 11, 2005 12:33 pm

ymalik wrote:

REG_BG0CNT = 0 << CHAR_SHIFT | BG_COLOR_256 | TEXTBG_SIZE_256x256 | 31 << SCREEN_SHIFT | 0;
REG_BG1CNT = 1 << CHAR_SHIFT | BG_COLOR_256 | TEXTBG_SIZE_256x256 | 30 << SCREEN_SHIFT | 1;

ymalik wrote:
In the following code I have a star background and on top of it I have a transparent cloud background. The star background (background 0) is composed of 4 8x8 8 bit tiles randomly placed. The cloud background (background 1) is a 240x256 8 bit image

Errr, bg0 (stars) has priority 0, bg1 (clouds) has priority 1, that means that the stars are in front of the clouds, not behind. Higher priority means higher drawing priority, i.e, draw first & painted over by the other backgrounds.
To make the clouds be over the stars, the stars-bg should have priority 1, and clouds-bg priority 0 (or switch the backgrounds themselves). You will probably have to alter REG_BLDMOD as wel to account for the change.

As for the black area around the sprite, are you sure it uses color index 0?

#33957 - ymalik - Tue Jan 11, 2005 5:18 pm

Thanks, Cearn.
I have the following now:
Code:

   REG_BG0CNT = 0 << CHAR_SHIFT | BG_COLOR_256 | TEXTBG_SIZE_256x256 | 31 << SCREEN_SHIFT | 3;
   REG_BG1CNT = 1 << CHAR_SHIFT | BG_COLOR_256 | TEXTBG_SIZE_256x256 | 30 << SCREEN_SHIFT | 0;
   REG_BLDMOD = BIT(0) | BIT(11) | BIT(4);

I gave the ship priority 2 in attribute2. The clouds are above the stars and ship, but I cannot see the ship or stars through the clouds.
I used gifs2sprites to create the header files for my sprites, and this is the palette that it creates:

Code:

const unsigned short palette[7]=
{
RGB( 0, 0, 0),RGB( 0, 0, 0),RGB( 0, 0,31),RGB(31,31, 0),RGB(24,24,24),
RGB( 0,31, 0),RGB(31, 0, 0)
};


and here's part of the ship array:
Code:

/* ship.gif (32x32x16) */
const unsigned short obj1[256]={
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x1111,
0x1111,   0x2111,
0x1111,   0x2111,
0x1111,   0x2211,
...


So I had to do a find a replace on all 1's with 0's to make the black transparent.

Much thanks,
Yasir

#33962 - Cearn - Tue Jan 11, 2005 6:24 pm

ymalik wrote:
I gave the ship priority 2 in attribute2. The clouds are above the stars and ship, but I cannot see the ship or stars through the clouds.

That's what the transparency is for, isn't it? I have a feeling you might need to read up on that a little bit. (So should I probably, it's been a while). One, euhm, 'interesting' thing about REG_BLDMOD is that lower byte is for the front layers (A) and the upper-byte for the back-layers (B). If you reverse it, it won't work. And there's more to blending than just REG_BLDMOD:
Code:

REG_BLDMOD =
     BIT(1)     // front, bg1 (the clouds)
   | BIT(6)     // you must switch blending ON before anything can happen
   | BIT(8)     // back, bg0 (stars)
   | BIT(12)    // sprites in back too

// and then the weights in REG_COLEV
REG_COLEV =
     (4<<8)      // set front to 1/4 strength
   | (12<8)      // set back to 3/4 strength

// and you probably need to switch on transparency for the sprite too
// but I'm not 100% sure here
sprite.attribute0 |= BIT(10)

That should do it.