Introduces particle emitters on monsters
Also adds the bleed emitter to monsters for later use with the mage.
This commit is contained in:
parent
826cbe11ff
commit
0476d4d1bd
|
@ -213,6 +213,7 @@ add_executable(breakhack
|
|||
src/pointer
|
||||
src/gui_button
|
||||
src/particle_engine
|
||||
src/particle_emitter
|
||||
src/menu
|
||||
src/collisions
|
||||
src/keyboard
|
||||
|
|
14
Makefile
14
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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#include "particle_emitter.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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*);
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue