GRRLIB/examples/xane02/source/main.cpp

287 lines
7.4 KiB
C++

/*===========================================
GRRLIB (GX Version)
Example code by Xane
This example shows a basic particle
engine creating a Smokebomb.
============================================*/
#include <grrlib.h>
#include <stdlib.h>
#include <wiiuse/wpad.h>
#include <math.h>
#include <ogc/lwp_watchdog.h>
#include <vector>
// Include Graphics
#include "GFX/RGFX_Background.h"
#include "GFX/RGFX_Crosshair.h"
#include "GFX/RGFX_Smoke.h"
#include "GFX/RGFX_Font.h"
// Define Effects
#define EFFECT_SMOKEBOMB 1
// Random Number (0 - 1) in float
#define RANDOM ((((float)(rand() % 12))/12)-0.5)
using std::vector;
Mtx GXmodelView2D;
// Basic structure to hold particle data
typedef struct Particle {
u8 id;
float x, y;
float sx, sy;
u16 rot;
u8 frame, framecnt, framedelay;
u8 red, green, blue;
float scale, alpha;
float sscale, salpha;
float scolor;
GRRLIB_texImg *tex;
} Particle;
// Vector used as a container to iterate through all members of GRRLIB_texImg
static vector<GRRLIB_texImg *> TextureList;
static vector<Particle *> ParticleList;
static vector<Particle *> ParticleListTmp;
// Declare static functions
static void ExitGame();
static void createEffect( u8 id, int _x, int _y );
static void createParticle( u8 _id, int _x, int _y, float _scale, float _alpha, u8 _red, u8 _green, u8 _blue );
static bool updateParticle( Particle *part );
static u8 CalculateFrameRate();
// Initialize general variables
extern GXRModeObj *rmode;
ir_t P1Mote;
short WinW;
short WinH;
int P1MX, P1MY;
// Prepare Graphics
GRRLIB_texImg *GFX_Background;
GRRLIB_texImg *GFX_Crosshair;
GRRLIB_texImg *GFX_Smoke;
GRRLIB_texImg *GFX_Font;
int main() {
u32 WPADKeyDown;
u32 WPADKeyHeld;
u8 FPS = 0;
u32 ParticleCnt = 0;
// Init GRRLIB & WiiUse
GRRLIB_Init();
WinW = rmode->fbWidth;
WinH = rmode->efbHeight;
WPAD_Init();
WPAD_SetIdleTimeout( 60*10 );
WPAD_SetDataFormat( WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR );
// Load textures
GFX_Background = GRRLIB_LoadTextureJPG(RGFX_Background);
GFX_Crosshair = GRRLIB_LoadTexturePNG(RGFX_Crosshair);
GFX_Smoke = GRRLIB_LoadTexturePNG(RGFX_Smoke);
GFX_Font = GRRLIB_LoadTexturePNG(RGFX_Font);
GRRLIB_InitTileSet( GFX_Font, 8, 16, 32 );
// Set handles
GRRLIB_SetMidHandle( GFX_Crosshair, true );
GRRLIB_SetMidHandle( GFX_Smoke, true );
// Feed the vector with the textures
TextureList.push_back( GFX_Background );
TextureList.push_back( GFX_Crosshair );
TextureList.push_back( GFX_Smoke );
TextureList.push_back( GFX_Font );
while (true) {
WPAD_ScanPads();
WPADKeyDown = WPAD_ButtonsDown(WPAD_CHAN_0);
WPADKeyHeld = WPAD_ButtonsHeld(WPAD_CHAN_0);
WPAD_SetVRes(WPAD_CHAN_0, WinW, WinH);
WPAD_IR(WPAD_CHAN_0, &P1Mote);
// Resetting Vars
GRRLIB_SetBlend( GRRLIB_BLEND_ALPHA );
ParticleCnt = 0;
// WiiMote IR Viewport correction
P1MX = P1Mote.sx - 150;
P1MY = P1Mote.sy - 150;
// Drawing Background
GRRLIB_DrawImg( 0, 0, GFX_Background, 0, 1, 1, RGBA(255, 255, 255, 255) );
// Add any pending objects into the main container
if (ParticleListTmp.size()) {
for(u32 i = 0; i<ParticleListTmp.size();i++) {
ParticleList.push_back(ParticleListTmp[i]);
}
ParticleListTmp.clear();
}
// Update and draw all particles
for (vector<Particle *>::iterator PartIter = ParticleList.begin(); PartIter != ParticleList.end();) {
if (updateParticle((*PartIter)) == true) {
GRRLIB_DrawImg( (*PartIter)->x, (*PartIter)->y, (*PartIter)->tex, (*PartIter)->rot, (*PartIter)->scale, (*PartIter)->scale, RGBA( (*PartIter)->red, (*PartIter)->green, (*PartIter)->blue, GRRLIB_ClampVar8((*PartIter)->alpha*255) ) );
} else {
free( (*PartIter) );
ParticleList.erase(PartIter);
continue;
}
ParticleCnt += 1;
PartIter++;
}
// Draw Crosshair
GRRLIB_DrawImg( P1MX, P1MY, GFX_Crosshair, 0, 1, 1, RGBA(255, 255, 255, 255) );
// Draw Text
GRRLIB_Rectangle( 28, 28, 280, 20, RGBA(0, 0, 0, 160), 1 );
GRRLIB_Printf ( 32, 32, GFX_Font, 0xFFFFFFFF, 1, "Point your WiiMote on the screen." );
GRRLIB_Rectangle( 28, 48, 200, 16, RGBA(0, 0, 0, 160), 1 );
GRRLIB_Printf ( 32, 48, GFX_Font, 0xFFFFFFFF, 1, "Number of Particle: %d", ParticleCnt );
GRRLIB_Rectangle( 28, 64, 64, 16, RGBA(0, 0, 0, 160), 1 );
GRRLIB_Printf ( 32, 64, GFX_Font, 0xFFFFFFFF, 1, "FPS: %d", FPS );
// Renders the Scene
GRRLIB_Render();
FPS = CalculateFrameRate();
if (WPADKeyDown & WPAD_BUTTON_B) {
createEffect( EFFECT_SMOKEBOMB, P1MX, P1MY );
}
if (WPADKeyDown & WPAD_BUTTON_HOME) {
ExitGame();
}
}
ExitGame();
return 0;
}
static void createEffect( u8 id, int _x, int _y ) {
u8 _ColorAdd = 0;
switch (id) {
case EFFECT_SMOKEBOMB:
for (u8 i = 0; i < 5; i++) {
createParticle( 1, (_x + (RANDOM * 10)), (_y + (RANDOM * 10)), (1.4f+(RANDOM*0.20)), 1.0f, 64, 64, 64 );
}
for (u8 i = 0; i < 20; i++) {
createParticle( 3, (_x + (RANDOM * 50)), (_y + (RANDOM * 50)), 1.25f, 1.5f, 92, 92, 92 );
}
for (u8 i = 0; i < 5; i++) {
_ColorAdd = (RANDOM*75);
createParticle( 2, (_x + (RANDOM * 40)), (_y + (RANDOM * 40)), (1.0f+(RANDOM*0.20)), 1.0f, 128+_ColorAdd, 128+_ColorAdd, 128+_ColorAdd );
}
break;
}
}
static void createParticle( u8 _id, int _x, int _y, float _scale, float _alpha, u8 _red, u8 _green, u8 _blue ) {
Particle *part = (struct Particle *)calloc(1, sizeof(Particle));
part->id = _id;
part->x = _x;
part->y = _y;
part->rot = rand() % 360;
part->red = _red;
part->green = _green;
part->blue = _blue;
part->scale = _scale;
part->alpha = _alpha;
part->tex = GFX_Smoke;
part->sy = RANDOM;
part->sx = RANDOM;
part->sscale = 0.9985;
part->salpha = 0.985;
switch (part->id) {
case 1:
part->sy = RANDOM * 0.5;
part->sx = RANDOM * 0.5;
part->sscale = 0.999;
part->salpha = 0.992;
part->framedelay = 10;
part->framecnt = 2;
break;
case 2:
part->scolor = 0.98;
part->salpha = 0.95;
break;
case 3:
part->sy = (RANDOM * 8);
part->sx = (RANDOM * 8);
part->salpha = 0.85;
part->scolor = 0.95;
break;
}
ParticleListTmp.push_back( part );
}
static bool updateParticle( Particle *part ) {
if (part->alpha < 0.05) { part->alpha -= 0.001; }
if (part->alpha < 0.1) { part->alpha -= 0.001; }
part->x += part->sx;
part->y += part->sy;
part->scale *= part->sscale;
part->alpha *= part->salpha;
switch (part->id) {
case 1:
if (part->alpha < 0.25) { part->alpha -= 0.001; }
if (part->framecnt == 0) {
part->framecnt = 20;
part->red -= 1;
part->green -= 1;
part->blue -= 1;
}
part->framecnt -= 1;
break;
case 2:
case 3:
part->red *= part->scolor;
part->green *= part->scolor;
part->blue *= part->scolor;
break;
}
if ((part->scale < 0) || (part->alpha < 0)) { return false; }
return true;
}
static void ExitGame() {
// Deinitialize GRRLIB & Video
GRRLIB_Exit();
// Free all memory used by textures.
for (vector<GRRLIB_texImg *>::iterator TexIter = TextureList.begin(); TexIter != TextureList.end(); TexIter++) {
free((*TexIter)->data);
free((*TexIter));
}
TextureList.clear();
// Exit application
exit(0);
}
static u8 CalculateFrameRate() {
static u8 frameCount = 0;
static u32 lastTime;
static u8 FPS = 0;
u32 currentTime = ticks_to_millisecs(gettime());
frameCount++;
if(currentTime - lastTime > 1000) {
lastTime = currentTime;
FPS = frameCount;
frameCount = 0;
}
return FPS;
}