From 80d78756ada0fe61b5e78f794ebb104333f5d759 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Tue, 26 Feb 2013 23:18:40 +0000
Subject: [PATCH] [Add] Primitive special effect system with explosions!!

---
 .clang_complete   |   4 +
 gfx/spfx/exps.png | Bin 0 -> 13243 bytes
 src/input.h       |   2 +-
 src/lephisto.c    |   8 +-
 src/menu.c        |   2 +-
 src/music.c       |   2 +-
 src/pause.c       |   3 +
 src/sound.c       |   4 +-
 src/spfx.c        | 221 ++++++++++++++++++++++++++++++++++++++++++++++
 src/spfx.h        |  22 +++++
 src/toolkit.h     |   2 +-
 src/weapon.c      |   6 +-
 12 files changed, 268 insertions(+), 8 deletions(-)
 create mode 100644 .clang_complete
 create mode 100644 gfx/spfx/exps.png
 create mode 100644 src/spfx.c
 create mode 100644 src/spfx.h

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 0000000000000000000000000000000000000000..e3dfbb8cdb4488d9ffb67796194bbf06304ed387
GIT binary patch
literal 13243
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

literal 0
HcmV?d00001

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);