Add better support for particle system

Changelog:
- Move sprite to emitter itself to allow better reusing emitter config
- Dedicate a function for destroying entity. This is helpful for dealing
  with events that only occurs during entity destruction
scene_man
En Yi 2023-11-04 14:36:59 +08:00
parent e4bd3fdcab
commit ebecc68941
7 changed files with 46 additions and 27 deletions

View File

@ -229,6 +229,7 @@ struct Entity {
unsigned long components[N_COMPONENTS];
EntityManager_t* manager;
bool m_alive;
bool m_active;
};
enum EntityUpdateEvent

View File

@ -147,7 +147,6 @@ EmitterConfig_t* add_emitter_conf(Assets_t* assets, const char* name, Sprite_t*
uint8_t emitter_idx = n_loaded[5];
assert(emitter_idx < MAX_EMITTER_CONF);
memset(emitter_confs + emitter_idx, 0, sizeof(EmitterConfData_t));
emitter_confs[emitter_idx].conf.spr = sprite;
strncpy(emitter_confs[emitter_idx].name, name, MAX_NAME_LEN);
sc_map_put_s64(&assets->m_emitter_confs, emitter_confs[emitter_idx].name, emitter_idx);
n_loaded[5]++;

View File

@ -121,7 +121,7 @@ void draw_particle_system(ParticleSystem_t* system)
{
if (part->alive)
{
if (emitter->config->spr == NULL)
if (emitter->spr == NULL)
{
Rectangle rect = {
.x = part->position.x,
@ -137,7 +137,7 @@ void draw_particle_system(ParticleSystem_t* system)
}
else
{
draw_sprite(emitter->config->spr, part->position, part->rotation, false);
draw_sprite(emitter->spr, part->position, part->rotation, false);
}
}
}

View File

@ -32,13 +32,13 @@ typedef struct EmitterConfig
float speed_range[2];
uint32_t particle_lifetime[2];
PartEmitterType_t type;
Sprite_t* spr;
bool one_shot;
}EmitterConfig_t;
typedef struct ParticleEmitter
{
const EmitterConfig_t* config;
Sprite_t* spr;
Vector2 position;
Particle_t particles[MAX_PARTICLES];
uint32_t n_particles;

View File

@ -69,13 +69,13 @@ int main(void)
.launch_range = {0, 360},
.speed_range = {400, 2000},
.particle_lifetime = {30, 110},
.spr = (tex.width == 0) ? NULL : &spr,
};
ParticleEmitter_t emitter = {
.config = &conf,
.n_particles = MAX_PARTICLES,
.update_func = &simple_particle_system_update
.update_func = &simple_particle_system_update,
.spr = (tex.width == 0) ? NULL : &spr,
};
bool key_press = false;

View File

@ -68,7 +68,7 @@ int main(void)
scenes[0] = &scene.scene;
change_scene(&engine, 0);
EmitterConfig_t* conf = add_emitter_conf(&engine.assets, "pe_wood", get_sprite(&engine.assets, "bomb"));
EmitterConfig_t* conf = add_emitter_conf(&engine.assets, "pe_burst", get_sprite(&engine.assets, "bomb"));
conf->launch_range[0] = 240;
conf->launch_range[1] = 300;
conf->one_shot = true;

View File

@ -194,6 +194,39 @@ static Vector2 shift_bbox(Vector2 bbox, Vector2 new_bbox, AnchorPoint_t anchor)
return offset;
}
void destroy_entity(Scene_t* scene, TileGrid_t* tilemap, Entity_t* p_ent)
{
if (p_ent->m_tag == BOULDER_ENT_TAG)
{
const CTransform_t* p_ctransform = get_component(p_ent, CTRANSFORM_COMP_T);
//const CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
ParticleEmitter_t emitter = {
.spr = get_sprite(&scene->engine->assets, "p_rock"),
.config = get_emitter_conf(&scene->engine->assets, "pe_burst"),
.position = p_ctransform->position,
.n_particles = 5,
.user_data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data),
.update_func = &simple_particle_system_update,
};
play_particle_emitter(&scene->part_sys, &emitter);
}
else if (p_ent->m_tag == CRATES_ENT_TAG)
{
const CTransform_t* p_ctransform = get_component(p_ent, CTRANSFORM_COMP_T);
//const CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
ParticleEmitter_t emitter = {
.spr = get_sprite(&scene->engine->assets, "p_wood"),
.config = get_emitter_conf(&scene->engine->assets, "pe_burst"),
.position = p_ctransform->position,
.n_particles = 5,
.user_data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data),
.update_func = &simple_particle_system_update,
};
play_particle_emitter(&scene->part_sys, &emitter);
}
remove_entity_from_tilemap(&scene->ent_manager, tilemap, p_ent);
}
void player_respawn_system(Scene_t* scene)
{
Entity_t* p_player;
@ -1219,7 +1252,7 @@ void movement_update_system(Scene_t* scene)
|| p_ctransform->position.y < 0 || p_ctransform->position.y > level_height
)
{
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, p_ent);
destroy_entity(scene, &tilemap, p_ent);
}
}
@ -1555,13 +1588,13 @@ void hitbox_update_system(Scene_t* scene)
{
remove_component(p_other_ent, CHURTBOX_T);
CLifeTimer_t* p_clifetimer = add_component(p_other_ent, CLIFETIMER_T);
p_clifetimer->life_time = 6;
p_clifetimer->life_time = 3;
}
}
else
{
// Need to remove immediately, otherwise will interfere with bomb spawning
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, p_other_ent);
destroy_entity(scene, &tilemap, p_other_ent);
if (p_other_ent->m_tag == CHEST_ENT_TAG)
{
data->coins.current++;
@ -1576,7 +1609,7 @@ void hitbox_update_system(Scene_t* scene)
}
if (p_hitbox->one_hit && hit)
{
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, p_ent);
destroy_entity(scene, &tilemap, p_ent);
}
}
}
@ -1630,20 +1663,6 @@ void container_destroy_system(Scene_t* scene)
Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx);
if (!p_ent->m_alive)
{
if (p_ent->m_tag == CRATES_ENT_TAG)
{
const CTransform_t* p_ctransform = get_component(p_ent, CTRANSFORM_COMP_T);
//const CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T);
ParticleEmitter_t emitter = {
.config = get_emitter_conf(&scene->engine->assets, "pe_wood"),
.position = p_ctransform->position,
.n_particles = 3,
.user_data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data),
.update_func = &simple_particle_system_update,
};
play_particle_emitter(&scene->part_sys, &emitter);
}
Entity_t* dmg_src = NULL;
CHurtbox_t* p_hurtbox = get_component(p_ent, CHURTBOX_T);
if(p_hurtbox != NULL)
@ -1717,7 +1736,7 @@ void lifetimer_update_system(Scene_t* scene)
p_lifetimer->life_time--;
if (p_lifetimer->life_time == 0)
{
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, get_entity(&scene->ent_manager, ent_idx));
destroy_entity(scene, &tilemap, get_entity(&scene->ent_manager, ent_idx));
}
}
}
@ -1786,7 +1805,7 @@ void airtimer_update_system(Scene_t* scene)
}
else
{
remove_entity_from_tilemap(&scene->ent_manager, &tilemap, get_entity(&scene->ent_manager, ent_idx));
destroy_entity(scene, &tilemap, get_entity(&scene->ent_manager, ent_idx));
}
}