/*=========================================== GRRLIB (GX Version) Example code by Xane This example shows a basic particle engine creating a Smokebomb. ============================================*/ #include #include #include #include #include #include // 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 TextureList; static vector ParticleList; static vector 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_SetColorRGBA( RGBA(255, 255, 255, 255) ); GRRLIB_DrawImg( 0, 0, GFX_Background ); // Add any pending objects into the main container if (ParticleListTmp.size()) { for(u32 i = 0; i::iterator PartIter = ParticleList.begin(); PartIter != ParticleList.end();) { if (updateParticle((*PartIter)) == true) { GRRLIB_SetColorRGBA( RGBA( (*PartIter)->red, (*PartIter)->green, (*PartIter)->blue, GRRLIB_ClampVar8((*PartIter)->alpha*255) ) ); GRRLIB_SetScale ( (*PartIter)->scale, (*PartIter)->scale ); GRRLIB_SetRotation ( (*PartIter)->rot ); GRRLIB_DrawImg( (*PartIter)->x, (*PartIter)->y, (*PartIter)->tex ); } else { free( (*PartIter) ); ParticleList.erase(PartIter); continue; } ParticleCnt += 1; PartIter++; } // Draw Crosshair GRRLIB_ResetSettings(); GRRLIB_DrawImg( P1MX, P1MY, GFX_Crosshair ); // Draw Text GRRLIB_SetColorRGBA( RGBA(0, 0, 0, 160) ); GRRLIB_Rectangle( 28, 28, 280, 20, 1 ); GRRLIB_SetColorRGBA( 0xFFFFFFFF ); GRRLIB_Printf ( 32, 32, GFX_Font, "Point your WiiMote on the screen." ); GRRLIB_SetColorRGBA( RGBA(0, 0, 0, 160) ); GRRLIB_Rectangle( 28, 48, 200, 16, 1 ); GRRLIB_SetColorRGBA( 0xFFFFFFFF ); GRRLIB_Printf ( 32, 48, GFX_Font, "Number of Particle: %d", ParticleCnt ); GRRLIB_SetColorRGBA( RGBA(0, 0, 0, 160) ); GRRLIB_Rectangle( 28, 64, 64, 16, 1 ); GRRLIB_SetColorRGBA( 0xFFFFFFFF ); GRRLIB_Printf ( 32, 64, GFX_Font, "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::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; }