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

|
|
|
|
Last Update: 10/31/2005
|
|
|
|
|
|
|
|
|
|