Implement level ending

Internal Changelog:
- Activate on collected chest == all chest
- Add spawning level end entity
- Level ending in sandbox will just reset the scene
scene_man
En Yi 2023-09-25 22:04:13 +08:00
parent d54fee8935
commit ce8284ab39
6 changed files with 85 additions and 3 deletions

View File

@ -26,9 +26,10 @@ enum EntitySpawnSelection {
SPAWN_CRATE_BOMB, SPAWN_CRATE_BOMB,
SPAWN_BOULDER, SPAWN_BOULDER,
SPAWN_WATER_RUNNER, SPAWN_WATER_RUNNER,
SPAWN_LEVEL_END,
}; };
#define MAX_SPAWN_TYPE 15 #define MAX_SPAWN_TYPE 16
static unsigned int current_spawn_selection = 0; static unsigned int current_spawn_selection = 0;
static bool metal_toggle = false; static bool metal_toggle = false;
static bool crate_activation = false; static bool crate_activation = false;
@ -58,6 +59,7 @@ static char* get_spawn_selection_string(enum EntitySpawnSelection sel)
case SPAWN_CRATE_BOMB: return (metal_toggle) ? "metal bomb crate" : "wooden bomb crate"; case SPAWN_CRATE_BOMB: return (metal_toggle) ? "metal bomb crate" : "wooden bomb crate";
case SPAWN_BOULDER: return "boulder"; case SPAWN_BOULDER: return "boulder";
case SPAWN_WATER_RUNNER: return "water runner"; case SPAWN_WATER_RUNNER: return "water runner";
case SPAWN_LEVEL_END: return "level end";
default: return "unknown"; default: return "unknown";
} }
} }
@ -330,6 +332,12 @@ static void level_scene_render_func(Scene_t* scene)
} }
} }
sc_map_foreach_value(&scene->ent_manager.entities_map[LEVEL_END_TAG], p_ent)
{
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
DrawCircleV(p_ct->position, tilemap.tile_size >> 1, (data->coins.current < data->coins.total)? RED : GREEN);
}
sc_map_foreach_value(&scene->ent_manager.entities_map[DYNMEM_ENT_TAG], p_ent) sc_map_foreach_value(&scene->ent_manager.entities_map[DYNMEM_ENT_TAG], p_ent)
{ {
CWaterRunner_t* p_runner = get_component(p_ent, CWATERRUNNER_T); CWaterRunner_t* p_runner = get_component(p_ent, CWATERRUNNER_T);
@ -597,6 +605,17 @@ static void toggle_block_system(Scene_t* scene)
} }
} }
break; break;
case SPAWN_LEVEL_END:
{
Entity_t* p_ent = create_level_end(&scene->ent_manager, &scene->engine->assets);
if (p_ent != NULL)
{
CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T);
p_ct->position.x = (tile_idx % tilemap.width) * tilemap.tile_size + (tilemap.tile_size >> 1);
p_ct->position.y = (tile_idx / tilemap.width) * tilemap.tile_size + (tilemap.tile_size >> 1);;
}
}
break;
case SPAWN_CHEST: case SPAWN_CHEST:
if (data->coins.total < 65535) if (data->coins.total < 65535)
{ {
@ -717,6 +736,11 @@ static void restart_editor_level(Scene_t* scene)
} }
} }
} }
Entity_t* p_ent;
sc_map_foreach_value(&scene->ent_manager.entities_map[LEVEL_END_TAG], p_ent)
{
remove_entity(&scene->ent_manager, p_ent->m_id);
}
update_entity_manager(&scene->ent_manager); update_entity_manager(&scene->ent_manager);
for (size_t i = 0; i < tilemap.width; ++i) for (size_t i = 0; i < tilemap.width; ++i)
{ {
@ -828,6 +852,7 @@ static void level_do_action(Scene_t* scene, ActionType_t action, bool pressed)
change_scene(scene->engine, 0); change_scene(scene->engine, 0);
} }
break; break;
case ACTION_NEXTLEVEL:
case ACTION_RESTART: case ACTION_RESTART:
restart_editor_level(scene); restart_editor_level(scene);
break; break;
@ -862,7 +887,7 @@ void init_sandbox_scene(LevelScene_t* scene)
BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5), BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5),
ColorAlpha(RAYWHITE, 0.5), YELLOW, crate_colour, crate_colour, crate_colour, ColorAlpha(RAYWHITE, 0.5), YELLOW, crate_colour, crate_colour, crate_colour,
crate_colour, crate_colour, crate_colour, crate_colour, crate_colour, crate_colour,
ColorAlpha(RAYWHITE, 0.5), ColorAlpha(RAYWHITE, 0.5) ColorAlpha(RAYWHITE, 0.5), ColorAlpha(RAYWHITE, 0.5), ColorAlpha(RAYWHITE, 0.5)
}; };
for (uint8_t i = 0; i < MAX_SPAWN_TYPE; ++i) for (uint8_t i = 0; i < MAX_SPAWN_TYPE; ++i)
{ {
@ -918,6 +943,9 @@ void init_sandbox_scene(LevelScene_t* scene)
case SPAWN_WATER_RUNNER: case SPAWN_WATER_RUNNER:
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, ColorAlpha(BLUE, 0.2)); DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, ColorAlpha(BLUE, 0.2));
break; break;
case SPAWN_LEVEL_END:
DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, GREEN);
break;
case TOGGLE_AIR_POCKET: case TOGGLE_AIR_POCKET:
DrawRectangleLinesEx((Rectangle){draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE}, 2.0, ColorAlpha(BLUE, 0.5)); DrawRectangleLinesEx((Rectangle){draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE}, 2.0, ColorAlpha(BLUE, 0.5));
break; break;
@ -961,6 +989,7 @@ void init_sandbox_scene(LevelScene_t* scene)
sc_array_add(&scene->scene.systems, &player_dir_reset_system); sc_array_add(&scene->scene.systems, &player_dir_reset_system);
sc_array_add(&scene->scene.systems, &update_water_runner_system); sc_array_add(&scene->scene.systems, &update_water_runner_system);
sc_array_add(&scene->scene.systems, &player_respawn_system); sc_array_add(&scene->scene.systems, &player_respawn_system);
sc_array_add(&scene->scene.systems, &level_end_detection_system);
sc_array_add(&scene->scene.systems, &toggle_block_system); sc_array_add(&scene->scene.systems, &toggle_block_system);
// This avoid graphical glitch, not essential // This avoid graphical glitch, not essential

