synkro
0xdeadbeef
Code:
/*
* GP32 Tutorial 03 "Structure, Prototyping"
*
* Intro
* -----
* You are still there? I guess the last two tutos were to easy, huh? This
* time we have a big and difficult tuto but at its end you will have
* something to impress your mommy. If you are still willing to learn C/C++
* for GP32 or in general I advise you to get a C/C++ textbook for beginners.
* This tuto is really hard, I don't knwo what I was think while writing this
* one. Feel free to skip this!
*
* I can take it!
* -------------
* 1. typedef struct
* Sometimes we need more than the standard types or arraye of them. We can
* compose a complex structure from different types/arrays. Here we define
* a type structure named tPARTICLES (the 't' stands for type). Every
* structure has different members, this one has four members, all of them
* are from the type int. We try to sombine data types that are logically
* connected. We can use this structure nearly like the other types.
*
* 2. void DrawParticles (void);
* Now we have arrived at a stage where our programs become so complex we
* should split our code into functions/procedures. Before you can
* implement and use them you have to prototype them. In this case we
* use two functions one to move and one to draw the particles on screen.
* The implementations of these functions are after the main function.
*
* 3. particles[i].x = rand() % WIDTH;
* We want to set every particle on a random position. To set the x
* position we take the specific particle 'particles[i]' and directly set
* the member '.x'. Note that the member of the structer is preceded by
* a '.'. The function rand() returns a random number, to make sure that
* that number is not bigger than the screen width, we use the '%' also
* known as modulo (I guess you heard about it at school). With '% WIDTH'
* we can assure that the random number is between 0 and WIDTH-1.
*
* 4. gp_SetPixel16(x, y, color, framebuffer);
* This SDK function sets a 16bit pixel at (x,y) on a framebuffer.
* We get the coordinates from every particle, draw them in the current
* framebuffer.
*
* So, you think learned enough to make your own particle animations? we
* will see. First try following exercises after re-typing the code:
* A) Change the color of the particles
* B) Add more particles
* C) Put the particles init in its own function called 'InitParticles'
*
* I want to thank everybody who helped in findig bugs and proofreading
* my bad English!
*
* Disclaimer
* ----------
* This Tutorial is based on Mr. Mirko's SDK (mirko@mirkoroller.de)
* download it at: http://home.t-online.de/home/mirkoroller/gp32/
* THIS TUTORIAL IS NOT WRITTEN BY MR. MIRKO! Parts of this Tutorial
* are from the SDK's examples or manual.
*
* SDK by Mr. Mirko mirko@mirkoroller.de
* Tutorial by synkro synkro@gmx.net
* 26.04.2004 14:26:39
*/
#include <gp32.h>
#include <stdlib.h>
// This is the C Standard Lib. We will need this for random numbers
// later on. We use the function rand() that returns a random number.
// Before we can use that function we have to "plant" a random seed.
#define MAX_PARTICLES 100 // Maximum count of particles
#define WIDTH 320
#define HEIGHT 240
#define FLIP_BUFFER \
gp_SetView(framebuffer[nflip++]); \
nflip &= 0x01;
// You alread know how to use #define for often used values but
// here we defined a whole macro. The compiler will expand FLIP_BUFFER
// with the following two commands. We use that macro to flip between
// the two framebuffers. '&' is the bitwise AND operator so we assure that
// nflip is 0 or 1 after we increased it.
int nflip = 0; // This variable determines the current buffer
unsigned short *framebuffer[2]; // Instead of two pointers we declare
// an array of them.
typedef struct
{
int x, y; // Position of the particel (x,y)
int velocity_x, velocity_y; // Particle velocity on x- and y-axis
}tPARTICLE; // the name of the struct, you don't have to set a preceding 't'
tPARTICLE particles[MAX_PARTICLES];
// This allocates an array of 100 tPARTICLES named particles.
void DrawParticles (void);
void MoveParticles (void);
// Here are the needed prototypes of the functions we want to use later.
/*
* This is the main function
*/
int main(void)
{
int i;
framebuffer[0] = (unsigned short*) FRAMEBUFFER;
framebuffer[1] = (unsigned short*) (FRAMEBUFFER + (WIDTH*HEIGHT*2));
gp_SetScreen(framebuffer[1], 16);
// Clear both buffer white
for (i=0; i<WIDTH*HEIGHT; i++)
{
framebuffer[0][i] = 0xFFFF;
framebuffer[1][i] = 0xFFFF;
}
gp_SetCpuSpeed(66);
srand(1337);
// You can take any number as seed, but keep in mind
// that these are still pseudo random numbers.
for (i=0; i<MAX_PARTICLES; i++)
{
// The particles get a random positrion on the screen
particles[i].x = rand() % WIDTH;
particles[i].y = rand() % HEIGHT;
if ((rand() % 2) == 0) // (rand() % 2) will be 1 or 0
particles[i].velocity_x = -(rand() % 3) + 1;
// if the condition is true the x velocity will be negative
else
particles[i].velocity_x = (rand() % 3) + 1;
// else x velocity will be positive
if ((rand() % 2) == 0)
particles[i].velocity_y = -(rand() % 3) + 1;
else
particles[i].velocity_y = (rand() % 3) + 1;
// Here we do the same for the y velocity.
}
// This inits all particles with a random position and velocity
while (1)
{
for (i=0; i<WIDTH*HEIGHT; i++)
framebuffer[nflip][i] = 0x0000;
// Clear the screen black before we draw the particles.
MoveParticles();
DrawParticles();
FLIP_BUFFER
for (i=0; i<500000; i++) i=i;
// No flip the working framebuffer with the current framebuffer
// on screen. This creates the animation of the particles moving
// around on the screen.
}
}
/*
* This function draws the particles on the screen
*/
void DrawParticles (void)
{
int i;
for (i=0; i<MAX_PARTICLES; i++)
gp_SetPixel16(particles[i].x, particles[i].y, 0xFFFF, framebuffer[nflip]);
// We draw all particles in white on the current working framebuffer.
}
/*
* This function moves the particles and deletes them
* if they are leaving the screen.
*/
void MoveParticles (void)
{
int i;
for (i=0; i<MAX_PARTICLES; i++)
{
particles[i].x += particles[i].velocity_x;
if (particles[i].x >= WIDTH) // Leaving the screen left
particles[i].x -= WIDTH; // Reset x coordinate
if (particles[i].x <= 0) // Leaving the screen right
particles[i].x += WIDTH; // Reset y coordinate
particles[i].y += particles[i].velocity_y;
if (particles[i].y >= HEIGHT) // Leaving the screen top
particles[i].y -= HEIGHT; // Reset y coordinate
if (particles[i].y <= 0) // Leaving the screen bottom
particles[i].y += HEIGHT; // Reset y coordinate
}
}