Nintendo DS


Introduction


Version History

Day 1
Environment Setup

Links

WiFiMe

PA_Lib

Linux

Emulators

Downloads

Demos




NDS Magic Key MK2/MK3

   Hosted by
FrogNet


Document made with Nvu

 

Nintendo DS Development Tutorial :: Day 6 :: Sprites 2

 

Okay, don't panic if today's tutorial looks a little overwhelming at first.  It's not really as complicated as it might seem.  Here are some of the things we'll be doing today.  

  • This will be our first example of using a background image and a sprite on the screen at the same time.  You may not realize that the sprite is "on top" of the background so I'll explain why this is happening below.

  • There will be quite a few more variables than in anything we've done up to this point, but they should all make sense.  There's even a function prototype in this one!  You better get used to them (functions), otherwise your code will become very confusing very quickly.

  • The image we'll load for the sprite actually contains eight different "frames" for the plane - one for each direction it can face.  Click here to see what I mean.  Looking at that bitmap of the plane, you may notice that the background color is black and that you don't see that color when the plane is drawn on the screen.  I'll explain why in just a moment.

  • Then we'll throw in a couple of sprite-related PA_Lib functions that you'll soon find you can't live without.

 

// Includes
#include <PA9.h> // Include for PA_Lib
// Graphics Includes
// --- Backgrounds ---
// gfx2gba -fsrc -m -pBackground.pal -t8 Background.bmp
#include "gfx/Background.map.c"
#include "gfx/Background.pal.c"
#include "gfx/Background.raw.c"

// --- Sprites ---
// gfx2gba -D -fsrc -pred_plane_anim.pal -t8 red_plane_anim.bmp
#include "gfx/Red_plane_anim.pal.c"
#include "gfx/Red_plane_anim.raw.c"

// Defines
#define ANIM_UP 0
#define ANIM_UPRIGHT 1
#define ANIM_RIGHT 2
#define ANIM_DOWNRIGHT 3
#define ANIM_DOWN 4
#define ANIM_DOWNLEFT 5
#define ANIM_LEFT 6
#define ANIM_UPLEFT 7

// Global Variables
u8 dir_plane = ANIM_RIGHT; // Direction the plane is facing
u8 plane; // Sprite object number of the plane
u8 plane_x = 98; // X position of the plane
u8 plane_y = 64; // Y position of the plane

// Function Prototypes
void query_buttons(); // Query for user input


// Function: main()
int main(int argc, char ** argv)
{
PA_Init(); // Initializes PA_Lib
PA_InitVBL(); // Initializes a standard VBL

//PA_LoadSplash(); // PA_Lib splash screen

// Load Palettes
PA_LoadPal(PAL_BG0, Background_Palette);
PA_LoadPal(PAL_SPRITE0, Red_plane_anim_Palette);

// Load Background
PA_LoadSimpleBg(0, 3, Background_Tiles, Background_Map,
BG_256X256, 0, 1);

// Create Sprite
PA_CreateSprite(0,0,(void*)&Red_plane_anim_Bitmap[4096*dir_plane],
OBJ_SIZE_64X64,1,0,plane_x,plane_y);

// Infinite loop to keep the program running
while (1)
{
// Query for user input
query_buttons();

// Update Sprite Graphics
PA_UpdateSpriteGfx(0, 0,
(
void*)&Red_plane_anim_Bitmap[4096*dir_plane]);

// Update Sprite Position
PA_SetSpriteXY(0,0,plane_x,plane_y);

PA_WaitForVBL();
}

return 0;
} // End of main()


