Archived

This topic is now archived and is closed to further replies.

slippers2k

Ack! Need crash course in GBA tile background mode rendering

Recommended Posts

slippers2k    138
I need help figuring out how to draw and set up a background mode (modes 0-2) on the gba. I can understand a little bit of the internals, but I am confused with how to properly draw tiles and set up a background. I''m assuming you would need a gba tile map editor. Just need to get over this hurdle! Thanks in advance for any assistance. Sincerely, Ramon Reyes

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
www.thepernproject.com has some great tutorials also.

Share this post


Link to post
Share on other sites
I''m not sure what your problem is at the moment, so i suppose all i can do is point you to some of the more general stuff. as has already been mentioned, the pern project has some great tutorials on the matter, so make sure you''ve looked over that well. if you just want a code example, you can take a look at this, which i posted on another thread about sprites, but still might be helpful for you:

http://home.attbi.com/~runeofalgo/spritedemo.zip

Of course, i didn''t actually read in map data in this one, but you can assume that all you''d change is that instead of having some quirky formula to pick a tile, you''d just copy from another array. And if you were doing that, you should probably use a DMA copy instead, but you probably get the picture.

-Arek the Absolute

Share this post


Link to post
Share on other sites
slippers2k    138
Question: now that I've loaded my background, one of my sprites has stopped responding to movement commands. Is it possible that I've overlapped background and sprite memory? If so, what should I do about it?

Thanks for all your help.
-slippers2k

EDIT: The one sprite that is not moving yet is my first sprite, which is at character number 0 in sprite data memory. Every other sprite works and is accessible, so I will try to change the sprite character number. -slippers2k

EDIT (Mar 25 2003): I tried changing the character number but no dice. What gives?

Quotes from ThePernProject.Com:
quote:
Tile data can be placed anywhere in VRAM as long as it is on a 16KB boundary (from 0x6000000-0x600FFFF).

(Reference to character base blocks)

quote:
Character data starts at 0x6010000 and extends for 32KB.

Note that in either instance, both fields of memory do not seem to overlap. Is my program suffering from code indigestion?

The understanding I'm missing is how to effectively marry the sprite tutorials I've learned from day 3 of ThePernProject.Com to the ease of text backgrounds in modes 0 - 2.

quote:
To compute the actual memory address of a character the following equation will work. 0x6010000 + (CharName * 8x4) = addressOfChar. 0x6010000 is the start address of character memory...
(From day 3 - is this information only relevant to a mode 3/4/5 environment?)

Just in case the last several weeks and months of code questions have been confusing, let me post my code, and leave no mind sane.

quote:
// new_pong_proj.c AGBmain Entry point is contained here (main program loop)

#include <gba.h> //extra-large header file - screenmode, keys, sprite info and more
#include "stdlib.h" //standard code needed for certain functions (not sure which)
#include <mathluts.h> //precompiled sin and cos values (not necessary)
#include <interupts.h> //GBA interrupt information above and beyond that of gba.h
#include "TEST.h" //background file - no longer used since I am using mode 0 - Mar 25 2003
#include "SPRITE1.h" //sprite#1 - my first car
#include "SPRITE2.h" //sprite#2 - a big square tennis ball
#include "SPRITE4.h" //sprite#4 - blue car (computer opponent)
#include "NUMBER0.h" //numbered sprites for keeping score onscreen (Jan 26 2003)
#include "NUMBER1.h"
#include "NUMBER2.h"
#include "NUMBER3.h"
#include "NUMBER4.h"
#include "NUMBER5.h"
#include "NUMBER6.h"
#include "NUMBER7.h"
#include "NUMBER8.h"
#include "NUMBER9.h"
#include "CARPONG.h" //splash screen

#include "levelone1.c" //my first level map
#include "levelone1.h" //my first level map header

// GLOBAL VARIABLES

u16* OAM = (u16*)0x7000000;
OAMEntry sprites[128];
pRotData rotData = (pRotData)sprites;

//determines whether ball travels toward player or computer

int direction_x = 1;
int direction_y = 1;

