// Includes #include <PA9.h> // Include for PA_Lib
// Graphics Includes // *** Backgrounds *** // gfx2gba -fsrc -m -pBackgrounds.pal -t8 BG*.bmp #include "gfx/BG1.map.c" #include "gfx/BG1.raw.c" #include "gfx/BG2.map.c" #include "gfx/BG2.raw.c" #include "gfx/BG3.map.c" #include "gfx/BG3.raw.c" #include "gfx/Backgrounds.pal.c" // *** Sprites *** // gfx2gba -D -fsrc -pSprites.pal -t8 Cloud.bmp #include "gfx/SpaceShipAnim.raw.c" #include "gfx/Sprites.pal.c"
// Global Variables u8 Curr_Frame = 0; // Used to animate the spaceship s16 Ship_X = 96; // Spaceship's X coordinate s16 Ship_Y = 128; // Spaceship's Y coordinate u32 vbl_count = 0; // Used to keep track of VBLs s16 scroll = 0; // Amount of parallax scroll
// Function Prototypes void Scroll_Backgrounds(); void Update_Sprite_Location(); void Update_Sprite_Frame();
// 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, Backgrounds_Palette); // Backgrounds PA_LoadPal(PAL_BG1, Backgrounds_Palette); // Backgrounds PA_LoadPal(PAL_SPRITE0, Sprites_Palette); // Sprites
// Load Backgrounds PA_LoadSimpleBg(0, 3, BG3_Tiles, BG3_Map, BG_256X256, 0, 1); PA_LoadSimpleBg(0, 2, BG2_Tiles, BG2_Map, BG_256X256, 0, 1); PA_LoadSimpleBg(0, 1, BG1_Tiles, BG1_Map, BG_256X256, 0, 1); PA_LoadSimpleBg(1, 3, BG3_Tiles, BG3_Map, BG_256X256, 0, 1); PA_LoadSimpleBg(1, 2, BG2_Tiles, BG2_Map, BG_256X256, 0, 1); PA_LoadSimpleBg(1, 1, BG1_Tiles, BG1_Map, BG_256X256, 0, 1);
// Setup vertical parallax scrolling for backgrounds PA_InitParallaxY(0, 0, 256, 192, 128); PA_InitParallaxY(1, 0, 256, 192, 128);
// Load Sprite PA_CreateSpriteEx(0,0,(void*)&SpaceShipAnim_Bitmap[4096*Curr_Frame], OBJ_SIZE_64X64,1,0,0,0,0,0,1,0,Ship_X,Ship_Y);
// Infinite loop to keep the program running while (1) { ++vbl_count; // Increase VBL Counter
Scroll_Backgrounds(); // Parallax scroll BGs Update_Sprite_Location(); // Move sprite based on input
// Change the sprite frame every 3 VBLs if (vbl_count%3==0) Update_Sprite_Frame();
PA_WaitForVBL(); }
return 0; } // End of main()
void Scroll_Backgrounds() { // Increment scroll amount (scroll < 512) ? ++scroll : scroll=0;
// Vertically scroll backgrounds PA_ParallaxScrollY(0, -scroll); PA_ParallaxScrollY(1, -scroll);
return; } // End of Scroll_Backgrounds()
void Update_Sprite_Frame() { // Increment the current frame counter (Curr_Frame < 3) ? ++Curr_Frame : Curr_Frame = 0;
// Update sprite graphics PA_UpdateSpriteGfx(0,0,(void*)&SpaceShipAnim_Bitmap[4096*Curr_Frame]);
return; } // End of Update_Sprite_Frame()
void Update_Sprite_Location() { // Check for button press PA_UpdatePad();
// Move sprite based on input if ((Ship_X >= -8) && Pad.Held.Left) Ship_X -= 2; if ((Ship_X <= 200) && Pad.Held.Right) Ship_X += 2; if ((Ship_Y >= -8) && Pad.Held.Up) Ship_Y -= 2; if ((Ship_Y <= 130) && Pad.Held.Down) Ship_Y +=2;
// Update Sprite Position PA_SetSpriteXY(0,0,Ship_X,Ship_Y);
return; } // End of Update_Sprite_Location()
|
|
Code
Explanation
Pretty much everything up to the while()
statement should be familiar, or should make sense without explanation.
There are a few things to note, however.
First, I decided to use the same backgrounds images on both screens.
If you look carefully enough, you'll realize that the backgrounds
you see on both screens are exactly the same - even the parallax
scrolling effect.
Second, in Day 6's tutorial, I was able to use a standard 256x256
background with only 256x192 viewable pixels. Why? Because
that is how big the Nintendo DS' screen is and there are no extra pixels on the left
or right side of the image to worry about when scrolling horizontally.
For today's tutorial, I chose to use the full 256x256 pixels for
each background. Why? Because when you scroll an image
vertically, there is that extra space at the bottom that is normally
not used (and pink in color in my examples). Take a look at the
bitmaps included with any of the previous tutorials if you don't know
what I mean. You could probably figure out a way to do vertical
scrolling with 256x192 viewable pixels, but this way is so easy, why
bother?
if (vbl_count%3==0) Update_Sprite_Frame();
Let me explain this just in case you are not familiar with the modulus operator. % means the remainder when dividing. So, this statement means when vbl_count divided by 3 has no remainder, or every three VBLs.
You'll notice that I broke the main parts of today's code into three
functions. As I mentioned in Day 6, this makes looking at code -
and figuring it out - much easier.
Scroll_Backgrounds()
This code is very similar to what was done in Day 7. In fact, I
simply copied and pasted that code here and made only a few changes.
The main difference is that I am using a negative number for the
scrolling so that the backgrounds would scroll from
top to bottom. If you used positive numbers, they would
scroll from bottom to top instead - which is totally weird for a
spaceship game!
Update_Sprite_Frame()
(Curr_Frame < 3) ? ++Curr_Frame : Curr_Frame = 0;
If you take a look at SpaceShipAnim.bmp,
you'll see that it consists of four frames of a spaceship image that
all look very similar. In fact, the only difference you'll see is
the lights on the front of the wings and the flames at the back of the
ship. That's okay, though, because there is just enough difference
to show you how to animate a sprite. Oh, and the frame counter
goes from 0 to 3 and gets multiplied by 4096 (64x64 pixels) just like
in Day 6.
You'll notice that this function gets called every 3 VBLs. If you
call it any more often, the sprite animations get so fast that you can
hardly notice them.
Update_Sprite_Location()
Again, this is almost exactly the same as Day 6 except that I threw a
bunch of weird numbers in the if statements. The spaceship sprite
does not take up a full 64x64 pixels, so I had to increase the
allowable bounds for moving the ship around the screen. For
example, there are about 8 pixels on the left and right-hand side of
the ship that are not viewable so the X coordinate can actually be
allowed to move from -8 to 200.
Well, that's about it for today. Now you know how to parallax
scroll backgrounds horizontally (Day 7) and vertically (Day 9) and
animate sprites based on user input (Day 6) and without input (Day 9).
At this point you may want to take a little break and write your own
little demo. Then you can come back and learn some other neat
tricks to add to it!
|