View File

@ -6,7 +6,7 @@
#include "sc/map/sc_map.h" #include "sc/map/sc_map.h"
#include "sc/queue/sc_queue.h" #include "sc/queue/sc_queue.h"
#define N_TAGS 8 #define N_TAGS 10
#define N_COMPONENTS 13 #define N_COMPONENTS 13
#define MAX_COMP_POOL_SIZE 1024 #define MAX_COMP_POOL_SIZE 1024
typedef struct EntityManager EntityManager_t; typedef struct EntityManager EntityManager_t;

View File

@ -9,6 +9,7 @@ typedef enum EntityTag {
CRATES_ENT_TAG, CRATES_ENT_TAG,
CHEST_ENT_TAG, CHEST_ENT_TAG,
BOULDER_ENT_TAG, BOULDER_ENT_TAG,
LEVEL_END_TAG,
DESTRUCTABLE_ENT_TAG, DESTRUCTABLE_ENT_TAG,
DYNMEM_ENT_TAG, DYNMEM_ENT_TAG,
} EntityTag_t; } EntityTag_t;
@ -27,5 +28,6 @@ Entity_t* create_arrow(EntityManager_t* ent_manager, Assets_t* assets, uint8_t d
Entity_t* create_bomb(EntityManager_t* ent_manager, Assets_t* assets, Vector2 launch_dir); Entity_t* create_bomb(EntityManager_t* ent_manager, Assets_t* assets, Vector2 launch_dir);
Entity_t* create_explosion(EntityManager_t* ent_manager, Assets_t* assets); Entity_t* create_explosion(EntityManager_t* ent_manager, Assets_t* assets);
Entity_t* create_chest(EntityManager_t* ent_manager, Assets_t* assets); Entity_t* create_chest(EntityManager_t* ent_manager, Assets_t* assets);
Entity_t* create_level_end(EntityManager_t* ent_manager, Assets_t* assets);
#endif // __ENT_IMPL_H #endif // __ENT_IMPL_H

View File

@ -1732,3 +1732,44 @@ void camera_update_system(Scene_t* scene)
if (min.x > 0) lvl_scene->data.cam.offset.x = width/2.0f - min.x; if (min.x > 0) lvl_scene->data.cam.offset.x = width/2.0f - min.x;
if (min.y > 0) lvl_scene->data.cam.offset.y = height/2.0f - min.y; if (min.y > 0) lvl_scene->data.cam.offset.y = height/2.0f - min.y;
} }
void level_end_detection_system(Scene_t* scene)
{
LevelScene_t* lvl_scene = CONTAINER_OF(scene, LevelScene_t, scene);
if (lvl_scene->data.coins.current < lvl_scene->data.coins.total) return;
Entity_t* p_flag;
TileGrid_t tilemap = lvl_scene->data.tilemap;
sc_map_foreach_value(&scene->ent_manager.entities_map[LEVEL_END_TAG], p_flag)
{
CTransform_t* p_ct = get_component(p_flag, CTRANSFORM_COMP_T);
unsigned int tile_idx = get_tile_idx(
p_ct->position.x,
p_ct->position.y,
tilemap.width
);
unsigned int other_ent_idx;
Entity_t* p_other_ent;
sc_map_foreach(&tilemap.tiles[tile_idx].entities_set, other_ent_idx, p_other_ent)
{
if (p_other_ent->m_tag != PLAYER_ENT_TAG) continue;
CTransform_t* p_other_ct = get_component(p_other_ent, CTRANSFORM_COMP_T);
CBBox_t* p_other_bbox = get_component(p_other_ent, CBBOX_COMP_T);
Vector2 overlap;
Vector2 pos = Vector2Subtract(p_ct->position,(Vector2){tilemap.tile_size >> 1, tilemap.tile_size >> 1});
if (
find_AABB_overlap(
pos, (Vector2){tilemap.tile_size, tilemap.tile_size},
p_other_ct->position, p_other_bbox->size, &overlap
)
)
{
do_action(scene, ACTION_NEXTLEVEL, true);
}
}
}
}

View File

@ -24,5 +24,6 @@ void player_dir_reset_system(Scene_t* scene);
void player_respawn_system(Scene_t* scene); void player_respawn_system(Scene_t* scene);
void lifetimer_update_system(Scene_t* scene); void lifetimer_update_system(Scene_t* scene);
void spike_collision_system(Scene_t* scene); void spike_collision_system(Scene_t* scene);
void level_end_detection_system(Scene_t* scene);
#endif // __GAME_SYSTEMS_H #endif // __GAME_SYSTEMS_H

View File

@ -225,3 +225,12 @@ Entity_t* create_chest(EntityManager_t* ent_manager, Assets_t* assets)
return p_chest; return p_chest;
} }
Entity_t* create_level_end(EntityManager_t* ent_manager, Assets_t* assets)
{
Entity_t* p_flag = add_entity(ent_manager, LEVEL_END_TAG);
if (p_flag == NULL) return NULL;
add_component(p_flag, CTRANSFORM_COMP_T);
return p_flag;
}