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 > Movements of sprite and blur

#5592 - Link - Fri May 02, 2003 2:54 pm

I'm proving the .bin file of tutorial33.zip of pernproject...
(i'm learning how show sprite on GBA and move)

But moving the sprite in that .bin example i can see a bad blur of image:

When i move the image it became blurry, in the movement i see it not correctly (like bleary)...
Instead if i try commercial game it don't happen..

What does depend it by?

#5610 - pollier - Sat May 03, 2003 4:10 am

Make sure your emulator is running at full speed, and maybe turn on V-Sync if you're using, say, VBA. Or does this problem occur on hardware? If so, the code isn't waiting for the V-Blank to update the position. Be sure to update your OAM after scanlines have finished to avoid shearing.
_________________
(Works for me!)

#5612 - Link - Sat May 03, 2003 8:47 am

Quote:
Make sure your emulator is running at full speed, and maybe turn on V-Sync if you're using, say, VBA.

i don't think it depend by that, because i have the some configuration of emu with commercial rom, and blurry don't happen with them.

Quote:
V-Blank

can u explain? What is V-blank?

Update? i do see you the code:

Code:
/********************************************************
*   
*
*            by devoto
*
*   
********************************************************/
#include<math.h>
#include"gba.h"
#include"screenmode.h"
#include"keypad.h"
#include"sprite.h"

#include"sprite1.h"



#define FIXED s32
#define PI 3.14159
#define RADIAN(n)       (((float)n)/(float)180*PI)

///declare our functions so the c compiler knows what we are talking about

void InitializeSprites(void);
void WaitForVsync(void);
void CopyOAM(void);
void GetInput(void);
void MoveSprite(OAMEntry* sp, int x, int y);
void RotateSprite(int rotDataIndex, int angle, FIXED x_scale,FIXED y_scale);

///these are global so i do not have to pass them to GetInput
s16 x = 10;
s16 y = 10;
u16 char_number = 0;

FIXED angle = 0;
FIXED zoom = 1<<8;

FIXED SIN[360];
FIXED COS[360];



///main entry point from the boot.asm startup file
int main(void)

{
   int index = 0;  //some looping variables for loops :)
   u16 loop;
   
   for(loop = 0; loop < 360; loop++)
   {
      SIN[loop] = (FIXED)(sin(RADIAN(loop)) * 256);  //sin and cos are computed and cast to                      //fixed
      COS[loop] = (FIXED)(cos(RADIAN(loop)) * 256);
   }
   
   SetMode(MODE_2 | OBJ_ENABLE | OBJ_MAP_1D); //set mode 2 and enable sprites and 2d mapping

   for(loop = 0; loop < 256; loop++)
      OBJPaletteMem[loop] = sprite1Palette[loop];   //loop through and store the palette from your pict
                           //palette into obj palette mem OBJPaletteMem is
                           //defined in gba.h.  sprite1Palette is from
                           //pcx2gba tool sprite1.h.
   
   InitializeSprites();  //set all 128 sprites to offscreen

   //this is were we define our sprite atributes for the first sprite
   //256 color 64x64 sprite that starts at character 0.  Character 0 is
   //the first sprite data memory location.

   sprites[0].attribute0 = COLOR_256 | SQUARE| ROTATION_FLAG | y; 
   sprites[0].attribute1 = SIZE_64 |ROTDATA(0)|x;
   sprites[0].attribute2 = char_number;

   
//allright now to copy in the sprites bitmap.  The data in sprite1Data is allready striped
//so we just copy it in one row of tiles at a time.  The only difference between this and a
//2D sprite is that we would need to keep in mind the fact that the tiles are not all in a row.
//We could just use one big for loop.  There are 8 rows (64x64 = 8x8 tiles) so we loop through
//all 8.  There is 512 bytes per row (8 tiles * 8x8 = 512) but since we copy 2 bytes at a
//time that equals 256.  The width of char memory is 32 * 8x8 = 1024 (512 double bytes).
//   
      for(index = 0; index < 256*8; index++)
      {
         OAMData[index] = sprite1Data[index]; 
         
      }//end index loop

///Main Game loop   
   while(1)
   {
      GetInput();    //get input changes the x and y based on input
      MoveSprite(&sprites[0],x,y); //changes sprite atributes based on new x,y
      
      RotateSprite(0,angle,zoom,zoom);

      WaitForVsync();         //waits for the screen to stop drawing
      CopyOAM();            //Copies our sprite array into OAM.
   }
}

////Set sprites to off screen

void InitializeSprites(void)
{
   int loop;
   for(loop = 0; loop < 128; loop++)
   {
      sprites[loop].attribute0 = 160;  //y to > 159
      sprites[loop].attribute1 = 240;  //x to > 239
   }
}

//wait for the screen to stop drawing
void WaitForVsync(void)
{
   

//lets get rid of htat inline asm we used in arm

/*
   __asm
   {
      mov    r0, #0x4000006   //0x4000006 is vertical trace counter; when it hits 160                //160 the vblanc starts
      scanline_wait:             //the vertical blank period has begun. done in asm just
                        //because:)
      ldrh   r1, [r0]
      cmp   r1, #160
      bne    scanline_wait
   }         
*/

while(REG_VCOUNT<160);

}

///Copy our sprite array to OAM
void CopyOAM(void)
{
   u16 loop;
   u16* temp;
   temp = (u16*)sprites;
   for(loop = 0; loop < 128*4; loop++)
   {
      OAM[loop] = temp[loop];
   }
}

///Test for key presses
void GetInput(void)
{
   if(!(*KEYS & KEY_UP))
   {
       y--;
   }
   if(!(*KEYS & KEY_DOWN))
   {
       y++;
   }
   if(!(*KEYS & KEY_LEFT))
   {
       x--;
   }
   if(!(*KEYS & KEY_RIGHT))
   {
       x++;
   }
   if(!(*KEYS & KEY_L))
   {
       angle--;
      if(angle<0)
         angle = 359;
   }
   if(!(*KEYS & KEY_R))
   {
       angle++;
      if(angle > 359)
         angle = 0;
   }
   if(!(*KEYS & KEY_A))
   {
       zoom--;
   }
   if(!(*KEYS & KEY_B))
   {
       zoom++;
   }
   if(!(*KEYS & KEY_START))
   {
       if(!(sprites[0].attribute0 & SIZE_DOUBLE))//set or clear size double
      {                                 //needs if to keep from holding down the start
         sprites[0].attribute0 |= SIZE_DOUBLE;
         x-=32;                        //size double shifts the sprite center by half the width and height this just
         y-=32;                        //adjusts for it.
      }
   }
   if(!(*KEYS & KEY_SELECT))
   {
       if((sprites[0].attribute0 & SIZE_DOUBLE))
      {
         sprites[0].attribute0 &= ~SIZE_DOUBLE;
         x+=32;
         y+=32;
      }
   }
}

//move the sprite
void MoveSprite(OAMEntry* sp, int x, int y)
{
   if(x < 0)         //if it is off the left corect
      x = 512 + x;
   if(y < 0)         //if off the top corect
      y = 256 + y;

   sp->attribute1 = sp->attribute1 & 0xFE00;  //clear the old x value
   sp->attribute1 = sp->attribute1 | x;
   
   sp->attribute0 = sp->attribute0 & 0xFF00;  //clear the old y value
   sp->attribute0 = sp->attribute0 | y;
}   
void RotateSprite(int rotDataIndex, int angle, FIXED x_scale,FIXED y_scale)
{
   
   FIXED pa,pb,pc,pd;

   pa = ((x_scale) * COS[angle])>>8;    //(do my fixed point multiplies and shift back down)
   pb = ((y_scale) * SIN[angle])>>8;
   pc = ((x_scale) * -SIN[angle])>>8;
   pd = ((y_scale) * COS[angle])>>8;


   rotData[rotDataIndex].pa = pa;  //put them in my data struct
   rotData[rotDataIndex].pb = pb;
   rotData[rotDataIndex].pc = pc;
   rotData[rotDataIndex].pd = pd;
}

#5617 - Malefactor - Sat May 03, 2003 3:02 pm

if you are using VBA, make sure you have the motion blur filter turned off.
_________________
[Images not permitted - Click here to view it]

#5620 - pollier - Sat May 03, 2003 9:17 pm

Code:
//wait for the screen to stop drawing
void WaitForVsync(void)
{
   

//lets get rid of htat inline asm we used in arm

/*
   __asm
   {
      mov    r0, #0x4000006   //0x4000006 is vertical trace counter; when it hits 160                //160 the vblanc starts
      scanline_wait:             //the vertical blank period has begun. done in asm just
                        //because:)
      ldrh   r1, [r0]
      cmp   r1, #160
      bne    scanline_wait
   }         
*/

while(REG_VCOUNT<160);

}


This is interesting... It should work fine, but you might want to watch out for skipping frames. I don't think that would be the cause of the blurring, however.

V-Blank is the period in which it's safe to do anything to the display registers/memory without getting things like shearing on the LCD because the GBA is finished drawing scanlines for this frame.

If we're talking about a real 'blur' then it's definitely your emulator, but if the image is choppy or sheared then it might be either the emulator or the code.
_________________
(Works for me!)

#5625 - Link - Sun May 04, 2003 1:06 am

what exactly do this??:
Code:
 //wait for the screen to stop drawing
void WaitForVsync(void)
{
   

//lets get rid of htat inline asm we used in arm

/*
   __asm
   {
      mov    r0, #0x4000006   //0x4000006 is vertical trace counter; when it hits 160                //160 the vblanc starts
      scanline_wait:             //the vertical blank period has begun. done in asm just
                        //because:)
      ldrh   r1, [r0]
      cmp   r1, #160
      bne    scanline_wait
   }         
*/

while(REG_VCOUNT<160);

}


however the motion blur is disabled, and i usa VBA with parameters default.
In the game (commercials) the blur don't appear but in my test yes!

#5632 - antysix - Sun May 04, 2003 2:19 pm

It waits for the screen to finish drawing.
_________________
Currently playing: NGC: Metroid Prime
GBA: Golden Sun: The Lost Age

Currently developping: Project ~ [ Phail ]

#5633 - Link - Sun May 04, 2003 2:27 pm

how do u do?

Thanx for help! ;)

#5634 - Touchstone - Sun May 04, 2003 2:51 pm

A more proper wait-vsync is this:
Code:
void WaitForVsync(void)
{
    while(REG_VCOUNT == 160);
    while(REG_VCOUNT != 160);
}

This is safer to use if your processing-time of a frame is shorter than the vblank period.
_________________
You can't beat our meat

#5635 - Link - Sun May 04, 2003 3:09 pm

Tnx much