From a8b62f5aec72d03d8bf592445f6e726a11cb898f Mon Sep 17 00:00:00 2001 From: En Yi Date: Thu, 2 Nov 2023 22:44:52 +0800 Subject: [PATCH] Integrate particle system into scenes Changelog: - Each scene will have its own particle system to maintain - Crate destruction now emits particles - Draw particles during screen renders - May want to make this configurable - Should be in general scene render --- engine/engine.c | 3 +++ engine/engine.h | 2 +- scene_test.c | 13 ++++++++-- scenes/editor_scene.c | 3 +++ scenes/game_scene.c | 1 + scenes/game_systems.c | 58 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 3 deletions(-) diff --git a/engine/engine.c b/engine/engine.c index cdd47be..c45c945 100644 --- a/engine/engine.c +++ b/engine/engine.c @@ -94,6 +94,7 @@ void init_scene(Scene_t* scene, system_func_t render_func, action_func_t action_ sc_map_init_64(&scene->action_map, 32, 0); sc_array_init(&scene->systems); init_entity_manager(&scene->ent_manager); + init_particle_system(&scene->part_sys); //scene->scene_type = scene_type; scene->render_function = render_func; @@ -106,6 +107,7 @@ void free_scene(Scene_t* scene) sc_map_term_64(&scene->action_map); sc_array_term(&scene->systems); free_entity_manager(&scene->ent_manager); + deinit_particle_system(&scene->part_sys); } inline void update_scene(Scene_t* scene) @@ -115,6 +117,7 @@ inline void update_scene(Scene_t* scene) { sys(scene); } + update_particle_system(&scene->part_sys); } inline void render_scene(Scene_t* scene) diff --git a/engine/engine.h b/engine/engine.h index b9f3d3c..48bef79 100644 --- a/engine/engine.h +++ b/engine/engine.h @@ -22,7 +22,6 @@ typedef struct GameEngine { unsigned int curr_scene; Assets_t assets; SFXList_t sfx_list; - ParticleSystem_t part_sys; // Maintain own queue to handle key presses struct sc_queue_32 key_buffer; } GameEngine_t; @@ -50,6 +49,7 @@ struct Scene { EntityManager_t ent_manager; //SceneType_t scene_type; SceneState_t state; + ParticleSystem_t part_sys; GameEngine_t *engine; }; diff --git a/scene_test.c b/scene_test.c index 8c17d62..e8d162c 100644 --- a/scene_test.c +++ b/scene_test.c @@ -14,7 +14,7 @@ static GameEngine_t engine = .max_scenes = 1, .curr_scene = 0, .assets = {0}, - .sfx_list = {0} + .sfx_list = {0}, }; void update_loop(void) @@ -35,7 +35,6 @@ int main(void) InitAudioDevice(); init_engine(&engine); - #ifndef NDEBUG load_from_infofile("res/assets.info.raw", &engine.assets); init_player_creation("res/player_spr.info", &engine.assets); @@ -56,6 +55,7 @@ int main(void) load_sfx(&engine, "snd_bland", BOULDER_LAND_SFX); load_sfx(&engine, "snd_bubble", BUBBLE_SFX); + LevelScene_t scene; scene.scene.engine = &engine; init_sandbox_scene(&scene); @@ -68,6 +68,15 @@ 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")); + conf->launch_range[0] = 240; + conf->launch_range[1] = 300; + conf->one_shot = true; + conf->speed_range[0] = 200; + conf->speed_range[1] = 300; + conf->particle_lifetime[0] = 30; + conf->particle_lifetime[1] = 110; + #if defined(PLATFORM_WEB) puts("Setting emscripten main loop"); emscripten_set_main_loop(update_loop, 0, 1); diff --git a/scenes/editor_scene.c b/scenes/editor_scene.c index 40192a0..2106165 100644 --- a/scenes/editor_scene.c +++ b/scenes/editor_scene.c @@ -448,6 +448,9 @@ static void render_editor_game_scene(Scene_t* scene) unsigned int y = ((p_runner->current_tile) / tilemap.width) * tilemap.tile_size; DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6)); } + + draw_particle_system(&scene->part_sys); + for (int tile_y = min.y; tile_y < max.y; tile_y++) { for (int tile_x = min.x; tile_x < max.x; tile_x++) diff --git a/scenes/game_scene.c b/scenes/game_scene.c index 6041411..e641981 100644 --- a/scenes/game_scene.c +++ b/scenes/game_scene.c @@ -319,6 +319,7 @@ static void render_regular_game_scene(Scene_t* scene) unsigned int y = ((p_runner->current_tile) / tilemap.width) * tilemap.tile_size; DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6)); } + draw_particle_system(&scene->part_sys); // Draw Border DrawLine(0, 0, 0, tilemap.height * tilemap.tile_size, BLACK); diff --git a/scenes/game_systems.c b/scenes/game_systems.c index 538b07f..c2b3f49 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -1,10 +1,13 @@ #include "game_systems.h" +#include "particle_sys.h" #include "ent_impl.h" #include "AABB.h" #include "EC.h" #include "constants.h" #include +void simple_particle_system_update(Particle_t* part, void* user_data); + static const Vector2 GRAVITY = {0, GRAV_ACCEL}; static const Vector2 UPTHRUST = {0, -GRAV_ACCEL * 1.1}; typedef enum AnchorPoint { @@ -1627,6 +1630,19 @@ 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); @@ -1927,3 +1943,45 @@ void level_end_detection_system(Scene_t* scene) } } + +void simple_particle_system_update(Particle_t* part, void* user_data) +{ + LevelSceneData_t* lvl_data = (LevelSceneData_t*)user_data; + TileGrid_t tilemap = lvl_data->tilemap; + + float delta_time = DELTA_T; // TODO: Will need to think about delta time handling + part->velocity = + Vector2Add( + part->velocity, + Vector2Scale(GRAVITY, delta_time) + ); + + float mag = Vector2Length(part->velocity); + part->velocity = Vector2Scale( + Vector2Normalize(part->velocity), + (mag > PLAYER_MAX_SPEED)? PLAYER_MAX_SPEED:mag + ); + // 3 dp precision + if (fabs(part->velocity.x) < 1e-3) part->velocity.x = 0; + if (fabs(part->velocity.y) < 1e-3) part->velocity.y = 0; + + part->position = Vector2Add( + part->position, + Vector2Scale(part->velocity, delta_time) + ); + + // Level boundary collision + unsigned int level_width = tilemap.width * TILE_SIZE; + unsigned int level_height = tilemap.height * TILE_SIZE; + { + + if( + part->position.x < 0 || part->position.x + part->size > level_width + || part->position.y < 0 || part->position.y + part->size > level_height + ) + { + part->timer = 0; + } + } +} +