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 > [solved] help needed on animating a background

#21939 - tornadokick - Wed Jun 09, 2004 10:04 pm

Code:
void AnimateBG(Bg *bg)   // swaps out the tiles to create animation to simulate the waves of water.
{
   u16 loop;
   u16* temp = (u16*)frogmap; 
   for(loop = 0; loop < 64*64 ; loop++)
   {
      if (bg->mapData[loop] == 0x00)         // if it's one wave pattern, switch
         bg->mapData[loop] = 0x01;
      else if (bg->mapData[loop] == 0x01)    // if it's the other, switch
         bg->mapData[loop] = 0x00;
   }
}


Ok, this should be a somewhat basic approach to swapping out the tiles to create the illusion of motion in a background. It works, but the only every other tile is being changed. The remaining (every other) tiles stay static. To illustrate:
101010101010...
101010101010...
101010101010...
101010101010...
...
1's would signify the tiles that change, and 0's would stay the same. I know essentially why the tiles aren't changing (the loop is just looking at every other tile), but I don't know how to fix it.

Once again. Any help is appreciated.


Last edited by tornadokick on Thu Jun 10, 2004 1:58 am; edited 1 time in total

#21943 - Abscissa - Wed Jun 09, 2004 11:05 pm

I don't know how experienced you are, so forgive me if you already know most of this:

The problem is that the map data is 8-bits per tile, but you are accessing it as if it were 16-bits per tile. Let's say the first 8 bytes in map memory looked like this:

00 00 00 00 00 00 00 00

When you use 16-bit integers (ie u16 for data and u16* for pointers), then this memory gets treated as four 16-bit numbers, instead of eight 8-bit numbers. It's treated like this:

0000 0000 0000 0000

So, if you change the first three of these to 1, it goes and changes the first three numbers to one:

0001 0001 0001 0000 (Ignoring endian-ness)

So you get every other byte updated. If you change everything to u8 and u8*, then it correctly looks at the memory as:

00 00 00 00 00 00 00 00

And setting the first three to 1 will have the intended result:

01 01 01 00 00 00 00 00

So, in short (no pun intended), use u8 instead of u16. But, there might still be a problem with even that. I know that there are parts of the GBA that you can only access two-bytes at a time (like the memory for the background in modes 3, 4 and 5), but I don't know whether or not that also applies to the map memory. If it does require two-bytes at a time(and you can tell just by seeing if u8 fixes everything or not), then you'll have to stick with u16 and do someting else instead:

Probably the easiest way would be like this:

Code:

// Everything is still u16
for(loop = 0; loop < 64*64/2 ; loop++)
   {
      if (bg->mapData[loop] == 0x0000)
         bg->mapData[loop] = 0x0101;
      else if (bg->mapData[loop] == 0x0101)
         bg->mapData[loop] = 0x0000;
   }


That way, you're updating both bytes with 0x01 instead of just one. By contrast, what your original code was essentially doing is this:

Code:

for(loop = 0; loop < 64*64 ; loop++)
   {
      if (bg->mapData[loop] == 0x0000)
         bg->mapData[loop] = 0x0001; // Sets first tile to 0x00 and second to 0x01
      else if (bg->mapData[loop] == 0x0001)
         bg->mapData[loop] = 0x0000;
   }
// Note that this loop changes 64*64*2 tiles, not 64*64 tiles, since we're using u16*


Last edited by Abscissa on Wed Jun 09, 2004 11:09 pm; edited 1 time in total

#21944 - sajiimori - Wed Jun 09, 2004 11:08 pm

Just so I'm clear, the 'temp' and 'frogmap' variables aren't supposed to be used in this function, right?

Is it a rot/scale or text bg? If it's rot/scale and mapData is a u16*, you're setting 2 tiles at once.

#21945 - sajiimori - Wed Jun 09, 2004 11:11 pm

Careful, Abscissa's solution only works if water tiles always come in pairs.

#21946 - Abscissa - Wed Jun 09, 2004 11:14 pm

sajiimori wrote:
Careful, Abscissa's solution only works if water tiles always come in pairs.


Yes, sorry, I forgot to mention that. If they don't always come in pairs, you'll have to use some bitmasking to prevent changes to non-water tiles, which takes a little bit more effort.

#21947 - tornadokick - Thu Jun 10, 2004 12:07 am

sajiimori wrote:
Just so I'm clear, the 'temp' and 'frogmap' variables aren't supposed to be used in this function, right?

Is it a rot/scale or text bg? If it's rot/scale and mapData is a u16*, you're setting 2 tiles at once.


Yeah, I edited after I created the post to remove those. They aren't needed.

Abscissa wrote:
Code:

// Everything is still u16
for(loop = 0; loop < 64*64/2 ; loop++)
   {
      if (bg->mapData[loop] == 0x0000)
         bg->mapData[loop] = 0x0101;
      else if (bg->mapData[loop] == 0x0101)
         bg->mapData[loop] = 0x0000;
   }



yeah, I knew about it (referring to the post, about reading in the variables which are 2 8-bit vars), but I didn't know how to deal with it. Thank you so much for this explanation.

I need to know about bit masking so if someone would care to explain that to me, thank you.

#21949 - sajiimori - Thu Jun 10, 2004 12:37 am

Use the bitwise-and operator (&) to clear bits, and bitwise-or operator (|) to set bits, the bitwise-xor operator (^) to toggle bits, and the ones-complement operator (~) to flip all the bits in a value.

If you're using Windows, it comes with a calculator which has bitwise operators in scientific mode. You can experiment there. Anyway, get a good C book for more details.

#21952 - poslundc - Thu Jun 10, 2004 12:47 am

Also: learn hexadecimal.

Dan.

#21958 - tornadokick - Thu Jun 10, 2004 1:49 am

sajiimori wrote:
Use the bitwise-and operator (&) to clear bits, and bitwise-or operator (|) to set bits, the bitwise-xor operator (^) to toggle bits, and the ones-complement operator (~) to flip all the bits in a value.

If you're using Windows, it comes with a calculator which has bitwise operators in scientific mode. You can experiment there. Anyway, get a good C book for more details.


OK, thanx. I knew you could view binary and hex as part of the calculator, but I didn't see all of those useful functions. Thanks for drawing my attention to them.

This is a very helpful post, it answers a lot of my questions. Thanks once again. (Am I being too humble?)

poslundc wrote:
Also: learn hexadecimal.

Dan.


I'm sorry, I am already familiar with hexadecimal, just not how to use it.

#21963 - poslundc - Thu Jun 10, 2004 4:13 am

tornadokick wrote:
I'm sorry, I am already familiar with hexadecimal, just not how to use it.


You just prefix the number you want to specify with "0x" (that's a zero). So 127 can be written in hex in C as 0x7F, for example.

You will find that hexadecimal comes into its own when you are doing bit-manipulation, because it gives you a notation that makes it very easy to visually identify which bits are on and which are off. Plus, everyone else uses it heavily, so it's essential when reading other people's code as well.

Dan.