Tutorial 06: Particle Systems

Working with particle systems and the particle editor.

Overview

This tutorial covers the HGE particle system, which enables effects like fire, smoke, explosions, sparkles, and magic spells. You'll learn to use the particle editor and integrate effects into your game.

Prerequisites

  • Basic HGE application structure
  • Texture loading and sprite rendering
  • Particle Editor tool

The Particle System

HGE's particle system uses these components:

  • hgeParticleSystem — Manages and renders particles
  • hgeParticleSystemInfo — Stores effect parameters
  • Particle Editor — Visual design tool

Creating Effects

Step 1: Design in the Editor

Open the particle editor and create your effect:

  1. Load a particle texture (small sprite for each particle)
  2. Adjust emission, movement, and appearance
  3. Test and refine
  4. Save as .psi file

Step 2: Load in Your Game

hgeSprite *sprParticle;
hgeParticleSystem *ps;

void LoadParticles()
{
    // Load the particle sprite
    HTEXTURE tex = hge->Texture_Load("particles.png");
    sprParticle = new hgeSprite(tex, 0, 0, 32, 32);
    sprParticle->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD);
    sprParticle->SetHotSpot(16, 16);
    
    // Create particle system from .psi file
    ps = new hgeParticleSystem("effects/fire.psi", sprParticle);
}

Step 3: Update and Render

bool FrameFunc()
{
    float dt = hge->Timer_GetDelta();
    
    // Update particle positions
    ps->Update(dt);
    
    // Move emitter to follow something
    float mx, my;
    hge->Input_GetMousePos(&mx, &my);
    ps->MoveTo(mx, my);
    
    return false;
}

bool RenderFunc()
{
    hge->Gfx_BeginScene();
    hge->Gfx_Clear(0);
    
    // Render all particles
    ps->Render();
    
    hge->Gfx_EndScene();
    return false;
}

Effect Triggering

Continuous Effects

For ongoing effects like torch fire:

// The system emits continuously by default
ps->Fire();  // Start emission

Burst Effects

For one-shot effects like explosions:

// Stop continuous emission
ps->Stop(false);  // false = let existing particles finish

// Trigger bursts manually
void Explode(float x, float y)
{
    ps->MoveTo(x, y);
    ps->Fire();  // Emit burst
}

Multiple Particle Systems

For different effects, create multiple systems:

hgeParticleSystem *psFire;
hgeParticleSystem *psSmoke;
hgeParticleSystem *psExplosion;

void LoadEffects()
{
    psFire = new hgeParticleSystem("effects/fire.psi", sprFireParticle);
    psSmoke = new hgeParticleSystem("effects/smoke.psi", sprSmokeParticle);
    psExplosion = new hgeParticleSystem("effects/explosion.psi", sprExplosionParticle);
}

void UpdateEffects(float dt)
{
    psFire->Update(dt);
    psSmoke->Update(dt);
    psExplosion->Update(dt);
}

void RenderEffects()
{
    psFire->Render();
    psSmoke->Render();
    psExplosion->Render();
}

Performance Tips

  • Limit particle count — Don't exceed a few thousand active particles
  • Use simple textures — Small, simple particle sprites render faster
  • Reuse systems — Move and retrigger rather than create new instances
  • Cull off-screen — Don't update systems that aren't visible

Complete Example

#include <hge.h>
#include <hgeparticle.h>

HGE *hge = 0;
hgeSprite *sprParticle;
hgeParticleSystem *ps;

bool FrameFunc()
{
    float dt = hge->Timer_GetDelta();
    
    // Update particles
    ps->Update(dt);
    
    // Follow mouse
    float mx, my;
    hge->Input_GetMousePos(&mx, &my);
    ps->MoveTo(mx, my);
    
    // Click to restart
    if (hge->Input_KeyDown(HGEK_LBUTTON))
        ps->Fire();
    
    return hge->Input_GetKeyState(HGEK_ESCAPE);
}

bool RenderFunc()
{
    hge->Gfx_BeginScene();
    hge->Gfx_Clear(0);
    ps->Render();
    hge->Gfx_EndScene();
    return false;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    hge = hgeCreate(HGE_VERSION);
    
    hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
    hge->System_SetState(HGE_RENDERFUNC, RenderFunc);
    hge->System_SetState(HGE_WINDOWED, true);
    hge->System_SetState(HGE_SCREENWIDTH, 800);
    hge->System_SetState(HGE_SCREENHEIGHT, 600);
    hge->System_SetState(HGE_TITLE, "Tutorial 06 - Particles");
    
    if (hge->System_Initiate())
    {
        HTEXTURE tex = hge->Texture_Load("particle.png");
        sprParticle = new hgeSprite(tex, 0, 0, 32, 32);
        sprParticle->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD);
        sprParticle->SetHotSpot(16, 16);
        
        ps = new hgeParticleSystem("trail.psi", sprParticle);
        ps->Fire();
        
        hge->System_Start();
        
        delete ps;
        delete sprParticle;
        hge->Texture_Free(tex);
    }
    
    hge->System_Shutdown();
    hge->Release();
    return 0;
}

See Also