diff --git a/scenes/editor_scene.c b/scenes/editor_scene.c index a8e3435..bd9914f 100644 --- a/scenes/editor_scene.c +++ b/scenes/editor_scene.c @@ -430,6 +430,9 @@ static void level_scene_render_func(Scene_t* scene) CJump_t* p_cjump = get_component(p_ent, CJUMP_COMP_T); CPlayerState_t* p_pstate = get_component(p_ent, CPLAYERSTATE_T); CMovementState_t* p_mstate = get_component(p_ent, CMOVEMENTSTATE_T); + + CAirTimer_t* p_air = get_component(p_ent, CAIRTIMER_T); + sprintf(buffer, "Pos: %.3f\n %.3f", p_ct->position.x, p_ct->position.y); DrawText(buffer, gui_x, gui_y, 12, BLACK); sprintf(buffer, "Vel: %.3f\n %.3f", p_ct->velocity.x, p_ct->velocity.y); @@ -448,6 +451,13 @@ static void level_scene_render_func(Scene_t* scene) sprintf(buffer, "Ladder: %u", p_pstate->ladder_state); DrawText(buffer, gui_x, gui_y, 12, BLACK); gui_y += 30; + + Vector2 air_pos = {data->game_rec.x + data->game_rec.width - 16, data->game_rec.y + data->game_rec.height - 16}; + for (uint8_t i = 0; i < p_air->curr_count; i++) + { + DrawCircleV(air_pos, 16, BLUE); + air_pos.x -= 32; + } } #endif //sprintf(buffer, "Spawn Entity: %s", get_spawn_selection_string(current_spawn_selection)); @@ -983,6 +993,7 @@ void init_sandbox_scene(LevelScene_t* scene) sc_array_add(&scene->scene.systems, &state_transition_update_system); sc_array_add(&scene->scene.systems, &player_ground_air_transition_system); sc_array_add(&scene->scene.systems, &lifetimer_update_system); + sc_array_add(&scene->scene.systems, &airtimer_update_system); sc_array_add(&scene->scene.systems, &container_destroy_system); sc_array_add(&scene->scene.systems, &sprite_animation_system); sc_array_add(&scene->scene.systems, &camera_update_system); diff --git a/scenes/engine/EC/EC.h b/scenes/engine/EC/EC.h index fd9da1f..47ed2f2 100644 --- a/scenes/engine/EC/EC.h +++ b/scenes/engine/EC/EC.h @@ -7,13 +7,13 @@ #include "sc/queue/sc_queue.h" #define N_TAGS 10 -#define N_COMPONENTS 13 +#define N_COMPONENTS 14 #define MAX_COMP_POOL_SIZE 1024 typedef struct EntityManager EntityManager_t; typedef struct Entity Entity_t; typedef enum ComponentEnum { - CBBOX_COMP_T, + CBBOX_COMP_T = 0, CTRANSFORM_COMP_T, CTILECOORD_COMP_T, CMOVEMENTSTATE_T, @@ -26,6 +26,7 @@ typedef enum ComponentEnum { CMOVEABLE_T, CLIFETIMER_T, CWATERRUNNER_T, + CAIRTIMER_T, } ComponentEnum_t; typedef enum MovementMode { @@ -58,6 +59,7 @@ typedef struct _CTransform_t { typedef struct _CMovementState_t { uint8_t ground_state; uint8_t water_state; + uint8_t x_dir; } CMovementState_t; // This is to store the occupying tiles @@ -129,6 +131,14 @@ typedef struct _CLifeTimer_t { uint8_t life_time; } CLifeTimer_t; +typedef struct _CAirTimer_t { + uint8_t max_count; + uint8_t curr_count; + uint16_t max_ftimer; + uint16_t curr_ftimer; + uint16_t decay_rate; +} CAirTimer_t; + typedef struct _BFSTile { int32_t to; int32_t from; diff --git a/scenes/engine/EC/mempool.c b/scenes/engine/EC/mempool.c index 8a03845..3cd1d99 100644 --- a/scenes/engine/EC/mempool.c +++ b/scenes/engine/EC/mempool.c @@ -5,22 +5,6 @@ #include #include -// Static allocate buffers -static Entity_t entity_buffer[MAX_COMP_POOL_SIZE]; -static CBBox_t bbox_buffer[MAX_COMP_POOL_SIZE]; -static CTransform_t ctransform_buffer[MAX_COMP_POOL_SIZE]; -static CTileCoord_t ctilecoord_buffer[MAX_COMP_POOL_SIZE]; -static CMovementState_t cmstate_buffer[MAX_COMP_POOL_SIZE]; -static CJump_t cjump_buffer[8]; // Only player is expected to have this -static CPlayerState_t cplayerstate_buffer[8]; // Only player is expected to have this -static CContainer_t ccontainer_buffer[MAX_COMP_POOL_SIZE]; -static CHitBoxes_t chitboxes_buffer[MAX_COMP_POOL_SIZE]; -static CHurtbox_t churtbox_buffer[MAX_COMP_POOL_SIZE]; -static CSprite_t csprite_buffer[MAX_COMP_POOL_SIZE]; -static CMoveable_t cmoveable_buffer[MAX_COMP_POOL_SIZE]; -static CLifeTimer_t clifetimer_buffer[MAX_COMP_POOL_SIZE]; -static CWaterRunner_t cwaterrunner_buffer[32]; - typedef struct ULongCircBuffer { unsigned long* buffer; // data buffer unsigned long* buffer_end; // end of data buffer @@ -77,6 +61,23 @@ typedef struct MemPool { ULongCircBuffer_t free_list; } MemPool_t; +// Static allocate buffers +static Entity_t entity_buffer[MAX_COMP_POOL_SIZE]; +static CBBox_t bbox_buffer[MAX_COMP_POOL_SIZE]; +static CTransform_t ctransform_buffer[MAX_COMP_POOL_SIZE]; +static CTileCoord_t ctilecoord_buffer[MAX_COMP_POOL_SIZE]; +static CMovementState_t cmstate_buffer[MAX_COMP_POOL_SIZE]; +static CJump_t cjump_buffer[8]; // Only player is expected to have this +static CPlayerState_t cplayerstate_buffer[8]; // Only player is expected to have this +static CContainer_t ccontainer_buffer[MAX_COMP_POOL_SIZE]; +static CHitBoxes_t chitboxes_buffer[MAX_COMP_POOL_SIZE]; +static CHurtbox_t churtbox_buffer[MAX_COMP_POOL_SIZE]; +static CSprite_t csprite_buffer[MAX_COMP_POOL_SIZE]; +static CMoveable_t cmoveable_buffer[MAX_COMP_POOL_SIZE]; +static CLifeTimer_t clifetimer_buffer[MAX_COMP_POOL_SIZE]; +static CWaterRunner_t cwaterrunner_buffer[32]; +static CAirTimer_t cairtimer_buffer[8]; // Only player is expected to have this + // Static allocate mempools static MemPool_t comp_mempools[N_COMPONENTS] = { {bbox_buffer, MAX_COMP_POOL_SIZE, sizeof(CBBox_t), NULL, {0}}, @@ -92,6 +93,7 @@ static MemPool_t comp_mempools[N_COMPONENTS] = { {cmoveable_buffer, MAX_COMP_POOL_SIZE, sizeof(CMoveable_t), NULL, {0}}, {clifetimer_buffer, MAX_COMP_POOL_SIZE, sizeof(CLifeTimer_t), NULL, {0}}, {cwaterrunner_buffer, 32, sizeof(CWaterRunner_t), NULL, {0}}, + {cairtimer_buffer, 8, sizeof(CAirTimer_t), NULL, {0}}, }; static MemPool_t ent_mempool = { .buffer = entity_buffer, diff --git a/scenes/game_systems.c b/scenes/game_systems.c index 7df2bd7..0990542 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -1258,6 +1258,9 @@ void state_transition_update_system(Scene_t* scene) CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T); if (p_ctransform == NULL || p_bbox == NULL) continue; + if (p_ctransform->velocity.x > 0) p_mstate->x_dir = 1; + else if (p_ctransform->velocity.x < 0) p_mstate->x_dir = 0; + bool on_ground = check_on_ground( p_ent, p_ctransform->position, p_ctransform->prev_position, p_bbox->size, &data->tilemap @@ -1669,6 +1672,78 @@ void lifetimer_update_system(Scene_t* scene) } } +void airtimer_update_system(Scene_t* scene) +{ + LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data); + TileGrid_t tilemap = data->tilemap; + unsigned int ent_idx; + CAirTimer_t* p_air; + sc_map_foreach(&scene->ent_manager.component_map[CAIRTIMER_T], ent_idx, p_air) + { + Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx); + if (!p_ent->m_alive) continue; + CTransform_t* p_ctransform = get_component(p_ent, CTRANSFORM_COMP_T); + CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T); + CMovementState_t* p_movement = get_component(p_ent, CMOVEMENTSTATE_T); + if (p_ctransform == NULL || p_bbox == NULL || p_movement == NULL) continue; + + Vector2 point_to_check = { + (p_movement->x_dir == 0) ? p_ctransform->position.x : p_ctransform->position.x + p_bbox->size.x, + p_ctransform->position.y + p_bbox->half_size.y, + }; + + unsigned int tile_idx = get_tile_idx( + point_to_check.x, + point_to_check.y, + tilemap.width + ); + + bool in_water = false; + int tile_x = tile_idx % tilemap.width; + int tile_y = tile_idx / tilemap.width; + uint32_t water_height = data->tilemap.tiles[tile_idx].water_level * WATER_BBOX_STEP; + Vector2 tl = {tile_x * data->tilemap.tile_size, (tile_y + 1) * data->tilemap.tile_size - water_height}; + in_water |= point_in_AABB( + point_to_check, + (Rectangle){tl.x, tl.y, tilemap.tile_size, water_height} + ); + + if (!in_water) + { + p_air->curr_count = p_air->max_count; + p_air->curr_ftimer = p_air->max_ftimer * 2; // Lengthen the first + } + + if (p_movement->water_state & 1) + { + if (p_air->curr_ftimer > p_air->decay_rate) + { + p_air->curr_ftimer -= p_air->decay_rate; + } + else + { + if (p_air->curr_count > 0) + { + p_air->curr_count--; + p_air->curr_ftimer = p_air->max_ftimer; + } + else + { + if (p_ent->m_tag == PLAYER_ENT_TAG) + { + p_ent->m_alive = false; + } + else + { + remove_entity_from_tilemap(&scene->ent_manager, &tilemap, get_entity(&scene->ent_manager, ent_idx)); + } + } + + } + } + } +} + void sprite_animation_system(Scene_t* scene) { unsigned int ent_idx; diff --git a/scenes/game_systems.h b/scenes/game_systems.h index c46ef04..61c61a9 100644 --- a/scenes/game_systems.h +++ b/scenes/game_systems.h @@ -23,6 +23,7 @@ void container_destroy_system(Scene_t* scene); void player_dir_reset_system(Scene_t* scene); void player_respawn_system(Scene_t* scene); void lifetimer_update_system(Scene_t* scene); +void airtimer_update_system(Scene_t* scene); void spike_collision_system(Scene_t* scene); void level_end_detection_system(Scene_t* scene); diff --git a/scenes/player_ent.c b/scenes/player_ent.c index 5f67dcd..c2ab0b4 100644 --- a/scenes/player_ent.c +++ b/scenes/player_ent.c @@ -93,6 +93,12 @@ Entity_t* create_player(EntityManager_t* ent_manager, Assets_t* assets) CHurtbox_t* p_hurtbox = add_component(p_ent, CHURTBOX_T); p_hurtbox->size = p_bbox->size; + CAirTimer_t* p_air = add_component(p_ent, CAIRTIMER_T); + p_air->max_count = 10; + p_air->curr_count = 10; + p_air->max_ftimer = 300; + p_air->decay_rate = 5; + CSprite_t* p_cspr = add_component(p_ent, CSPRITE_T); p_cspr->sprites = player_sprite_map; p_cspr->transition_func = &player_sprite_transition_func;