//******************************
// Function: query_buttons()
// Purpose: Query for user input
//******************************
void query_buttons()
{
// Check for button press
PA_UpdatePad();

// UP only
if(Pad.Held.Up
&& !Pad.Held.Right
&& !Pad.Held.Left)
{
if (plane_y > 0) plane_y--;
dir_plane = ANIM_UP;
return;
}

// UP + RIGHT
if(Pad.Held.Up
&& Pad.Held.Right)
{
if (plane_y > 0) plane_y--;
if (plane_x < 192) plane_x++;
dir_plane = ANIM_UPRIGHT;
return;
}

// RIGHT only
if(Pad.Held.Right
&& !Pad.Held.Up
&& !Pad.Held.Down)
{
if (plane_x < 192) plane_x++;
dir_plane = ANIM_RIGHT;
return;
}

// DOWN + RIGHT
if(Pad.Held.Down
&& Pad.Held.Right)
{
if (plane_y < 128) plane_y++;
if (plane_x < 192) plane_x++;
dir_plane = ANIM_DOWNRIGHT;
return;
}

// DOWN only
if(Pad.Held.Down
&& !Pad.Held.Right
&& !Pad.Held.Left)
{
if (plane_y < 128) plane_y++;
dir_plane = ANIM_DOWN;
return;
}

// DOWN + LEFT
if(Pad.Held.Down
&& Pad.Held.Left)
{
if (plane_y < 128) plane_y++;
if (plane_x > 0) plane_x--;
dir_plane = ANIM_DOWNLEFT;
return;
}

// LEFT only
if(Pad.Held.Left
&& !Pad.Held.Up
&& !Pad.Held.Down)
{
if (plane_x > 0) plane_x--;
dir_plane = ANIM_LEFT;
return;
}

// UP + LEFT
if(Pad.Held.Up
&& Pad.Held.Left)
{
if (plane_y > 0) plane_y--;
if (plane_x > 0) plane_x--;
dir_plane = ANIM_UPLEFT;
return;
}

return;
} // End of query_buttons()

 

Code Explanation

// Defines
I don't really want to go into C/C++ very much, so if you don't know what these are, check out this site.  I use them because it's easier to use ANIM_RIGHT than to remember that right equals 2 (etc) in this demo.

The main point is that you understand each direction matches up to a frame in the image used for the plane sprite.  Also keep in mind that the plane sprite is 64x64 pixels which becomes 4096 array spots per frame.  You may want to take a quick peek at gfx\Red_plane_anim.raw.c.

Okay, so let's dissect Red_plane_anim_Bitmap[4096*dir_plane] real quick.  If dir_plane = ANIM_RIGHT (which equals 2) that means 4096*2 which equals 8192.  This leads me to...

PA_CreateSprite(...);
Notice that I passed the array as (void*)&Red_plane_anim_Bitmap[4096*dir_plane] - there was no & used in Day 3.  That's because I need to pass it a pointer to the address of the 8192nd slot in the array (and not the value, whatever that may be).  See Arrays as parameters on this page for more info.  You'll also note that I used OBJ_SIZE_64X64 (instead of 32X32) because the plane is a 64x64 pixel sprite.

Remember how I mentioned that the plane sprite has a black background but you don't see it when it's drawn to the screen?  That's because the first color in the palette is the transparency or alpha color.  That means that any slot in the graphic array whose color matches the alpha color does not get drawn to the screen.  In this case the color was black though it is often pink.

PA_UpdateSpriteGfx(...);
This is another relatively easy-to-understand PA_Lib function.  Once the user press a direction, the sprite needs to be moved (see PA_SetSpriteXY() below) and the sprite graphic needs to be updated.

PA_SetSpriteXY(...);
The parameters the screen (0 or 1), the sprite number (0-127), and the X & Y co-ordinate (of course).

query_buttons();
Once every VBL we check to see if the user has pressed any buttons (though we only care about the directional pad for this demo).  If he has, then we have to move the plane (if it's not at the edge of the screen) and change the direction to match.

That's it!  I hope that wasn't too overwhelming, but if you think about it, we didn't really do too much this time around.

 

Download

Day6_Sprites_2

 

Screenshot

Day1_Hello_World

 

Last Update: 10/31/2005

 

Google
 
Web aaronrogers.com/nintendods

 

<<

HOME

>>