diff --git a/.clang_complete b/.clang_complete new file mode 100644 index 0000000..733c14f --- /dev/null +++ b/.clang_complete @@ -0,0 +1,4 @@ +-I /usr/include/SDL/ +-I /usr/include/freetype2/ +-I lib/lua/ + diff --git a/gfx/spfx/exps.png b/gfx/spfx/exps.png new file mode 100644 index 0000000..e3dfbb8 Binary files /dev/null and b/gfx/spfx/exps.png differ diff --git a/src/input.h b/src/input.h index 02ba676..96ab2fa 100644 --- a/src/input.h +++ b/src/input.h @@ -1,5 +1,5 @@ #pragma once -#include "SDL.h" +#include <SDL.h> // Input types. typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType; diff --git a/src/lephisto.c b/src/lephisto.c index 4e98483..8493d32 100644 --- a/src/lephisto.c +++ b/src/lephisto.c @@ -24,6 +24,7 @@ #include "toolkit.h" #include "pilot.h" #include "sound.h" +#include "spfx.h" #include "music.h" #define XML_START_ID "Start" @@ -150,6 +151,7 @@ int main(int argc, char** argv) { // Data loading. factions_load(); + spfx_load(); outfit_load(); ships_load(); fleet_load(); @@ -203,6 +205,7 @@ int main(int argc, char** argv) { fleet_free(); ships_free(); outfit_free(); + spfx_free(); // Remove the special effects. factions_free(); gl_freeFont(&gl_smallFont); @@ -242,6 +245,7 @@ static void fps_control(void) { // Update the game. static void update_space(void) { weapons_update(dt); + spfx_update(dt); pilots_update(dt); } @@ -254,8 +258,8 @@ static void update_space(void) { // | Back layer weapons. // X // N | NPC ships. -// | Normal layer particles (above ships). // | Front layer weapons. +// | Normal layer particles (above ships). // X // FG | Player. // | Foreground particles. @@ -270,8 +274,10 @@ static void render_space(void) { // N. pilots_render(); weapons_render(WEAPON_LAYER_FG); + spfx_render(SPFX_LAYER_BACK); // FG. player_render(); + spfx_render(SPFX_LAYER_FRONT); display_fps(dt); } diff --git a/src/menu.c b/src/menu.c index ae6633b..6ad2da2 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1,5 +1,5 @@ #include <string.h> -#include "SDL.h" +#include <SDL.h> #include "toolkit.h" #include "log.h" diff --git a/src/music.c b/src/music.c index 897e9c6..da7dd9f 100644 --- a/src/music.c +++ b/src/music.c @@ -1,7 +1,7 @@ #include <AL/al.h> #include <AL/alc.h> #include <vorbis/vorbisfile.h> -#include "SDL.h" +#include <SDL.h> #include "lephisto.h" #include "log.h" diff --git a/src/pause.c b/src/pause.c index 2ec87c8..221ddec 100644 --- a/src/pause.c +++ b/src/pause.c @@ -1,5 +1,6 @@ #include "weapon.h" #include "pilot.h" +#include "spfx.h" #include "pause.h" // Main thing with pausing is to allow things based on time to @@ -22,6 +23,7 @@ void pause(void) { pilots_pause(); weapons_pause(); + spfx_pause(); paused = 1; // We should unpause it. } @@ -31,6 +33,7 @@ void unpause(void) { pilots_unpause(); weapons_unpause(); + spfx_unpause(); paused = 0; } diff --git a/src/sound.c b/src/sound.c index 5ccbffb..8fa84a4 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1,7 +1,7 @@ #include <sys/stat.h> #include <AL/alc.h> -#include "SDL.h" -#include "SDL_thread.h" +#include <SDL.h> +#include <SDL_thread.h> #include "lephisto.h" #include "log.h" diff --git a/src/spfx.c b/src/spfx.c new file mode 100644 index 0000000..4478673 --- /dev/null +++ b/src/spfx.c @@ -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; +} + diff --git a/src/spfx.h b/src/spfx.h new file mode 100644 index 0000000..c8fd61f --- /dev/null +++ b/src/spfx.h @@ -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); + diff --git a/src/toolkit.h b/src/toolkit.h index 6cfb683..21b2007 100644 --- a/src/toolkit.h +++ b/src/toolkit.h @@ -1,5 +1,5 @@ #pragma once -#include "SDL.h" +#include <SDL.h> #include "opengl.h" #include "font.h" diff --git a/src/weapon.c b/src/weapon.c index 4f5c116..7f7c568 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -10,6 +10,7 @@ #include "pilot.h" #include "collision.h" #include "player.h" +#include "spfx.h" #include "weapon.h" #define weapon_isSmart(w) (w->think) @@ -236,8 +237,11 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { // Good shot. static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer) { // Someone should let the ai know it's been attacked. - if(!pilot_isPlayer(p)) + if(!pilot_isPlayer(p)) { 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) // Make hostile to player. pilot_setFlag(p, PILOT_HOSTILE);