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 > messed up sprite coord

#18485 - Darmstadium - Sat Mar 27, 2004 5:01 pm

I am working on this collision detection thing. I have two sprites to test it. I'm storing the coords of my sprites in unsigned shorts and those variables are in a struct along with some other stuff for my collision detection. The x coord of my first sprite is completely wrong, though the y coord was correct. My other sprite always apears where I tell it to. As a despereate attempt to fix this, I changed the types of the variables that store the coords to unsigned chars. The second sprite was where I told it to be, but the first sprite appeared somewhere completely different from where I told it to be. I have absolutely no clue what the heck is going on. Here is my code:
Code:

#include "gba.h"
#include "dispcnt.h"
#include "keypad.h"
#include "sprite.h"
#include "dma.h"

#include "box.raw.c"
#include "box.pal.c"

struct object
{
   u8 n;
   u16 x, y;
   u16 h, w;
};

inline void WaitForVsync();
inline void CopyOAM();
void MoveBox();
bool MoveOK(object *,s16,s16);

#define OBJSLEN   1
object * objs[OBJSLEN];

object box;
object evilBox;

inline void WaitForVsync()
{
   while((volatile u16)REG_VCOUNT != 160){}
}

inline void CopyOAM()
{
   REG_DM3SAD = (u32)sprites;
   REG_DM3DAD = (u32)OAM;
   REG_DM3CNT = 256 | DMA_ENABLE | DMA_TIMEING_IMMEDIATE | DMA_32;
}

bool MoveOK(object * client, s16 xmove, s16 ymove)
{
   u16 loop = 1;
   for (loop = 0; loop <= OBJSLEN; loop++)
   {
      if (objs[loop]->n != client->n)
      {
         if (client->x + xmove + client->w < objs[loop]->x)
            continue;
         if (client->x + xmove > objs[loop]->x + objs[loop]->w)
            continue;
         if (client->y + ymove + client->h < objs[loop]->y)
            continue;
         if (client->y + ymove > objs[loop]->y + objs[loop]->h)
            continue;
         
         return false;
      }
   }
   
   return true;
}

void MoveBox()
{
   if (!(*KEYS & KEY_UP))
   {
      if (MoveOK(&box, 0, -1))
         box.y -= 1;
   }
   if (!(*KEYS & KEY_DOWN))
   {
      if (MoveOK(&box, 0, 1))
         box.y += 1;
   }
   if (!(*KEYS & KEY_LEFT))
   {
      if (MoveOK(&box, -1, 0))
         box.x -= 1;
   }
   if (!(*KEYS & KEY_RIGHT))
   {
      if (MoveOK(&box, 1, 0))
         box.x += 1;
   }
}

int main()
{
   u16 loop;
   
   for(loop = 0; loop < 128; loop++)
   {
      sprites[loop].attribute0 = 160;
      sprites[loop].attribute1 = 240;
   }
   
   REG_DISPCNT = MODE_1 | OBJ_ENABLE | OBJ_MAP_1D;
   
   REG_DM3SAD = (u32)box_Palette;
   REG_DM3DAD = (u32)OBJPaletteMem;
   REG_DM3CNT = 64 | DMA_ENABLE | DMA_TIMEING_IMMEDIATE | DMA_32;
   
   REG_DM3SAD = (u32)box_Bitmap;
   REG_DM3DAD = (u32)&OAMData[0];
   REG_DM3CNT = 64 | DMA_ENABLE | DMA_TIMEING_IMMEDIATE | DMA_32;
   
   objs[0] = &box;
   box.n = 0;
   box.x = 20;
   box.y = 20;
   box.h = 16;
   box.w = 16;
   sprites[0].attribute0 = COLOR_256 | SQUARE | box.y;
   sprites[0].attribute1 = SIZE_16 | box.x;
   sprites[0].attribute2 = 0;
   
   objs[1] = &evilBox;
   evilBox.n = 1;
   evilBox.x = 120;
   evilBox.y = 60;
   evilBox.h = 16;
   evilBox.w = 16;
   sprites[1].attribute0 = COLOR_256 | SQUARE | evilBox.y;
   sprites[1].attribute1 = SIZE_16 | evilBox.x;
   sprites[1].attribute2 = 0;
   
   while (1)
   {
      MoveBox();

      sprites[0].attribute0 = COLOR_256 | SQUARE | box.y;
      sprites[0].attribute1 = SIZE_16 | box.x;
      
      sprites[1].attribute0 = COLOR_256 | SQUARE | evilBox.y;
      sprites[1].attribute1 = SIZE_16 | evilBox.x;
      
      WaitForVsync();
      CopyOAM();
   }
   return 0;
}


Thanks in advance

#18486 - Miked0801 - Sat Mar 27, 2004 5:22 pm

objs[1] = &evilBox;

reads off the end of your pointer list - it is only 1 in length - same bug as in the previous post. Chaos thus ensues

#18488 - Darmstadium - Sat Mar 27, 2004 5:42 pm

You could not possibly comprehend how grateful I am. Seriously!!!!!!!!!

#18494 - sajiimori - Sat Mar 27, 2004 7:40 pm

The previous bug is still there, too. Your loop in MoveOK tests for loop <= OBJSLEN, so what is the last index that's accessed?

Also, about your scheme of having seperate variables for each object, then having an array of pointers to all of them: it's clever, but not very memory efficient, and it's somewhat slower during collision detection due to the extra pointer indirection. How about this?
Code:

#define OBJSLEN   2
object objs[OBJSLEN];

#define box     objs[0]
#define evilBox objs[1]

Now you can access box and evilBox just like normal, you don't have an extra initialization step, and accessing the objects using the array is faster.

#18495 - Lupin - Sat Mar 27, 2004 9:43 pm

do you check if the x/y value is out of bounds? I think it is 9 bits for X and 8 bits for Y but i am not sure, you should check for the value anyway...
_________________
Team Pokeme
My blog and PM ASM tutorials

#18499 - Darmstadium - Sun Mar 28, 2004 1:18 am

Thanks a lot for you help guys!