[Add] Primitive special effect system with explosions!!

This commit is contained in:
Allanis 2013-02-26 23:18:40 +00:00
parent 21deb8709d
commit 80d78756ad
12 changed files with 268 additions and 8 deletions

4
.clang_complete Normal file
View File

@ -0,0 +1,4 @@
-I /usr/include/SDL/
-I /usr/include/freetype2/
-I lib/lua/

BIN
gfx/spfx/exps.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "SDL.h" #include <SDL.h>
// Input types. // Input types.
typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType; typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;

View File

@ -24,6 +24,7 @@
#include "toolkit.h" #include "toolkit.h"
#include "pilot.h" #include "pilot.h"
#include "sound.h" #include "sound.h"
#include "spfx.h"
#include "music.h" #include "music.h"
#define XML_START_ID "Start" #define XML_START_ID "Start"
@ -150,6 +151,7 @@ int main(int argc, char** argv) {
// Data loading. // Data loading.
factions_load(); factions_load();
spfx_load();
outfit_load(); outfit_load();
ships_load(); ships_load();
fleet_load(); fleet_load();
@ -203,6 +205,7 @@ int main(int argc, char** argv) {
fleet_free(); fleet_free();
ships_free(); ships_free();
outfit_free(); outfit_free();
spfx_free(); // Remove the special effects.
factions_free(); factions_free();
gl_freeFont(&gl_smallFont); gl_freeFont(&gl_smallFont);
@ -242,6 +245,7 @@ static void fps_control(void) {
// Update the game. // Update the game.
static void update_space(void) { static void update_space(void) {
weapons_update(dt); weapons_update(dt);
spfx_update(dt);
pilots_update(dt); pilots_update(dt);
} }
@ -254,8 +258,8 @@ static void update_space(void) {
// | Back layer weapons. // | Back layer weapons.
// X // X
// N | NPC ships. // N | NPC ships.
// | Normal layer particles (above ships).
// | Front layer weapons. // | Front layer weapons.
// | Normal layer particles (above ships).
// X // X
// FG | Player. // FG | Player.
// | Foreground particles. // | Foreground particles.
@ -270,8 +274,10 @@ static void render_space(void) {
// N. // N.
pilots_render(); pilots_render();
weapons_render(WEAPON_LAYER_FG); weapons_render(WEAPON_LAYER_FG);
spfx_render(SPFX_LAYER_BACK);
// FG. // FG.
player_render(); player_render();
spfx_render(SPFX_LAYER_FRONT);
display_fps(dt); display_fps(dt);
} }

View File

@ -1,5 +1,5 @@
#include <string.h> #include <string.h>
#include "SDL.h" #include <SDL.h>
#include "toolkit.h" #include "toolkit.h"
#include "log.h" #include "log.h"

View File

@ -1,7 +1,7 @@
#include <AL/al.h> #include <AL/al.h>
#include <AL/alc.h> #include <AL/alc.h>
#include <vorbis/vorbisfile.h> #include <vorbis/vorbisfile.h>
#include "SDL.h" #include <SDL.h>
#include "lephisto.h" #include "lephisto.h"
#include "log.h" #include "log.h"

View File

@ -1,5 +1,6 @@
#include "weapon.h" #include "weapon.h"
#include "pilot.h" #include "pilot.h"
#include "spfx.h"
#include "pause.h" #include "pause.h"
// Main thing with pausing is to allow things based on time to // Main thing with pausing is to allow things based on time to
@ -22,6 +23,7 @@ void pause(void) {
pilots_pause(); pilots_pause();
weapons_pause(); weapons_pause();
spfx_pause();
paused = 1; // We should unpause it. paused = 1; // We should unpause it.
} }
@ -31,6 +33,7 @@ void unpause(void) {
pilots_unpause(); pilots_unpause();
weapons_unpause(); weapons_unpause();
spfx_unpause();
paused = 0; paused = 0;
} }

View File

@ -1,7 +1,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <AL/alc.h> #include <AL/alc.h>
#include "SDL.h" #include <SDL.h>
#include "SDL_thread.h" #include <SDL_thread.h>
#include "lephisto.h" #include "lephisto.h"
#include "log.h" #include "log.h"

221
src/spfx.c Normal file
View File

@ -0,0 +1,221 @@
#include <SDL.h>
#include "lephisto.h"
#include "log.h"
#include "pilot.h"
#include "physics.h"
#include "opengl.h"
#include "pause.h"
#include "spfx.h"
#define SPFX_GFX "../gfx/spfx/" // Graphics location.
#define SPFX_CHUNK 10 // Chunk to allocate when needed.
typedef struct SPFX_Base_ {
char* name;
int anim; // Total duration in ms.
glTexture* gfx; // Will use each sprite as a frame.
} SPFX_Base;
static SPFX_Base* spfx_effects = NULL;
static int spfx_neffects = 0;
typedef struct SPFX_ {
Vec2 pos, vel; // They don't accelerate.
int lastframe; // Need when pausing.
int effect; // Actual effect.
unsigned int t; // Start.
} SPFX;
// Front stack is for effects on player.
// Back is for everything else.
static SPFX* spfx_stack_front = NULL;
static int spfx_nstack_front = 0;
static int spfx_mstack_front = 0;
static SPFX* spfx_stack_back = NULL;
static int spfx_nstack_back = 0;
static int spfx_mstack_back = 0;
static int spfx_base_load(char* name, int anim, char* gfx, int sx, int sy);
static void spfx_base_free(SPFX_Base* effect);
static void spfx_destroy(SPFX* layer, int* nlayer, int spfx);
static void spfx_update_layer(SPFX* layer, int* nlayer, const double dt);
static void spfx_pause_layer(SPFX* layer, int nlayer);
static void spfx_unpause_layer(SPFX* layer, int nlayer);
// Load the SPFX_Base.
static int spfx_base_load(char* name, int anim, char* gfx, int sx, int sy) {
SPFX_Base* cur;
char buf[PATH_MAX];
spfx_effects = realloc(spfx_effects, ++spfx_neffects*sizeof(SPFX_Base));
cur = &spfx_effects[spfx_neffects-1];
cur->name = strdup(name);
cur->anim = anim;
sprintf(buf, SPFX_GFX"%s", gfx);
cur->gfx = gl_newSprite(buf, sx, sy);
return 0;
}
static void spfx_base_free(SPFX_Base* effect) {
if(effect->name) free(effect->name);
if(effect->gfx) gl_freeTexture(effect->gfx);
}
// Load/Unload.
int spfx_load(void) {
spfx_base_load("ExpS", 600, "exps.png", 6, 5);
return 0;
}
void spfx_free(void) {
int i;
// Get rid of all the particles and free the stacks.
spfx_clear();
if(spfx_stack_front) free(spfx_stack_front);
spfx_stack_front = NULL;
spfx_mstack_front = 0;
if(spfx_stack_back) free(spfx_stack_back);
spfx_stack_back = NULL;
spfx_mstack_back = 0;
for(i = 0; i < spfx_neffects; i++)
spfx_base_free(&spfx_effects[i]);
free(spfx_effects);
spfx_effects = NULL;
spfx_neffects = 0;
}
void spfx_add(int effect, const Vec2* pos, const Vec2* vel, const int layer) {
SPFX* cur_spfx;
if(layer == SPFX_LAYER_FRONT) {
// Front layer.
if(spfx_mstack_front < spfx_nstack_front+1) {
// We need more memory.
spfx_mstack_front += SPFX_CHUNK;
spfx_stack_front = realloc(spfx_stack_front, spfx_mstack_front*sizeof(SPFX));
}
cur_spfx = &spfx_stack_front[spfx_nstack_front];
spfx_nstack_front++;
}
else if(layer == SPFX_LAYER_BACK) {
// Back layer.
if(spfx_mstack_back < spfx_nstack_back+1) {
// Need more memory.
spfx_mstack_back += SPFX_CHUNK;
spfx_stack_back = realloc(spfx_stack_back, spfx_mstack_back*sizeof(SPFX));
}
cur_spfx = &spfx_stack_back[spfx_nstack_back];
spfx_nstack_back++;
}
cur_spfx->effect = effect;
vectcpy(&cur_spfx->pos, pos);
vectcpy(&cur_spfx->vel, vel);
cur_spfx->t = SDL_GetTicks();
}
void spfx_clear(void) {
int i;
for(i = spfx_nstack_front-1; i >= 0; i--)
spfx_destroy(spfx_stack_front, &spfx_nstack_front, i);
for(i = spfx_nstack_back-1; i >= 0; i--)
spfx_destroy(spfx_stack_back, &spfx_nstack_back, i);
}
static void spfx_destroy(SPFX* layer, int* nlayer, int spfx) {
int i;
(*nlayer)--;
for(i = spfx; i < *nlayer; i++)
memcpy(&layer[i], &layer[i+1], sizeof(SPFX));
}
void spfx_update(const double dt) {
spfx_update_layer(spfx_stack_front, &spfx_nstack_front, dt);
spfx_update_layer(spfx_stack_back, &spfx_nstack_back, dt);
}
static void spfx_update_layer(SPFX* layer, int* nlayer, const double dt) {
int i;
unsigned int t = SDL_GetTicks();
for(i = 0; i < *nlayer; i++) {
// Time to die!!!
if(t > (layer[i].t + spfx_effects[layer[i].effect].anim)) {
spfx_destroy(layer, nlayer, i);
i--;
continue;
}
// Mkay. Update it now.
vect_cadd(&layer[i].pos, dt*VX(layer[i].vel), dt*VY(layer[i].vel));
}
}
void spfx_render(const int layer) {
SPFX* spfx_stack;
int i, spfx_nstack;
SPFX_Base* effect;
int sx, sy;
unsigned int t = SDL_GetTicks();
// Get the appropriate layer.
switch(layer) {
case SPFX_LAYER_FRONT:
spfx_stack = spfx_stack_front;
spfx_nstack = spfx_nstack_front;
break;
case SPFX_LAYER_BACK:
spfx_stack = spfx_stack_back;
spfx_nstack = spfx_nstack_back;
break;
}
for(i = 0; i < spfx_nstack; i++) {
effect = &spfx_effects[spfx_stack[i].effect];
sx = (int)effect->gfx->sx;
sy = (int)effect->gfx->sy;
if(!paused) // Don't calculate frame if paused.
spfx_stack[i].lastframe = sx * sy
* MIN(((double)(t - spfx_stack[i].t)/(double)effect->anim), 1.);
gl_blitSprite(effect->gfx,
VX(spfx_stack[i].pos), VY(spfx_stack[i].pos),
spfx_stack[i].lastframe % sx,
spfx_stack[i].lastframe / sx,
NULL);
}
}
void spfx_pause(void) {
spfx_pause_layer(spfx_stack_front, spfx_nstack_front);
spfx_pause_layer(spfx_stack_back, spfx_nstack_back);
}
static void spfx_pause_layer(SPFX* layer, int nlayer) {
int i;
unsigned int t = SDL_GetTicks();
for(i = 0; i < nlayer; i++)
layer[i].t -= t;
}
void spfx_unpause(void) {
spfx_unpause_layer(spfx_stack_front, spfx_nstack_front);
spfx_unpause_layer(spfx_stack_back, spfx_nstack_back);
}
static void spfx_unpause_layer(SPFX* layer, int nlayer) {
int i;
unsigned int t = SDL_GetTicks();
for(i = 0; i < nlayer; i++)
layer[i].t += t;
}

22
src/spfx.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "physics.h"
#define SPFX_LAYER_FRONT 0
#define SPFX_LAYER_BACK 1
void spfx_add(const int effect,
const Vec2* pos, const Vec2* vel, const int layer);
// Stack manipulation functions.
void spfx_update(const double dt);
void spfx_render(const int layer);
void spfx_clear(void);
// Load/free.
int spfx_load(void);
void spfx_free(void);
// Pause/Unpause routines.
void spfx_pause(void);
void spfx_unpause(void);

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "SDL.h" #include <SDL.h>
#include "opengl.h" #include "opengl.h"
#include "font.h" #include "font.h"

View File

@ -10,6 +10,7 @@
#include "pilot.h" #include "pilot.h"
#include "collision.h" #include "collision.h"
#include "player.h" #include "player.h"
#include "spfx.h"
#include "weapon.h" #include "weapon.h"
#define weapon_isSmart(w) (w->think) #define weapon_isSmart(w) (w->think)
@ -236,8 +237,11 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
// Good shot. // Good shot.
static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer) { static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer) {
// Someone should let the ai know it's been attacked. // Someone should let the ai know it's been attacked.
if(!pilot_isPlayer(p)) if(!pilot_isPlayer(p)) {
ai_attacked(p, w->parent); ai_attacked(p, w->parent);
spfx_add(0, &w->solid->pos, &p->solid->vel, SPFX_LAYER_BACK);
} else
spfx_add(0, &w->solid->pos, &p->solid->vel, SPFX_LAYER_FRONT);
if(w->parent == PLAYER_ID) if(w->parent == PLAYER_ID)
// Make hostile to player. // Make hostile to player.
pilot_setFlag(p, PILOT_HOSTILE); pilot_setFlag(p, PILOT_HOSTILE);