Implemented a simple particle engine.
This commit is contained in:
parent
753448efdb
commit
93c0623fe4
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
17
src/main.c
17
src/main.c
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef VECTOR2D_H_
|
||||||
|
#define VECTOR2D_H_
|
||||||
|
|
||||||
|
typedef struct Vector2d_t {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} Vector2d;
|
||||||
|
|
||||||
|
#endif // VECTOR2D_H_
|
Loading…
Reference in New Issue