//variables for scrolling the background

/////////////////////////SPRITE GLOBAL VARIABLES//////////////////////////////////////

///these are global so i do not have to pass them to GetInput -dovoto

//x and y for sprite 1 - yellow car
s16 x = 0;
s16 y = 50;


int count = 0;

//Character number global vars below allow us to swap sprite contents on the fly
//(Jan 26 2003)

u16 char_number = 0;
u16 char_number_yellow = 0;
u16 char_number_blue = 0;
u16 char_number_n0 = 0;
u16 char_number_n1 = 0;
u16 char_number_n2 = 0;
u16 char_number_n3 = 0;
u16 char_number_n4 = 0;
u16 char_number_n5 = 0;
u16 char_number_n6 = 0;
u16 char_number_n7 = 0;
u16 char_number_n8 = 0;
u16 char_number_n9 = 0;

u16 char_number_ntemp = 0;

//x and y for tennis ball (yes, I know it's square
s16 xs = 100;
s16 ys = 50;

//x and y for sprite 4 - blue car
s16 x4 = 180;
s16 y4 = 50;

//for collision detection: define bounding boxes for the 64x64 sprites - me (12/9/02)
//UPDATE: 12/12/02 - decided to use 32x32 sprites for paddles
//(game will be "car pong")

s16 x_ur = 0;
s16 y_ll = 0;

s16 xs_ur = 0;
s16 ys_ll = 0;

s16 x4_ur = 0;
s16 y4_ll = 0;

/////////////////////////////// RGB macro
/************************************************************* The GBA stores 15 bit color in blue green red format meaning
* the first 5 bits are the red the next 5 bits are green and the next
* 5 blue. This macro just shifts the colors over the correct amount.
* RGB is the more standard way to represent color.
\************************************************************/
#define RGB(r,g,b) ((r)+((g)<<5)+((b)<<10)) /*both do the same thing but just in case you prefer RGB notation i included both macros */
#define BGR(b,g,r) ((r)+((g)<<5)+((b)<<10))

//DMA_Copy - FAST memory copying on the gba Mar 20 2003

void DMA_Copy(u8 channel, void* source, void* dest, u32 WordCount, u32 mode)
{
switch (channel)
{
case 0:
REG_DMA0SAD = (u32)source;
REG_DMA0DAD = (u32)dest;
REG_DMA0CNT = WordCount | mode;
break;
case 1:
REG_DMA1SAD = (u32)source;
REG_DMA1DAD = (u32)dest;
REG_DMA1CNT = WordCount | mode;
break;
case 2:
REG_DMA2SAD = (u32)source;
REG_DMA2DAD = (u32)dest;
REG_DMA2CNT = WordCount | mode;
break;

case 3:
REG_DMA3SAD = (u32)source;
REG_DMA3DAD = (u32)dest;
REG_DMA3CNT = WordCount | mode;
break;

}
}

//my plot pixle function from day 2 -dovoto
void PlotPixel(int x,int y, unsigned short int c) {VideoBuffer[(y) *120 + (x)] = (c);}

// functions (all functions -dovoto unless otherwise stated)

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)
{
while((volatile u16)REG_VCOUNT != 160){}

}

