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.

Coding > Clear Screen Special Effects

#3221 - Vortex - Thu Feb 20, 2003 5:12 pm

Hello

I have spend some time searching for information how to implement the cool screen clearing effects used in most of the commersial games (the circular effects in Golden Sun for example).

Except for the pallete based effects (fade in/fade out) and random based effects (dissolve) I was not able to find *any* resource or example. What makes the task even more interesting is how to implement these in the tile-based modes.

If you have any links and/or book titles regarding the subject please let me know.

Any help or idea will be highly appreciated.

Thanks

#3231 - tepples - Thu Feb 20, 2003 7:18 pm

Warp transitions such as Super Mario All-Stars are done with hblank DMA on the X scroll value. Iris transitions such as Zoop's box between levels and circle at end of game or Super Mario World's keyhole shape iris can be done with hblank DMA on the window registers.

The tile-based clears in Dragon Warrior, Earthbound Zero, and Pokemon are done with a list of tiles you want to clear, in the order that you want them cleared. In each frame, take 32 (x, y) elements from the list and write solid-color tiles into the corresponding map spaces. If you want a symmetrical effect, you can use a bit of mirroring to make the lists shorter.

If you're using any of modes 2, 3, 4, or 5, all of which can be zoomed and rotated, you can do a Final Fantasy VII style fade by zooming and rotating the layer clockwise while fading the palette to white.

One RPG I've played splits the map tiles into n layers, choosing a layer randomly for each tile, and then scrolls each layer randomly while fading the palette.

I still don't know how to do a "shatter" effect on GBA.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.


Last edited by tepples on Fri Feb 21, 2003 3:43 pm; edited 1 time in total

#3272 - joet - Fri Feb 21, 2003 3:13 pm

Hi - I've implemented a simple effect by read/writing the vram tile data (fetching it all back to a buffer, altering it, and DMA-ing it back again) - my effect is (luckily) tailored towards an 8x8 tiled screen though.

And I also had to do the sprite data, etc. Did a few more simple effects by using a layer on top. I guess if you could reserve enough tile data to treat a background as a bitmap then you could do it that way ...

#3275 - dummer Anf?nger - Fri Feb 21, 2003 4:57 pm

http://gbadev.org/download.php?section=demos&filename=swirl.zip
_________________
... but im just a dummy Newbie

(sorry for my terrible english)

#3355 - Drago - Sun Feb 23, 2003 1:09 pm

Circular effects in Golden Sun are implemented by using windowing and hblank. The interrupt routine changes the geometry of the window every scanline, probably using LUTs. Yoshi's Island has similar effects implemented the same way.

#3383 - animension - Sun Feb 23, 2003 9:37 pm

Tepples, do you have sample source of an iris clearing effect? I still don't understand how a window's geometry can be effected to be anything other than a square since all I know is that register 0x04000040 - 0x04000046 deal with the vertical and horizontal dimensions of the window. I haven't seen any documentation about any masks that could be used to create a geometry for the window.
_________________
"Beer is proof that God loves us and wants us to be happy."
-- Benjamin Franklin

#3387 - darkcloud - Sun Feb 23, 2003 10:17 pm

I'd like to see a sample of the iris effect too. I understand the concept, I'm just not sure how to axactly implement it since I'm not that familiar with windowing features.
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.

#3397 - DekuTree64 - Mon Feb 24, 2003 12:59 am

I've never actually done the iris thing, but basically you'd have a table of 160 WIN0H reg values, and in HBL you set WIN0H to your table value at the current scanline.
For the actual values, the easiest way I can think of do it is just take a hunk of EWRAM and treat it like an image, so you can draw a circle in it with Bresenham's algoritm or whatever, and for each line of the screen, search through your image until you find a pixel set to your circle color (I'd just use 0 for blank and 1 for in-circle), and that's the lower 8 bits of WIN0H for that row, then search from there until you find the first pixel set to 0, and that's the upper 8 bits. Oh, and just set WIN0V to center-radius | (center+radius << 8), since it won't need to change per-scanline.

A better way would probably be to have your circle drawing function calculate the x and y of the pixel it's going to draw, and if the x is less than the center x, then check if it's also less than the left value for that scanline, and if so, set the current left to x. Same if it's greater than center, check with the right value. That way, you don't need a big hunk of memory for your temp image, and you don't have to go through all that searching for pixels.

#3412 - animension - Mon Feb 24, 2003 10:59 am

I'm not sure I understand the calculations for plotting the pixels off the top of my head but I'm sure I can get it if I see it in code and can mess around with it. I understand the basic concept though. Essentically, every scanline HBLANK, you dynamically change the WIN(0|1)H to the dimensions of the edge of whatever shape it is to be drawn and let the scan line draw it with the window set to that shape, wash, rinse, repeat.

