#9969 - nazuraku - Sat Aug 23, 2003 7:57 pm
I have gone through and downloaded pern's tutorial 3 and it seems to work fine except for one issue... whenever the sprite passes off the screen and returns on the other side and then crosses the point x coordinate at which it started... it suddenly becomes a blank green square. I am at a loss how this could happen and am wondering if someone has any clues to why. I origionally thought it could be a emulator issue, but I have tried multiple emulators and they all do the same thing. It also appears that the sprite will get knocked a little to the right if you continually press down. I will post the code below, but I am assuming many of you already have this code.
#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 AgbMain(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;
}
I would appreciate any ideas or comments you may have
thx
#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 AgbMain(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;
}
I would appreciate any ideas or comments you may have
thx