I'm coding a simple physics demo for the GBA. This is a 2D demo. One thing to know is that the GBA screen is 240x160 pixels. There is a struct called object that stores data for images that can be collided with. There is a struct called force that keeps track of the amount of force in the x direction and the amount of force in the y direction. Also there is a struct called special_obj that is for the edges of the screen and stuff in the background (if I had one). I don't think I'll really explain the GBA-specific stuff too much, but you should know that the WaitForVsync() function waits until the GBA is done drawing the current frame. Every object is moved each frame based on the values in it's force struct. So the function ApplyAllForce() loops through every object in the array of objects objs and applies force based on each object's force struct. In this demo, there is only one object. Now, the problem is that my collision detection system isn't working at all. I've used it before and it works perfectly. Hmm... I'm sure that's all you need to know. Here's 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 force
{
s16 x, y;
};
struct object
{
u8 n, x, y, h, w, m;
force v;
void move();
};
struct special_obj
{
u8 x, y, h ,w;
};
inline void WaitForVsync();
inline void CopyOAM();
bool MoveOK(object *,s16,s16);
inline void apply_force(force *,object *);
inline void return_force(force *,object *);
void TakeBoxInput();
void ApplyAllForce();
u8 vsyncs = 0;
u16 keys_lastframe;
#define OBJSLEN 1
#define SPECIALSLEN 4
object objs[OBJSLEN];
special_obj specials[SPECIALSLEN];
force gravity;
force jump;
void object::move()
{
if (MoveOK(this, v.x, v.y))
{
x += v.x >> 4;
y += v.y >> 4;
}
}
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 objsMoveOK(object * client, s16 xmove, s16 ymove)
{
u16 loop;
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;
}
bool specialsMoveOK(object * client, s16 xmove, s16 ymove)
{
u16 loop;
for (loop = 0; loop < SPECIALSLEN; loop++)
{
if (client->x + xmove + client->w <= specials[loop].x)
continue;
if (client->x + xmove >= specials[loop].x + specials[loop].w)
continue;
if (client->y + ymove + client->h <= specials[loop].y)
continue;
if (client->y + ymove >= specials[loop].y + specials[loop].h)
continue;
return false;
}
return true;
}
bool MoveOK(object * client, s16 xmove, s16 ymove)
{
if (!objsMoveOK(client, xmove, ymove))
return false;
if (!specialsMoveOK(client, xmove, ymove))
return false;
return true;
}
inline void apply_force(force * v, object * obj)
{
obj->v.x += v->x;
obj->v.y += v->y;
}
inline void return_force(force * v, object * obj)
{
obj->v.x -= v->x;
obj->v.y -= v->y;
}
void TakeBoxInput()
{
if ((!(*KEYS & KEY_A)) && (keys_lastframe & KEY_A) && (objs[0].y + objs[0].h == 159))
apply_force(&jump, &objs[0]);
if (!(*KEYS & KEY_LEFT))
objs[0].v.x -= 1;
if (!(*KEYS & KEY_RIGHT))
objs[0].v.x += 1;
}
void ApplyAllForce()
{
u16 loop;
for (loop = 0; loop < OBJSLEN; loop++)
{
apply_force(&gravity, &objs[loop]);
if (objs[loop].y + objs[loop].h == 159)
return_force(&gravity, &objs[loop]);
objs[loop].move();
}
}
int main()
{
gravity.x = 0;
gravity.y = 1;
jump.x = 0;
jump.y = -20;
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;
//box
objs[0].x = 20;
objs[0].y = 140;
objs[0].h = 16;
objs[0].w = 16;
objs[0].m = 3;
objs[0].v.x = 0;
objs[0].v.y = 0;
sprites[0].attribute0 = COLOR_256 | SQUARE | objs[0].y;
sprites[0].attribute1 = SIZE_16 | objs[0].x;
sprites[0].attribute2 = 0;
//ground
specials[0].x = 0;
specials[0].y = 160;
specials[0].h = 0;
specials[0].w = 240;
//ceiling
specials[1].x = 0;
specials[1].y = 0;
specials[1].h = 0;
specials[1].w = 240;
//left barrier
specials[2].x = 0;
specials[2].y = 0;
specials[2].h = 160;
specials[2].w = 0;
//right barrier
specials[3].x = 240;
specials[3].y = 0;
specials[3].h = 160;
specials[3].w = 0;
while (1)
{
sprites[0].attribute0 = COLOR_256 | SQUARE | objs[0].y;
sprites[0].attribute1 = SIZE_16 | objs[0].x;
keys_lastframe = *KEYS;
WaitForVsync();
CopyOAM();
vsyncs++;
TakeBoxInput();
ApplyAllForce();
}
return 0;
}
Thanks for your help