///Test for key presses
void GetInput(void)
{

//for collision detection: define bounding boxes for the 64x64 sprites - me (12/9/02)
// x_ur = X coordinate of first sprite at upper right corner (BAD variable naming...sorry!)
// y_ll = Y coordinate of first sprite at lower left corner

// xs_ur = X coordinate of second sprite at upper right corner
// ys_ll = Y coordinate of second sprite at lower left corner

x_ur = x + 32;
y_ll = y + 32;

xs_ur = xs + 16;
ys_ll = ys + 16;

x4_ur = x4 + 32;
y4_ll = y4 + 32;

if(!(*KEYS & KEY_UP))
{
y--;
if(y==ys_ll)
if(x<=xs_ur)
if(x_ur>=xs)
y++;
//experimental
//y4--;
}
if(!(*KEYS & KEY_DOWN))
{
y++;
if(y_ll==ys)
if(x<=xs_ur)
if(x_ur>=xs)
y--;
//experimental
//y4++;
}
if(!(*KEYS & KEY_LEFT))
{
x--;
if(x==xs_ur)
if(y<=ys_ll)
if(y_ll>=ys)
x++;
}
if(!(*KEYS & KEY_RIGHT))
{
x++;
if(x_ur==xs)
if(y<=ys_ll)
if(y_ll>=ys)
x--;
}
if(!(*KEYS & KEY_START))
{
while(1) //man-made infinite loop with a break condition
{
WaitForVsync();
if(!(*KEYS & KEY_START))
break;
}
}
if(!(*KEYS & KEY_A))
{
sprites[0].attribute2 = char_number_blue;
}
if(!(*KEYS & KEY_B))
{
sprites[0].attribute2 = char_number_yellow;
}
if(!(*KEYS & KEY_L))
{
if (count == 0)
{
sprites[3].attribute2 = char_number_n1;
}
if (count == 1)
{
sprites[3].attribute2 = char_number_n2;
}
if (count == 2)
{
sprites[3].attribute2 = char_number_n3;
}
if (count == 3)
{
sprites[3].attribute2 = char_number_n4;
}
if (count == 4)
{
sprites[3].attribute2 = char_number_n5;
}
if (count == 5)
{
sprites[3].attribute2 = char_number_n6;
}
if (count == 6)
{
sprites[3].attribute2 = char_number_n7;
}
if (count == 7)
{
sprites[3].attribute2 = char_number_n8;
}
if (count == 8)
{
sprites[3].attribute2 = char_number_n9;
}
if (count == 9)
{
sprites[3].attribute2 = char_number_ntemp;
count = 0;
}
count++;
//sprites[3].attribute2 = char_number_n1;
}
if(!(*KEYS & KEY_R))
{
sprites[3].attribute2 = char_number_n0;
}

}

//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;

/////////////////////////COLLISION DETECTION CODE/////////////////
///////////////////(FOR TENNIS BALL)//////////////////////////////

xs -= direction_x;

if (xs == 0)
{
direction_x *= -1;
xs++;
}

if (xs == 220)
{
direction_x *= -1;
xs--;
}

if (xs==x4)
if(ys<=y4_ll)
if(ys_ll>=y4)
{
direction_x *= -1;
xs--;
}

if (xs==x_ur)
if(ys<=y_ll)
if(ys_ll>=y)
{
direction_x *= -1;
xs++;
}

ys -= direction_y;

if (ys == 0)
{
direction_y = -1;
ys++;
}
if (ys == 140)
{
direction_y *= -1;
ys--;
}

//experimental (12/14/2002)
y4 = ys;

//approaching tennis ball from the left
//if((x)==(xs))
// x--;

//approaching from the right
//if((x)<(xs))
// x++;

//////////////END COLLISION DETECTION CODE ///////////////////////
///(CALL YOUR INSURANCE COMPANY!!! /////////////////////////////

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;
}

///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];
}
}

