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
scene_man
En Yi 2023-11-02 22:44:52 +08:00
parent 43aa821c18
commit a8b62f5aec
6 changed files with 77 additions and 3 deletions

View File

@ -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_map_init_64(&scene->action_map, 32, 0);
sc_array_init(&scene->systems); sc_array_init(&scene->systems);
init_entity_manager(&scene->ent_manager); init_entity_manager(&scene->ent_manager);
init_particle_system(&scene->part_sys);
//scene->scene_type = scene_type; //scene->scene_type = scene_type;
scene->render_function = render_func; scene->render_function = render_func;
@ -106,6 +107,7 @@ void free_scene(Scene_t* scene)
sc_map_term_64(&scene->action_map); sc_map_term_64(&scene->action_map);
sc_array_term(&scene->systems); sc_array_term(&scene->systems);
free_entity_manager(&scene->ent_manager); free_entity_manager(&scene->ent_manager);
deinit_particle_system(&scene->part_sys);
} }
inline void update_scene(Scene_t* scene) inline void update_scene(Scene_t* scene)
@ -115,6 +117,7 @@ inline void update_scene(Scene_t* scene)
{ {
sys(scene); sys(scene);
} }
update_particle_system(&scene->part_sys);
} }
inline void render_scene(Scene_t* scene) inline void render_scene(Scene_t* scene)

View File

@ -22,7 +22,6 @@ typedef struct GameEngine {
unsigned int curr_scene; unsigned int curr_scene;
Assets_t assets; Assets_t assets;
SFXList_t sfx_list; SFXList_t sfx_list;
ParticleSystem_t part_sys;
// Maintain own queue to handle key presses // Maintain own queue to handle key presses
struct sc_queue_32 key_buffer; struct sc_queue_32 key_buffer;
} GameEngine_t; } GameEngine_t;
@ -50,6 +49,7 @@ struct Scene {
EntityManager_t ent_manager; EntityManager_t ent_manager;
//SceneType_t scene_type; //SceneType_t scene_type;
SceneState_t state; SceneState_t state;
ParticleSystem_t part_sys;
GameEngine_t *engine; GameEngine_t *engine;
}; };

View File

@ -14,7 +14,7 @@ static GameEngine_t engine =
.max_scenes = 1, .max_scenes = 1,
.curr_scene = 0, .curr_scene = 0,
.assets = {0}, .assets = {0},
.sfx_list = {0} .sfx_list = {0},
}; };
void update_loop(void) void update_loop(void)
@ -35,7 +35,6 @@ int main(void)
InitAudioDevice(); InitAudioDevice();
init_engine(&engine); init_engine(&engine);
#ifndef NDEBUG #ifndef NDEBUG
load_from_infofile("res/assets.info.raw", &engine.assets); load_from_infofile("res/assets.info.raw", &engine.assets);
init_player_creation("res/player_spr.info", &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_bland", BOULDER_LAND_SFX);
load_sfx(&engine, "snd_bubble", BUBBLE_SFX); load_sfx(&engine, "snd_bubble", BUBBLE_SFX);
LevelScene_t scene; LevelScene_t scene;
scene.scene.engine = &engine; scene.scene.engine = &engine;
init_sandbox_scene(&scene); init_sandbox_scene(&scene);
@ -68,6 +68,15 @@ int main(void)
scenes[0] = &scene.scene; scenes[0] = &scene.scene;
change_scene(&engine, 0); 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) #if defined(PLATFORM_WEB)
puts("Setting emscripten main loop"); puts("Setting emscripten main loop");
emscripten_set_main_loop(update_loop, 0, 1); emscripten_set_main_loop(update_loop, 0, 1);

View File

@ -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; unsigned int y = ((p_runner->current_tile) / tilemap.width) * tilemap.tile_size;
DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6)); 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_y = min.y; tile_y < max.y; tile_y++)
{ {
for (int tile_x = min.x; tile_x < max.x; tile_x++) for (int tile_x = min.x; tile_x < max.x; tile_x++)

View File

@ -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; unsigned int y = ((p_runner->current_tile) / tilemap.width) * tilemap.tile_size;
DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6)); DrawCircle(x+16, y+16, 8, ColorAlpha(BLUE, 0.6));
} }
draw_particle_system(&scene->part_sys);
// Draw Border // Draw Border
DrawLine(0, 0, 0, tilemap.height * tilemap.tile_size, BLACK); DrawLine(0, 0, 0, tilemap.height * tilemap.tile_size, BLACK);

View File

@ -1,10 +1,13 @@
#include "game_systems.h" #include "game_systems.h"
#include "particle_sys.h"
#include "ent_impl.h" #include "ent_impl.h"
#include "AABB.h" #include "AABB.h"
#include "EC.h" #include "EC.h"
#include "constants.h" #include "constants.h"
#include <stdio.h> #include <stdio.h>
void simple_particle_system_update(Particle_t* part, void* user_data);
static const Vector2 GRAVITY = {0, GRAV_ACCEL}; static const Vector2 GRAVITY = {0, GRAV_ACCEL};
static const Vector2 UPTHRUST = {0, -GRAV_ACCEL * 1.1}; static const Vector2 UPTHRUST = {0, -GRAV_ACCEL * 1.1};
typedef enum AnchorPoint { 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); Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx);
if (!p_ent->m_alive) 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; Entity_t* dmg_src = NULL;
CHurtbox_t* p_hurtbox = get_component(p_ent, CHURTBOX_T); 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;
}
}
}