From ebecc68941f5fe9de09c1cb65f62096d30fbd532 Mon Sep 17 00:00:00 2001 From: En Yi Date: Sat, 4 Nov 2023 14:36:59 +0800 Subject: [PATCH] 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 --- engine/EC.h | 1 + engine/assets.c | 1 - engine/particle_sys.c | 4 +-- engine/particle_sys.h | 2 +- particle_test.c | 4 +-- scene_test.c | 2 +- scenes/game_systems.c | 59 ++++++++++++++++++++++++++++--------------- 7 files changed, 46 insertions(+), 27 deletions(-) diff --git a/engine/EC.h b/engine/EC.h index fb322f5..ffc2168 100644 --- a/engine/EC.h +++ b/engine/EC.h @@ -229,6 +229,7 @@ struct Entity { unsigned long components[N_COMPONENTS]; EntityManager_t* manager; bool m_alive; + bool m_active; }; enum EntityUpdateEvent diff --git a/engine/assets.c b/engine/assets.c index 849fb04..462ed34 100644 --- a/engine/assets.c +++ b/engine/assets.c @@ -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]++; diff --git a/engine/particle_sys.c b/engine/particle_sys.c index f2e2f15..3b7154b 100644 --- a/engine/particle_sys.c +++ b/engine/particle_sys.c @@ -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); } } } diff --git a/engine/particle_sys.h b/engine/particle_sys.h index ffc3503..5c21f53 100644 --- a/engine/particle_sys.h +++ b/engine/particle_sys.h @@ -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; diff --git a/particle_test.c b/particle_test.c index dd8d0c2..55246c5 100644 --- a/particle_test.c +++ b/particle_test.c @@ -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; diff --git a/scene_test.c b/scene_test.c index e8d162c..e377199 100644 --- a/scene_test.c +++ b/scene_test.c @@ -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; diff --git a/scenes/game_systems.c b/scenes/game_systems.c index c2b3f49..f953973 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -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)); } }