From 0476d4d1bd1c4dff2b1c7866f384e55fa27132ad Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Tue, 7 May 2019 11:52:30 +0200 Subject: [PATCH] Introduces particle emitters on monsters Also adds the bleed emitter to monsters for later use with the mage. --- CMakeLists.txt | 1 + Makefile | 14 +++++------ src/monster.c | 57 ++++++++++++++++++++++++++++++++++-------- src/monster.h | 11 +++++++- src/particle_emitter.c | 55 ++++++++++++++++++++++++++++++++++++++++ src/particle_emitter.h | 44 ++++++++++++++++++++++++++++++++ src/particle_engine.c | 12 +++++++++ src/particle_engine.h | 6 +++++ 8 files changed, 182 insertions(+), 18 deletions(-) create mode 100644 src/particle_emitter.c create mode 100644 src/particle_emitter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2add3e3..b49e388 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,6 +213,7 @@ add_executable(breakhack src/pointer src/gui_button src/particle_engine + src/particle_emitter src/menu src/collisions src/keyboard diff --git a/Makefile b/Makefile index 89046d1..c1da974 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,18 @@ all: - @ninja -C _build/debug + @make -C _build/debug .PHONY: all release: - @ninja -C _build/release + @make -C _build/release .PHONY: release clean: - @ninja clean -C _build/debug - @ninja clean -C _build/release + @make clean -C _build/debug + @make clean -C _build/release .PHONY: clean test: - @ninja test -C _build/debug + @make test -C _build/debug .PHONY: test run: $(all) @@ -24,9 +24,9 @@ playtest: $(all) .PHONY: run lint: - @ninja lint -C _build/debug + @make lint -C _build/debug .PHONY: lint package: - @ninja package -C _build/release + @make package -C _build/release .PHONY: package diff --git a/src/monster.c b/src/monster.c index bd04e52..6f3f3f2 100644 --- a/src/monster.c +++ b/src/monster.c @@ -233,6 +233,24 @@ monster_behaviour_check(Monster *m, RoomMatrix *rm) } } +static void +create_emitters(Monster *m) +{ + // Bloodlust + ParticleEmitter *emitter = particle_emitter_create(); + emitter->timestep = 0; + emitter->enabled = false; + emitter->particle_func = particle_engine_bloodlust; + m->emitters.bloodlust = emitter; + + emitter = particle_emitter_create(); + emitter->timestep = 1000; + emitter->enabled = false; + emitter->particle_func = particle_engine_bleed; + m->emitters.bleed = emitter; + +} + Monster* monster_create(void) { @@ -265,9 +283,9 @@ monster_create(void) m->stateIndicator.shownOnPlayerRoomEnter = false; m->state.forceCount = 0; m->boss = false; - m->bloodlust = false; m->items.keyType = LOCK_NONE; monster_set_behaviour(m, NORMAL); + create_emitters(m); return m; } @@ -586,6 +604,19 @@ monster_reset_steps(Monster *m) m->steps = 0; } +static void +update_emitters(Monster *m) +{ + Position pos = m->sprite->pos; + pos.x += 6; + pos.y += 6; + particle_emitter_update(m->emitters.bloodlust, pos, DIM(20, 20)); + + pos.x += 5; + pos.y += 5; + particle_emitter_update(m->emitters.bleed, pos, DIM(10, 10)); +} + void monster_update(Monster *m, UpdateData *data) { @@ -593,6 +624,7 @@ monster_update(Monster *m, UpdateData *data) return; sprite_update(m->sprite, data); + update_emitters(m); if (m->sprite->state == SPRITE_STATE_PLUMMETED) { m->stats.hp = 0; @@ -762,13 +794,8 @@ monster_render(Monster *m, Camera *cam) if (m->stats.hp <= 0) return; - if (m->bloodlust) { - Position pos = m->sprite->pos; - pos.x += 6; - pos.y += 6; - particle_engine_sparkle(pos, DIM(20, 20), C_RED, false); - } - + particle_emitter_render(m->emitters.bloodlust); + particle_emitter_render(m->emitters.bleed); sprite_render(m->sprite, cam); } @@ -856,11 +883,11 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction) void monster_set_bloodlust(Monster *m, bool bloodlust) { - if (m->bloodlust == bloodlust || m->stats.hp <= 0) { + if (m->emitters.bloodlust->enabled == bloodlust || m->stats.hp <= 0) { return; } - m->bloodlust = bloodlust; + m->emitters.bloodlust->enabled = bloodlust; if (bloodlust) { gui_log("%s rages with bloodlust", m->label); monster_set_behaviour(m, HOSTILE); @@ -882,6 +909,12 @@ monster_set_bloodlust(Monster *m, bool bloodlust) } } +void +monster_set_bleeding(Monster *m) +{ + m->emitters.bleed->enabled = true; +} + void monster_destroy(Monster *m) { @@ -890,6 +923,10 @@ monster_destroy(Monster *m) free(m->label); if (m->lclabel) free(m->lclabel); + + particle_emitter_destroy(m->emitters.bloodlust); + particle_emitter_destroy(m->emitters.bleed); + sprite_destroy(m->stateIndicator.sprite); free(m); } diff --git a/src/monster.h b/src/monster.h index 38f555c..6851d82 100644 --- a/src/monster.h +++ b/src/monster.h @@ -26,6 +26,7 @@ #include "player.h" #include "linkedlist.h" #include "doorlocktype.h" +#include "particle_emitter.h" struct UpdateData; @@ -68,6 +69,11 @@ typedef struct MonsterItems { enum DoorLockType keyType; } MonsterItems; +typedef struct ParticleEmitters { + ParticleEmitter *bloodlust; + ParticleEmitter *bleed; +} ParticleEmitters; + typedef struct Monster { char *label; char *lclabel; @@ -77,9 +83,9 @@ typedef struct Monster { MonsterStateIndicator stateIndicator; MonsterBehaviour behaviour; MonsterItems items; + ParticleEmitters emitters; unsigned int steps; bool boss; - bool bloodlust; } Monster; Monster* monster_create(void); @@ -123,6 +129,9 @@ monster_reset_steps(Monster *m); void monster_set_bloodlust(Monster*, bool bloodlust); +void +monster_set_bleeding(Monster*); + void monster_destroy(Monster*); diff --git a/src/particle_emitter.c b/src/particle_emitter.c new file mode 100644 index 0000000..60e31c3 --- /dev/null +++ b/src/particle_emitter.c @@ -0,0 +1,55 @@ +#include "particle_emitter.h" +#include "util.h" + +#include + +ParticleEmitter * +particle_emitter_create(void) +{ + ParticleEmitter *emitter = ec_malloc(sizeof(ParticleEmitter)); + emitter->pos = POS(0, 0); + emitter->dim = DIM(32, 32); + emitter->particle_func = NULL; + emitter->timer = _timer_create(); + emitter->timestep = 1; + emitter->enabled = false; + return emitter; +} + +void +particle_emitter_render(ParticleEmitter *emitter) +{ + if (!emitter->enabled) + return; + + if (!timer_started(emitter->timer)) { + timer_start(emitter->timer); + return; + } + + if (timer_get_ticks(emitter->timer) < emitter->timestep) + return; + + timer_stop(emitter->timer); + timer_start(emitter->timer); + + if (emitter->particle_func) + emitter->particle_func(emitter->pos, emitter->dim); + else + error("Particle emitter missing particle_func"); +} + +void +particle_emitter_update(ParticleEmitter *emitter, Position pos, Dimension dim) +{ + emitter->pos = pos; + emitter->dim = dim; +} + +void +particle_emitter_destroy(ParticleEmitter *emitter) +{ + timer_destroy(emitter->timer); + emitter->timer = NULL; + free(emitter); +} diff --git a/src/particle_emitter.h b/src/particle_emitter.h new file mode 100644 index 0000000..4d99e19 --- /dev/null +++ b/src/particle_emitter.h @@ -0,0 +1,44 @@ +/* + * BreakHack - A dungeone crawler RPG + * Copyright (C) 2018 Linus Probert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "timer.h" +#include "position.h" +#include "dimension.h" + +typedef struct ParticleEmitter { + unsigned int timestep; + Timer *timer; + Position pos; + Dimension dim; + void (*particle_func)(Position, Dimension); + bool enabled; +} ParticleEmitter; + +ParticleEmitter * +particle_emitter_create(void); + +void +particle_emitter_render(ParticleEmitter*); + +void +particle_emitter_update(ParticleEmitter*, Position, Dimension); + +void +particle_emitter_destroy(ParticleEmitter*); diff --git a/src/particle_engine.c b/src/particle_engine.c index 8bf6dde..be2e6f5 100644 --- a/src/particle_engine.c +++ b/src/particle_engine.c @@ -100,6 +100,12 @@ particle_engine_init(void) engine->global_particles = linkedlist_create(); } +void +particle_engine_bleed(Position pos, Dimension dim) +{ + particle_engine_bloodspray(pos, dim, 5); +} + void particle_engine_bloodspray(Position pos, Dimension dim, unsigned int count) { @@ -254,6 +260,12 @@ particle_engine_speed_lines(Position pos, Dimension dim, bool horizontal) } } +void +particle_engine_bloodlust(Position pos, Dimension dim) +{ + particle_engine_sparkle(pos, dim, C_RED, false); +} + void particle_engine_sparkle(Position pos, Dimension dim, SDL_Color color, bool global) { diff --git a/src/particle_engine.h b/src/particle_engine.h index fb94134..e115d5f 100644 --- a/src/particle_engine.h +++ b/src/particle_engine.h @@ -28,6 +28,9 @@ void particle_engine_init(void); +void +particle_engine_bleed(Position pos, Dimension dim); + void particle_engine_bloodspray(Position, Dimension, unsigned int count); @@ -43,6 +46,9 @@ particle_engine_dust_puff(Position, Dimension); void particle_engine_speed_lines(Position, Dimension, bool horizontal); +void +particle_engine_bloodlust(Position, Dimension); + void particle_engine_sparkle(Position, Dimension, SDL_Color, bool global);