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.

DS development > Background Rotation and Movement Question (now with code)

#46920 - connor9 - Sat Jul 02, 2005 2:33 am

I'm having a bit of trouble with rotation backgrounds. I want to be able to rotate a background about the center point of the screen as in this picture:
[Images not permitted - Click here to view it]

After you've rotated say 45 degrees, if you press up or down I want background to move up and down relative to the screen as opposed to relative to it's own position. As in number two in the following figure.
[Images not permitted - Click here to view it]

From reading the old cearn tutorials I can only seem to get the behavoir shown in number 1 of the second picture. When you press up or down it moves up and down relative to the background. I.e if you've rotated 45 degrees. Down will move it in a 45 degree angle line.

Any help would be much appreciated.

Update: Here's the code for it:

Code:

s16 s = SIN[angle & 0x1FF] >> 4;
s16 c = COS[angle & 0x1FF] >> 4;
(scaleX,Y are alwats 1 << 8)


This will rotate about the left corner of the screen(bad), but up and down are relative to the screen not the background(good!)
Code:

        s16 tX = scrollX<<8;
        s16 tY = scrollY<<8;
        s16 tcx = (c*scrollX - s*scrollY);
        s16 tcy = (s*scrollX + c*scrollY );
   
        BG3_XDX = ( c * scaleX ) >> 8;
        BG3_XDY = (-s * scaleX ) >> 8;
        BG3_YDX = ( s * scaleY ) >> 8;
        BG3_YDY = ( c * scaleY ) >> 8;
       
        BG3_CX = tcx - rcX * (c - s);
        BG3_CY = tcy - rcY * (s + c);

This will rotate about the center of the screen(good!), but up and down are relative to the background not the screen (bad)
Code:

        s16 tX = scrollX<<8;
        s16 tY = scrollY<<8;
        s16 tcx = tX;
        s16 tcy = tY;
   
        BG3_XDX = ( c * scaleX ) >> 8;
        BG3_XDY = (-s * scaleX ) >> 8;
        BG3_YDX = ( s * scaleY ) >> 8;
        BG3_YDY = ( c * scaleY ) >> 8;
       
        BG3_CX = tcx - rcX * (c - s);
        BG3_CY = tcy - rcY * (s + c);

#47108 - Cearn - Tue Jul 05, 2005 8:21 am

(tcx,tcy) scrolls along the map's principal axes, (rcx,rcy) along the screen's. Try modifying rcx/y values instead of tcx/y.

#47202 - Cearn - Wed Jul 06, 2005 9:15 am

... nm, should have read more carefully. The basic equation is
dx = p0 - P?q0
with p0 the origin in map-space (scrolls along map axes) and q0 the origin in screen-space (scrolls along screen axes). You need something like this because the registers do the translation before the transformation, so you need to compensate for the matrix so scroll along the screen axes. The versions you have now use P on p0 and something very strange to q0. Something like this should be better:
Code:
// NOTE: terms are never defined, going by this assumption
// p0 = (scrollX,scrollY)  (.0 fixed)
// q0 = (rcX,rcY)  (.0 fixed)
s32 tcX = scrollX<<8;
s32 tcY = scrollY<<8;
   
BG3_XDX = ( c * scaleX ) >> 8;
BG3_XDY = (-s * scaleX ) >> 8;
BG3_YDX = ( s * scaleY ) >> 8;
BG3_YDY = ( c * scaleY ) >> 8;
       
BG3_CX = tcx - (rcX*c - rcY*s);
BG3_CY = tcy - (rcX*s + rcY*c);

#47217 - connor9 - Wed Jul 06, 2005 2:57 pm

Hey thanks for the help.

I tried that and it rotates around the screen center but it moves along the map axis instead of along the screen axis. rcX and rcY should be set to the screen midpoints right?

Here's the rom of what it's doing:
http://www.connor.completelyfreehosting.com/starfield/

Again thanks for helping me.

#47226 - Cearn - Wed Jul 06, 2005 4:26 pm

The binary doesn't seem to work on any of the emulators (unless I'm doing it wrong, which is a good possibility here), so I can't see what it does. Sorry.

Take a step back and look at each step in the mapping process. In principle, the rotation always happens with respect to the screen's origin. With dx= (BG3_CX, BG3_CY) you can set offset the map coordinates. The rotation still happens around the screen's origin, but this is now at a different map-coordinate dx, so that it looks as though you rotate around different map coordinates.
A map-offset is all you have available here: it's not possible to rotate around any other screen position than the origin. However, what you can do is make it look like you're doing that, and that's where p0=(tcX, tcY) and q0=(rcX,rcY) come in. p0 is the map-point around which the rotation takes place. The purpose of q0 is to then move the image you now have by rcX horizontally and rcY vertically. Basically, rcX and rcY serve as the screen's scrolling registers. By combining them via dx= p0-P?q0 you have map offset dx that rotates around p0 (with a radius |q0|) so that it looks as though you're rotating around a different screen point than the origin, but all you're doing is updating what is mapped to the origin as you rotate.

Remember what p0 and q0 represent, don't think about the final effect. I have the feeling that what you want isn't a way to scroll along the screen axes (that'd be what q0 is for), but a way to walk on the map along an angle (changing p0). The effect looks the same if you walk, but if you then rotate the difference becomes clear. To accomplish that, do something like p0 += P?ds, where ds is the vector of movement along screen axes.

I know it's tricky to explain without images or a movie or something. You could try constructing something out of paper and sticks to get a feel of what's going on.