int main(void)
{
int index = 0; //some looping variables for loops
u16 loop;



SetMode(MODE_4 | BG2_ENABLE| 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.

while(1)
{
for(loop = 0; loop < 256; loop++)
BGPaletteMem[loop] = CARPONGPalette[loop];

for (y = 0; y < 160; y++)
{
for (x = 0; x < 120; x++)
{
PlotPixel(x,y,CARPONGData[y*120+x]);
}
}

if(!(*KEYS & KEY_START))
break;
}

//Regular background (mode 4) is now disabled, going to load mode 0 background (Mar 18 2003)
//for(loop = 0; loop < 256; loop++)
// BGPaletteMem[loop] = TESTPalette[loop]; //loop through and store the palette from your pict
// //palette into video palette mem
//
//for(y = 0; y < 160; y++)
//{
// for(x = 0; x < 120; x++)

// {
// PlotPixel(x,y,TESTData[y*120+x]);//testData contains the color values of your pict
//if((x>0)&&((x%10)==0))
// PlotPixel(x,y,RGB(31,31,31));
// HISTORY: Above two lines are debug scaffolding... used to delineate x coords
// (Dec 9 2002)

// }
//}

//

int x=0,y=0; //just some looping vars

//this is a temparary pointer that we will point to the last screen memory block(31)
u16* bg0map =(u16*)ScreenBaseBlock(31);

//bg0map now points to were we are going to put our map data

//now we set up background 0 to be a 256 x 256 256 color background and make sure it
//it looks in the right place for its map data
REG_BG0CNT = BG_COLOR256 | TEXTBG_SIZE_256x256 | (31 << SCREEN_SHIFT) | WRAPAROUND;

//good old set mode function. here we just set it to mode 0 and enable background 0
SetMode(MODE_0 | BG0_ENABLE| OBJ_ENABLE | OBJ_MAP_1D); //added OBJ_ENABLE and OBJ_MAP_1D
//Mar 18 2003


//now we use our DMA copy routine to copy in the palette
DMA_Copy(3,(void*)levelone1Map.pal,(void*)BGPaletteMem,256,DMA_16NOW);

//now we copy in the tile data
DMA_Copy(3,(void*)levelone1Map.tiledata,(void*)CharBaseBlock(0),levelone1Map.tileDataSize/4,DMA_32NOW);

//now we copy in the map. this could be done with dma as well but this is a bit more flexible
for(y = 0; y < 32; y++) //loop through all 32x32 tiles
{
for(x = 0; x < 32; x++)
{
//this is were the data from our map editor is copied to video memory
bg0map[x + y * 32] = levelone1Map.layers[0].data[x + y * levelone1Map.layers[0].w];

}

}


//our main loop..this is were we would normaly do stuff
//for now we just let you scroll around a bit with the keys
//to see your map.


//while(1)
//{

//while(!(REG_DISPSTAT & 1));//wait for vblank to start

//use the hardware to scroll around some
//if(!(KEYS & KEY_LEFT))x--;
//if(!(KEYS & KEY_RIGHT))x++;
//if(!(KEYS & KEY_UP))y--;
//if(!(KEYS & KEY_DOWN))y++;

//We load x and y into the offset registers and the GBA scrolls the background for us
//REG_BG0VOFS = y ;
//REG_BG0HOFS = x ;

//while((REG_DISPSTAT & 1));//wait for vblank to end

//}//end while
//}//end main


//

x = 10;
y = 10;
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 | y;
sprites[0].attribute1 = SIZE_32 | x;
sprites[0].attribute2 = char_number; //bit map mode so the first 512 chars are not available
//UPDATE: mode 0 - no more need to add 512 (3/18/03)

char_number_yellow = char_number;

sprites[1].attribute0 = COLOR_256 | SQUARE | ys;
sprites[1].attribute1 = SIZE_16 | xs;
sprites[1].attribute2 = char_number+(128); //bit map mode so the first 512 chars are not available each 64x64 sprite uses 128 tiles
////UPDATE: mode 0 - no more need to add 512 (3/18/03)

sprites[2].attribute0 = COLOR_256 | SQUARE | y4;
sprites[2].attribute1 = SIZE_32 | x4;
sprites[2].attribute2 = char_number+(128+64);

char_number_blue = char_number+(128+64);

//DEFINING NUMBER SPRITES

sprites[3].attribute0 = COLOR_256 | SQUARE | y+10;//0;
sprites[3].attribute1 = SIZE_32 | x+10;//0;
sprites[3].attribute2 = char_number+(128+128);

char_number_n0 = char_number+(128+128);
char_number_ntemp = char_number_n0;

sprites[4].attribute0 = COLOR_256 | SQUARE | 0;
sprites[4].attribute1 = SIZE_32 | 0;
sprites[4].attribute2 = char_number+(128+192);

char_number_n1 = char_number+(128+192);

sprites[5].attribute0 = COLOR_256 | SQUARE | 0;
sprites[5].attribute1 = SIZE_32 | 0;
sprites[5].attribute2 = char_number+(128+256);

char_number_n2 = char_number+(128+256);

sprites[6].attribute0 = COLOR_256 | SQUARE | 0;
sprites[6].attribute1 = SIZE_32 | 0;
sprites[6].attribute2 = char_number+(128+320);

char_number_n3 = char_number+(128+320);

sprites[7].attribute0 = COLOR_256 | SQUARE | 0;
sprites[7].attribute1 = SIZE_32 | 0;
sprites[7].attribute2 = char_number+(128+384);

char_number_n4 = char_number+(128+384);

sprites[8].attribute0 = COLOR_256 | SQUARE | 0;
sprites[8].attribute1 = SIZE_32 | 0;
sprites[8].attribute2 = char_number+(128+448);

char_number_n5 = char_number+(128+448);

sprites[9].attribute0 = COLOR_256 | SQUARE | 0;
sprites[9].attribute1 = SIZE_32 | 0;
sprites[9].attribute2 = char_number+(128+512);

char_number_n6 = char_number+(128+512);

sprites[10].attribute0 = COLOR_256 | SQUARE | 0;
sprites[10].attribute1 = SIZE_32 | 0;
sprites[10].attribute2 = char_number+(128+576);

char_number_n7 = char_number+(128+576);

sprites[11].attribute0 = COLOR_256 | SQUARE | 0;
sprites[11].attribute1 = SIZE_32 | 0;
sprites[11].attribute2 = char_number+(128+640);

char_number_n8 = char_number+(128+640);

sprites[12].attribute0 = COLOR_256 | SQUARE | 0;
sprites[12].attribute1 = SIZE_32 | 0;
sprites[12].attribute2 = char_number+(128+704);

char_number_n9 = char_number+(128+704);

//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*4; index++)
{
OAMData[index] = SPRITE1Data[index]; //copy it starting 512 tiles into oamdata mem. remember one tile = 32bytes and OAMdata is 16 bit pointer so offset is 512*16
//UPDATE: 512 tile offset no longer needed
//Mar 20 2003
}//end index loop
for(index =0 ; index <256*2 ; index++)
{
OAMData[index+256*8] = SPRITE2Data[index];

}//end index loop
for(index = 0; index < 256*4; index++)
{
OAMData[index+256*12] = SPRITE4Data[index];
}

//inserting number sprites to OAM
for(index = 0; index < 256*4; index++)
{
OAMData[index+256*16] = NUMBER0Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*20] = NUMBER1Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*24] = NUMBER2Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*28] = NUMBER3Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*32] = NUMBER4Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*36] = NUMBER5Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*40] = NUMBER6Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*44] = NUMBER7Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*48] = NUMBER8Data[index];
}

for(index = 0; index < 256*4; index++)
{
OAMData[index+256*52] = NUMBER9Data[index];
}

while(1)
{
while(!(REG_DISPSTAT & 1));//wait for vblank to start
GetInput(); //get input changes the x and y based on input
MoveSprite(&sprites[0],x,y); //changes sprite atributes based on new x,y
MoveSprite(&sprites[1],xs,ys);
MoveSprite(&sprites[2],x4,y4);
REG_BG0VOFS = y ;
REG_BG0HOFS = x ;
while((REG_DISPSTAT & 1));//wait for vblank to end
WaitForVsync(); //waits for the screen to stop drawing
CopyOAM(); //Copies our sprite array into OAM.
}
}

//end of entry point





My code, in living color. This time I am very interested - feedback? Criticism? Shock? Horror? Let me know! I am very stuck and hoping for illumination. Help!

Thanks for your time, and for your laughs, I need 'em...
-slippers2k
God bless you


[edited by - slippers2k on March 25, 2003 11:44:39 PM]

[edited by - slippers2k on March 26, 2003 11:36:17 PM]

Share this post


Link to post
Share on other sites
PLEASE USE CODE TAGS! That''s a bit of a mess to see there.

Well...

I really don''t mean to be cruel here... but it seems to me you could use some advice on general coding etiquette. Here''s a few pointers on things that''ll make that code a lot neater, free up a lot of memory, and make it a lot more pleasant for other people to look through.