Am I correct?
_________________
"Beer is proof that God loves us and wants us to be happy."
-- Benjamin Franklin

#3422 - Drago - Mon Feb 24, 2003 3:02 pm

Yes, that's the way. You have a table whith 160 entries, that you can calculate every frame at VBlank. Then, when the screen refresh begins you use those entries, one per scanline, to change the window geometry at HBlank. In fact the effect is very easy to implement, although you will need some tricky maths to calculate the table entries if the shape is complicated enough.

#3429 - DekuTree64 - Mon Feb 24, 2003 5:37 pm

Here's my old implementation of Bresenham's algorithm
Code:

DrawCircle(long xc, long yc, long r)
{
   long x = 0;
   long y = r;
   long p = 3 - (r << 1);

   while(x <= y)
   {
      putPixel(xc + x, yc + y);
      putPixel(xc - x, yc + y);
      putPixel(xc + x, yc - y);
      putPixel(xc - x, yc - y);
      putPixel(xc + y, yc + x);
      putPixel(xc - y, yc + x);
      putPixel(xc + y, yc - x);
      putPixel(xc - y, yc - x);
      if(p < 0)
         p += (x++ << 2) + 6;
      else
         p += ((x++ - y--) << 2) + 10;
   }
}


Don't ask me how it works, cause I don't really understand it myself^^;
It does work though, so just copy/paste it, or do a search on it and you'll get all sorts of different versions of it to pick from.
Another thing with windowing effects is that you have 2 windows, so you could pull off some pretty complicated shapes by using both at the same time and just letting them overlap. Like maybe 2 squares or triangles rotating in opposite directions as they get smaller. Windows also do an inversed-type effect if you swap the start and end pos. I can't think of any use for that, but I'm sure there's plenty of cool stuff you could do.

#3440 - animension - Mon Feb 24, 2003 9:15 pm

I've done work with the Bresenham algorithm before, so it should be easy to implement now that I understand the underlying trick to the effect. It's sweet how innovative people are forced to be when working with a limited hardware platform like the GBA. To think that we can make an iris effect using a window with its shape changing according to a pattern per scanline... ingenious.

I would imagine working a mask with two windows would be useful if you were to draw a mask that required two clear areas per scanline, as opposed to one like with a circle or simple polygon. I can imagine some neat effects that could be accomplished by putting this to work with two windows.

An efficient way I can think of off the top of my head in drawing a polygon or other geometrically shaped mask is to generate a small table of left and right pixel values where the left represented where the window began and the right where it ended. This way, instead of having a huge image table, all you have are the points per scanline where the window begins and ends, essentially a two dimensional unsigned char array of dimensions 2 x 160 for a total of 320 bytes. What it would take to generate this table is an algorithm that can find where the outline of the shape is per y value for the scanline.

You could also store the left and right values in a short with the higher 8 bits representing the left and the lower 8 bits representing the right. could be useful if you want to avoid the complexities of passing multidimensional arrays as parameters to functions.
_________________
"Beer is proof that God loves us and wants us to be happy."
-- Benjamin Franklin

#3452 - tepples - Tue Feb 25, 2003 4:51 am

animension wrote:
To think that we can make an iris effect using a window with its shape changing according to a pattern per scanline... ingenious.

The Atari 2600 drew all graphics that way, by changing the contents of its tiny VRAM each scanline.

Quote:
I would imagine working a mask with two windows would be useful if you were to draw a mask that required two clear areas per scanline, as opposed to one like with a circle or simple polygon. I can imagine some neat effects that could be accomplished by putting this to work with two windows.

Super Mario Kart for Super NES draws the player's ranking (the 3 in the corner) with two semi-transparent windows.

Quote:
generate a small table of left and right pixel values where the left represented where the window began and the right where it ended.

Which can in fact be passed directly to the GBA hardware.

Quote:
You could also store the left and right values in a short with the higher 8 bits representing the left and the lower 8 bits representing the right. could be useful if you want to avoid the complexities of passing multidimensional arrays as parameters to functions.

According to the CowBite spec's REG_WIN0H description, that's exactly how the GBA hardware itself represents the window coordinates.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#3453 - animension - Tue Feb 25, 2003 4:56 am

Seems I got the hang of it then! :)
_________________
"Beer is proof that God loves us and wants us to be happy."
-- Benjamin Franklin

#3472 - Drago - Tue Feb 25, 2003 4:51 pm

tepples wrote:

According to the CowBite spec's REG_WIN0H description, that's exactly how the GBA hardware itself represents the window coordinates.

And now that your table entries have the hardware format you could optimize the transfer by using hblank dma.