(A03) Document Sprite OAM attributes.
(A03) Document 1D vs. 2D sprites.
| Sprite Example #1 -- Simple 16 Color Sprites | Most basic example. Presents the minimum amount of code with relationship to activating registers to present sprites on the screen. Supports basic user input. |
| sprite02 | |
Start by copying the template directory to sprite01 for this example.
cd ~/ds_projects cp -R template sprite01
The Sprite.
Now, generate the LetA.h and LetA.c files by running the "Python-Fu/NDS/Create Sprites" script from the image manu. A dialog is displayed prompting for information about the sprite being created. Specify the output .c/.h file as ../arm9/LetA. Depending on the current directory for gimp, specify the path to the arm9 directory. In the screenshot below, gimp was run from the sprite01/graphics directory. Next, select the sprite size as 16x16. Set the palette to use as "Use Specified" and then place "NDS Text" in the palette name area. Finally, specify to generate 16 color tiles.
CreateSprites Dialog
The main function for the sprite01 application is exceedingly simple.
int main(int argc, char** argv) { Tutorial01Sprite& app(Tutorial01Sprite::theApp()); app.go(); return 0; }
The constructor for Tutorial01Sprite starts by clearing all of the palettes by setting all colors to black.
Tutorial01Sprite::Tutorial01Sprite()
{
unsigned int i;
for(i = 0; i < 0x200; ++i) {
BG_PALETTE[i]=0;
SPRITE_PALETTE[i] = 0;
BG_PALETTE_SUB[i]=0;
SPRITE_PALETTE_SUB[i] = 0;
}
Next, it turns on the screens, enabling VRAMs A and C, and sets the display for use with Mode 0.
VRAM_A is associated with the touch screen and is the sprite video memory. VRAM_C is associated with the top display and is the sprite video memory for that screen.
// Turn on the screens and 2D cores and switch to mode 0
POWER_CR = POWER_ALL_2D;
vramSetBankA(VRAM_A_MAIN_SPRITE);
vramSetBankD(VRAM_D_SUB_SPRITE);
DISPLAY_CR = MODE_0_2D | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D_LAYOUT;
SUB_DISPLAY_CR = MODE_0_2D | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D_LAYOUT;
The call to initOAM initializes our copy of the OAM memory (both the touch screen and the top screen) to values that cause none of the sprites to be visible. This disabling of the sprites is accomplished by using the ATTR0_DISABLED define.
//Turn off all of the sprites in OAM.
initOAM();
Next, the sprites are initialized. An entry in the application copy of OAM memory is assigned to a sprite in the oam member variable. Next, the x and y location of the sprite is set. Finally, the gfxID indicates the position of the first tile of the sprite in the sprite graphics memory. Later, the MoveSprite command will use these values to set the copy of OAM memory to correct values in preparation for moving the copy of OAM memory into the actual OAM memory.
//init our sprites.
letA.oam = &OAMCopy[0];
letA.x = 50;
letA.y = 50;
letA.gfxID = 0;
letASub.oam = &OAMSubCopy[0];
letASub.x = 50;
letASub.y = 50;
letASub.gfxID = 0;
Now the sprite must be described. Here, the sprite is specified as a 16 color sprite and noted that the sprite is a square. The next attribute speicifes the size of the sprite as 16 pixels. So at this point, the application has specified that the sprite is a 16 color 16x16 pixel sprite. Finally, the application specifies which graphic image is associated with the sprite. The same graphic image can be used by many sprites in many positions.
//set up our sprites OAM entry attributes.
letA.oam->attribute[0] = ATTR0_COLOR_16 | ATTR0_SQUARE;
letA.oam->attribute[1] = ATTR1_SIZE_16;
letA.oam->attribute[2] = letA.gfxID;
letASub.oam->attribute[0] = ATTR0_COLOR_16 | ATTR0_SQUARE;
letASub.oam->attribute[1] = ATTR1_SIZE_16;
letASub.oam->attribute[2] = letA.gfxID;
Now the sprite palette is moved into the sprite palette memory. While it is not required in general, the application specifies that the letter should be drawn on the screen in a green color rather than leaving the color as black.
//copy in the sprite palettes for(i = 0; i < sizeof(LetAPalette) / sizeof(uint16); ++i) { SPRITE_PALETTE[i] = LetAPalette[i]; SPRITE_PALETTE_SUB[i] = LetAPalette[i]; } SPRITE_PALETTE[1] = RGB15(0, 31, 0); SPRITE_PALETTE_SUB[1] = RGB15(0, 31, 0);
Finally the sprite graphics are loaded into memory.
//copy the sprite grahics in obj graphics mem for(i = 0; i < sizeof(LetAData) / sizeof(uint16); i++) { SPRITE_GFX[letA.gfxID * 16 + i] = LetAData[i]; SPRITE_GFX_SUB[letA.gfxID * 16 + i] = LetAData[i]; }
And lastly, the interrupt handler is initialized and configured.
// Enable the V-blank interrupt
IME = 0;
IRQ_HANDLER = &InterruptHandler;
IE = IRQ_VBLANK;
IF = ~0;
DISP_SR = DISP_VBLANK_IRQ;
IME = 1;
}
The Tutorial01Sprite::theApp method simplay returns a reference to the one and only Tutorial01Sprite object for the application.
Tutorial01Sprite& Tutorial01Sprite::theApp(void) { static Tutorial01Sprite app; return app; }
The Tutorial01Sprite::go method invokes MoveSprite, which updates the application copy of OAM memory, setting the attributes correctly so that the sprite will appear at the appropriate place on the screen. Finally, the application lets the interrupt handler take over processing for the application.
void Tutorial01Sprite::go(void) { MoveSprite(&letA); MoveSprite(&letASub); while (1) { swiWaitForVBlank(); }
1.3.6