1) Don''t use so many variables! For one, structures or classes might help clean things up. As in, don''t just have int player_x and int player_y, and then NPC_x, NPC_y.... and all that. Do this:

typedef struct object{
s16 x, y; // store x and y position
};

object player;
object npc;
object ball;

Also, you''re using a lot of variables for things that don''t really need them. Like character numbers, for instance. You should notice there''s a distinct pattern in how the character numbers change from sprite to sprite, and you can simply use that when you need it. As an example, assume all your sprites are 32x32, 156 color. When you loop through to write all the image data in, all you need to do is have a for loop with ONE variable to track character numbers. Every iteration, just increment it by 32. So what if all your sprites aren''t the same size? They should be grouped together anyway. Meaning you may know that sprites 0-5 are 32x32, and after that they''re something else. That can still be accounted for easily enough. And say there really is no pattern in the character numbers. You still have no reason to store variables, because the character numbers are already being held in attribute2. The first 10 bits of attribute2. That means, to get at the character number, all you need to do is this: character_number = sprite[number].attribute2&0x3FF;

Also... There''s no need to store variables specifically for the collision detection like you did. You know the size of the sprites won''t change, so given one point, you can always find the other three. You have the upper left, so the upper right is ALWAYS y+width. And so on. You don''t need variables for that, and it actually simplifies the code to avoid them. All you need to do is generate those values when you test for collision, because you''ll never need them otherwise. Basically put, you have a lot of global variables that really should be local.

2) Whenever you repeat similar actions a number of times... It cleans things up to put it in a for loop. Like when you fill in all the data for your sprites. Instead of saying:

sprites[1].attribute0 = COLOR_256 | SQUARE | ys;
sprites[1].attribute1 = SIZE_16 | xs;
sprites[1].attribute2 = char_number+(128);
sprites[2].attribute0 = COLOR_256 | SQUARE | y4;
sprites[2].attribute1 = SIZE_32 | x4;
sprites[2].attribute2 = char_number+(128+64);

char_number_blue = char_number+(128+64);

... ad infinitum...

just do this:

u16 character_number = 0;
for (int loop = 0; loop < however_many_needed; loop++)
sprites[1].attribute0 = COLOR_256 | SQUARE | y;
sprites[1].attribute1 = SIZE_16 | x;
sprites[1].attribute2 = character_number;
character_number += 64;
}

Now, you may be saying that gee... You don''t always put the same values in for every sprite. That can still be arranged. Just look for a pattern in the values. More often than not, they''ll be there.

3) Use more DMA copies. There are a number of areas where you do straight memory copies using for loops. While it''s not a crime for one time loads like there, it''s not a good habit to get into. Plotting the pixels for the image data on the splash screen as well as loading the map are good areas to use DMA instead.

4) I think you''re running a little high with your character numbers. Looking at where you initialize all your number sprites and all that... setting their attributes and such... Looking through it quickly it seems to me that there''s no reason you should be getting numbers that high. Think about it: Each 32x32 sprite is 4 8x8 blocks wide, and 4 tall. That means they''re composed of 16 blocks. Because they''re 256 color, though, they take up twice as much space. So that means you need 32 blocks for each sprite. With 13 sprites, you should have no need to give any sprite a character number over 384.

5) In your MoveSprite function... You have very unnecessary multiplies, which are very slow. Instead of direction_x *= -1; just do direction_x = -direction_x; As far as the movesprite function goes though... it makes absolutely no sense to me why you have the tennis ball collision detection in there. Particularly considering it''s called three times each pass through the main loop. Stick that in another function, and make sure its only called once each time.

Sorry... I didn''t see anything the looked to me like it would contribute to not being able to move sprite 0. I have to admit I was a little less than inclined to dig through all of that code. I''d be happy to take another look at it... but please try to clean some of that up first. Sorry i can''t solve your problem... at least i don''t think so.

-Arek the Absolute

Share this post


Link to post
Share on other sites