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/pointer
|
||||||
src/gui_button
|
src/gui_button
|
||||||
src/particle_engine
|
src/particle_engine
|
||||||
|
src/particle_emitter
|
||||||
src/menu
|
src/menu
|
||||||
src/collisions
|
src/collisions
|
||||||
src/keyboard
|
src/keyboard
|
||||||
|
|
14
Makefile
14
Makefile
|
@ -1,18 +1,18 @@
|
||||||
all:
|
all:
|
||||||
@ninja -C _build/debug
|
@make -C _build/debug
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
release:
|
release:
|
||||||
@ninja -C _build/release
|
@make -C _build/release
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@ninja clean -C _build/debug
|
@make clean -C _build/debug
|
||||||
@ninja clean -C _build/release
|
@make clean -C _build/release
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@ninja test -C _build/debug
|
@make test -C _build/debug
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
||||||
run: $(all)
|
run: $(all)
|
||||||
|
@ -24,9 +24,9 @@ playtest: $(all)
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@ninja lint -C _build/debug
|
@make lint -C _build/debug
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
|
|
||||||
package:
|
package:
|
||||||
@ninja package -C _build/release
|
@make package -C _build/release
|
||||||
.PHONY: package
|
.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*
|
||||||
monster_create(void)
|
monster_create(void)
|
||||||
{
|
{
|
||||||
|
@ -265,9 +283,9 @@ monster_create(void)
|
||||||
m->stateIndicator.shownOnPlayerRoomEnter = false;
|
m->stateIndicator.shownOnPlayerRoomEnter = false;
|
||||||
m->state.forceCount = 0;
|
m->state.forceCount = 0;
|
||||||
m->boss = false;
|
m->boss = false;
|
||||||
m->bloodlust = false;
|
|
||||||
m->items.keyType = LOCK_NONE;
|
m->items.keyType = LOCK_NONE;
|
||||||
monster_set_behaviour(m, NORMAL);
|
monster_set_behaviour(m, NORMAL);
|
||||||
|
create_emitters(m);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -586,6 +604,19 @@ monster_reset_steps(Monster *m)
|
||||||
m->steps = 0;
|
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
|
void
|
||||||
monster_update(Monster *m, UpdateData *data)
|
monster_update(Monster *m, UpdateData *data)
|
||||||
{
|
{
|
||||||
|
@ -593,6 +624,7 @@ monster_update(Monster *m, UpdateData *data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sprite_update(m->sprite, data);
|
sprite_update(m->sprite, data);
|
||||||
|
update_emitters(m);
|
||||||
|
|
||||||
if (m->sprite->state == SPRITE_STATE_PLUMMETED) {
|
if (m->sprite->state == SPRITE_STATE_PLUMMETED) {
|
||||||
m->stats.hp = 0;
|
m->stats.hp = 0;
|
||||||
|
@ -762,13 +794,8 @@ monster_render(Monster *m, Camera *cam)
|
||||||
if (m->stats.hp <= 0)
|
if (m->stats.hp <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m->bloodlust) {
|
particle_emitter_render(m->emitters.bloodlust);
|
||||||
Position pos = m->sprite->pos;
|
particle_emitter_render(m->emitters.bleed);
|
||||||
pos.x += 6;
|
|
||||||
pos.y += 6;
|
|
||||||
particle_engine_sparkle(pos, DIM(20, 20), C_RED, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprite_render(m->sprite, cam);
|
sprite_render(m->sprite, cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,11 +883,11 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction)
|
||||||
void
|
void
|
||||||
monster_set_bloodlust(Monster *m, bool bloodlust)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->bloodlust = bloodlust;
|
m->emitters.bloodlust->enabled = bloodlust;
|
||||||
if (bloodlust) {
|
if (bloodlust) {
|
||||||
gui_log("%s rages with bloodlust", m->label);
|
gui_log("%s rages with bloodlust", m->label);
|
||||||
monster_set_behaviour(m, HOSTILE);
|
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
|
void
|
||||||
monster_destroy(Monster *m)
|
monster_destroy(Monster *m)
|
||||||
{
|
{
|
||||||
|
@ -890,6 +923,10 @@ monster_destroy(Monster *m)
|
||||||
free(m->label);
|
free(m->label);
|
||||||
if (m->lclabel)
|
if (m->lclabel)
|
||||||
free(m->lclabel);
|
free(m->lclabel);
|
||||||
|
|
||||||
|
particle_emitter_destroy(m->emitters.bloodlust);
|
||||||
|
particle_emitter_destroy(m->emitters.bleed);
|
||||||
|
|
||||||
sprite_destroy(m->stateIndicator.sprite);
|
sprite_destroy(m->stateIndicator.sprite);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "linkedlist.h"
|
#include "linkedlist.h"
|
||||||
#include "doorlocktype.h"
|
#include "doorlocktype.h"
|
||||||
|
#include "particle_emitter.h"
|
||||||
|
|
||||||
struct UpdateData;
|
struct UpdateData;
|
||||||
|
|
||||||
|
@ -68,6 +69,11 @@ typedef struct MonsterItems {
|
||||||
enum DoorLockType keyType;
|
enum DoorLockType keyType;
|
||||||
} MonsterItems;
|
} MonsterItems;
|
||||||
|
|
||||||
|
typedef struct ParticleEmitters {
|
||||||
|
ParticleEmitter *bloodlust;
|
||||||
|
ParticleEmitter *bleed;
|
||||||
|
} ParticleEmitters;
|
||||||
|
|
||||||
typedef struct Monster {
|
typedef struct Monster {
|
||||||
char *label;
|
char *label;
|
||||||
char *lclabel;
|
char *lclabel;
|
||||||
|
@ -77,9 +83,9 @@ typedef struct Monster {
|
||||||
MonsterStateIndicator stateIndicator;
|
MonsterStateIndicator stateIndicator;
|
||||||
MonsterBehaviour behaviour;
|
MonsterBehaviour behaviour;
|
||||||
MonsterItems items;
|
MonsterItems items;
|
||||||
|
ParticleEmitters emitters;
|
||||||
unsigned int steps;
|
unsigned int steps;
|
||||||
bool boss;
|
bool boss;
|
||||||
bool bloodlust;
|
|
||||||
} Monster;
|
} Monster;
|
||||||
|
|
||||||
Monster* monster_create(void);
|
Monster* monster_create(void);
|
||||||
|
@ -123,6 +129,9 @@ monster_reset_steps(Monster *m);
|
||||||
void
|
void
|
||||||
monster_set_bloodlust(Monster*, bool bloodlust);
|
monster_set_bloodlust(Monster*, bool bloodlust);
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_bleeding(Monster*);
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_destroy(Monster*);
|
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();
|
engine->global_particles = linkedlist_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_bleed(Position pos, Dimension dim)
|
||||||
|
{
|
||||||
|
particle_engine_bloodspray(pos, dim, 5);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_bloodspray(Position pos, Dimension dim, unsigned int count)
|
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
|
void
|
||||||
particle_engine_sparkle(Position pos, Dimension dim, SDL_Color color, bool global)
|
particle_engine_sparkle(Position pos, Dimension dim, SDL_Color color, bool global)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
void
|
void
|
||||||
particle_engine_init(void);
|
particle_engine_init(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_bleed(Position pos, Dimension dim);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_bloodspray(Position, Dimension, unsigned int count);
|
particle_engine_bloodspray(Position, Dimension, unsigned int count);
|
||||||
|
|
||||||
|
@ -43,6 +46,9 @@ particle_engine_dust_puff(Position, Dimension);
|
||||||
void
|
void
|
||||||
particle_engine_speed_lines(Position, Dimension, bool horizontal);
|
particle_engine_speed_lines(Position, Dimension, bool horizontal);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_bloodlust(Position, Dimension);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_sparkle(Position, Dimension, SDL_Color, bool global);
|
particle_engine_sparkle(Position, Dimension, SDL_Color, bool global);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue