Implemented a simple particle engine.

This commit is contained in:
Linus Probert 2018-02-03 23:39:49 +01:00
parent 753448efdb
commit 93c0623fe4
9 changed files with 223 additions and 2 deletions

View File

@ -43,7 +43,7 @@ if (NOT WIN32)
) )
endif (NOT WIN32) endif (NOT WIN32)
set(CMAKE_C_FLAGS_DEBUG "-DDEBUG") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
# PROGRAMS: # PROGRAMS:
add_executable(breakhack add_executable(breakhack
@ -70,6 +70,7 @@ add_executable(breakhack
src/item_builder src/item_builder
src/pointer src/pointer
src/gui_button src/gui_button
src/particle_engine
) )
target_link_libraries(breakhack target_link_libraries(breakhack

View File

@ -465,6 +465,9 @@ gui_destroy(Gui *gui)
for (int i = 0; i < LOG_LINES_COUNT; ++i) for (int i = 0; i < LOG_LINES_COUNT; ++i)
texture_destroy(gui->log_lines[i]); texture_destroy(gui->log_lines[i]);
for (int i = 0; i < LABEL_COUNT; ++i)
sprite_destroy(gui->labels[i]);
ht_destroy_custom(gui->textures, (void (*)(void*)) &texture_destroy); ht_destroy_custom(gui->textures, (void (*)(void*)) &texture_destroy);
free(gui); free(gui);
} }

View File

@ -18,6 +18,7 @@
#include "item_builder.h" #include "item_builder.h"
#include "pointer.h" #include "pointer.h"
#include "gui_button.h" #include "gui_button.h"
#include "particle_engine.h"
static SDL_Window *gWindow = NULL; static SDL_Window *gWindow = NULL;
static SDL_Renderer *gRenderer = NULL; static SDL_Renderer *gRenderer = NULL;
@ -27,6 +28,7 @@ static RoomMatrix *gRoomMatrix = NULL;
static Gui *gGui = NULL; static Gui *gGui = NULL;
static Pointer *gPointer = NULL; static Pointer *gPointer = NULL;
static unsigned int cLevel = 1; static unsigned int cLevel = 1;
static float deltaTime = 1.0;
static double renderScale = 1.0; static double renderScale = 1.0;
static GameState gGameState; static GameState gGameState;
static Camera gCamera; static Camera gCamera;
@ -135,6 +137,7 @@ bool init(void)
gGui = gui_create(gRenderer); gGui = gui_create(gRenderer);
item_builder_init(gRenderer); item_builder_init(gRenderer);
gPointer = pointer_create(gRenderer); gPointer = pointer_create(gRenderer);
particle_engine_init();
} }
gGameState = PLAYING; gGameState = PLAYING;
@ -213,6 +216,7 @@ run_game(void)
roommatrix_build_lightmap(gRoomMatrix); roommatrix_build_lightmap(gRoomMatrix);
gui_update_player_stats(gGui, gPlayer, gMap, gRenderer); gui_update_player_stats(gGui, gPlayer, gMap, gRenderer);
particle_engine_update(deltaTime);
if (gPlayer->steps >= gPlayer->stats.speed) { if (gPlayer->steps >= gPlayer->stats.speed) {
player_reset_steps(gPlayer); player_reset_steps(gPlayer);
@ -224,6 +228,7 @@ run_game(void)
SDL_RenderSetViewport(gRenderer, &gameViewport); SDL_RenderSetViewport(gRenderer, &gameViewport);
map_render(gMap, &gCamera); map_render(gMap, &gCamera);
particle_engine_render(&gCamera);
player_render(gPlayer, &gCamera); player_render(gPlayer, &gCamera);
roommatrix_render_lightmap(gRoomMatrix, &gCamera); roommatrix_render_lightmap(gRoomMatrix, &gCamera);
@ -249,6 +254,9 @@ run_game(void)
static static
void run(void) void run(void)
{ {
static int oldTime = 0;
static int currentTime = 0;
bool quit = false; bool quit = false;
Timer* fpsTimer = timer_create(); Timer* fpsTimer = timer_create();
@ -281,6 +289,14 @@ void run(void)
if (ticks < 1000/60) if (ticks < 1000/60)
SDL_Delay((1000/60) - ticks); SDL_Delay((1000/60) - ticks);
timer_stop(fpsTimer); timer_stop(fpsTimer);
if (currentTime == 0)
currentTime = SDL_GetTicks();
else {
oldTime = currentTime;
currentTime = SDL_GetTicks();
deltaTime = (currentTime - oldTime) / 1000.0;
}
} }
timer_destroy(fpsTimer); timer_destroy(fpsTimer);
@ -295,6 +311,7 @@ void close(void)
gui_destroy(gGui); gui_destroy(gGui);
pointer_destroy(gPointer); pointer_destroy(gPointer);
item_builder_close(); item_builder_close();
particle_engine_close();
SDL_DestroyRenderer(gRenderer); SDL_DestroyRenderer(gRenderer);
SDL_DestroyWindow(gWindow); SDL_DestroyWindow(gWindow);
gWindow = NULL; gWindow = NULL;

View File

@ -10,6 +10,7 @@
#include "item.h" #include "item.h"
#include "item_builder.h" #include "item_builder.h"
#include "map.h" #include "map.h"
#include "particle_engine.h"
static void static void
monster_load_texts(Monster *m, SDL_Renderer *renderer) monster_load_texts(Monster *m, SDL_Renderer *renderer)
@ -231,6 +232,11 @@ monster_hit(Monster *monster, unsigned int dmg)
if (dmg > 0) { if (dmg > 0) {
monster->hitText->active = true; monster->hitText->active = true;
monster->missText->active = false; monster->missText->active = false;
Position p = monster->sprite->pos;
p.x += 8;
p.y += 8;
Dimension d = { 8, 8 };
particle_engine_bloodspray(p, d);
} else { } else {
monster->missText->active = true; monster->missText->active = true;
monster->hitText->active = false; monster->hitText->active = false;

155
src/particle_engine.c Normal file
View File

@ -0,0 +1,155 @@
#include <stdlib.h>
#include "particle_engine.h"
#include "linkedlist.h"
#include "util.h"
#include "defines.h"
#include "vector2d.h"
typedef struct Particle_t {
Position pos;
Vector2d velocity;
Dimension dim;
unsigned int movetime;
unsigned int lifetime;
SDL_Color color;
} Particle;
typedef struct Engine_t {
LinkedList *particles;
} Engine;
static Engine *engine = NULL;
static void
check_engine(void)
{
if (!engine)
fatal("Particle engine not initiated");
}
void
particle_engine_init(void)
{
if (engine != NULL)
fatal("Engine already initiated");
engine = ec_malloc(sizeof(Engine));
engine->particles = linkedlist_create();
}
void
particle_engine_bloodspray(Position pos, Dimension dim)
{
int x, y, xv, yv, w, h, i;
unsigned int mt, lt;
Particle *p;
check_engine();
for (i = 0; i < 15; ++i) {
x = (rand() % dim.width) + pos.x;
y = (rand() % dim.height) + pos.y;
xv = (rand() % 200) - 100;
yv = (rand() % 200) - 100;
mt = (rand() % 10) + 10;
lt = (rand() % 120) + 60;
w = (rand() % 3) + 2;
h = (rand() % 3) + 2;
p = ec_malloc(sizeof(Particle));
p->pos = (Position) { x, y };
p->velocity = (Vector2d) { xv, yv };
p->movetime = mt;
p->lifetime = lt;
p->dim = (Dimension) { w, h };
p->color = (SDL_Color) { 255, 0, 0, 255 };
linkedlist_append(&engine->particles, p);
}
}
static void
move_particle(Particle *particle, float deltaTime)
{
if (!particle->movetime)
return;
particle->pos.x += particle->velocity.x * deltaTime;
particle->pos.y += particle->velocity.y * deltaTime;
}
void
particle_engine_update(float deltaTime)
{
check_engine();
LinkedList *current, *last;
Particle *particle;
current = engine->particles;
last = NULL;
while (current) {
particle = current->data;
if (particle->movetime)
particle->movetime--;
if (particle->lifetime > 0) {
particle->lifetime--;
move_particle(current->data, deltaTime);
last = current;
current = current->next;
} else {
if (!last) {
engine->particles = current->next;
free(current->data);
free(current);
current = engine->particles;
} else {
last->next = current->next;
free(current->data);
free(current);
current = last->next;
}
}
}
}
static void
render_particle(Particle *p, Camera *cam)
{
Position pos = camera_to_camera_position(cam, &p->pos);
SDL_Rect box = { pos.x, pos.y, p->dim.width, p->dim.height };
SDL_SetRenderDrawColor(cam->renderer,
p->color.r,
p->color.b,
p->color.g,
p->color.a);
SDL_RenderFillRect(cam->renderer, &box);
}
void
particle_engine_render(Camera *cam)
{
check_engine();
LinkedList *particles = engine->particles;
while (particles) {
render_particle(particles->data, cam);
particles = particles->next;
}
}
void
particle_engine_close(void)
{
check_engine();
while (engine->particles)
free(linkedlist_pop(&engine->particles));
free(engine);
engine = NULL;
}

24
src/particle_engine.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef PARTICLE_ENGINE_H_
#define PARTICLE_ENGINE_H_
#include <SDL2/SDL.h>
#include "position.h"
#include "dimension.h"
#include "camera.h"
void
particle_engine_init(void);
void
particle_engine_bloodspray(Position, Dimension);
void
particle_engine_update(float deltatime);
void
particle_engine_render(Camera*);
void
particle_engine_close(void);
#endif // PARTICLE_ENGINE_H_

View File

@ -7,6 +7,7 @@
#include "util.h" #include "util.h"
#include "gui.h" #include "gui.h"
#include "item.h" #include "item.h"
#include "particle_engine.h"
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 1, 1 } #define ENGINEER_STATS { 12, 12, 5, 7, 2, 1, 1 }
#define MAGE_STATS { 12, 12, 5, 7, 2, 1, 1 } #define MAGE_STATS { 12, 12, 5, 7, 2, 1, 1 }
@ -309,6 +310,10 @@ player_hit(Player *p, unsigned int dmg)
if (dmg > 0) { if (dmg > 0) {
p->hitText->active = true; p->hitText->active = true;
p->missText->active = false; p->missText->active = false;
Position pos = p->sprite->pos;
pos.x += 8;
pos.y += 8;
particle_engine_bloodspray(pos, (Dimension) { 8, 8 });
} else { } else {
p->missText->active = true; p->missText->active = true;
p->hitText->active = false; p->hitText->active = false;

View File

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "pointer.h" #include "pointer.h"
#include "util.h" #include "util.h"
#include "particle_engine.h"
Pointer * Pointer *
pointer_create(SDL_Renderer *renderer) pointer_create(SDL_Renderer *renderer)
@ -25,7 +26,7 @@ pointer_handle_event(Pointer *p, SDL_Event *event)
if (event->type == SDL_MOUSEMOTION) { if (event->type == SDL_MOUSEMOTION) {
p->sprite->pos.x = event->motion.x; p->sprite->pos.x = event->motion.x;
p->sprite->pos.y = event->motion.y; p->sprite->pos.y = event->motion.y;
debug("Pointer pos: %dx%d", p->sprite->pos.x, p->sprite->pos.y); // debug("Pointer pos: %dx%d", p->sprite->pos.x, p->sprite->pos.y);
} }
} }

9
src/vector2d.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef VECTOR2D_H_
#define VECTOR2D_H_
typedef struct Vector2d_t {
float x;
float y;
} Vector2d;
#endif // VECTOR2D_H_