diff --git a/scenes/editor_scene.c b/scenes/editor_scene.c index ddae0b2..14c74fa 100644 --- a/scenes/editor_scene.c +++ b/scenes/editor_scene.c @@ -18,10 +18,11 @@ enum EntitySpawnSelection { TOGGLE_WATER, SPAWN_CRATE, SPAWN_METAL_CRATE, + SPAWN_CRATE_ARROW_L, SPAWN_BOULDER, }; -#define MAX_SPAWN_TYPE 8 +#define MAX_SPAWN_TYPE 9 static unsigned int current_spawn_selection = 0; #define SELECTION_TILE_SIZE 32 @@ -138,14 +139,51 @@ static void level_scene_render_func(Scene_t* scene) break; } - if (p_ent->m_tag == BOULDER_ENT_TAG) + if (p_bbox != NULL) { - DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, colour); - } - else - { - DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour); + if (p_ent->m_tag == BOULDER_ENT_TAG) + { + DrawCircleV(Vector2Add(p_ct->position, p_bbox->half_size), p_bbox->half_size.x, colour); + } + else + { + DrawRectangle(p_ct->position.x, p_ct->position.y, p_bbox->size.x, p_bbox->size.y, colour); + } + + if (p_ent->m_tag == CRATES_ENT_TAG) + { + CContainer_t* p_container = get_component(p_ent, CCONTAINER_T); + if (p_container != NULL) + { + switch (p_container->item) + { + case CONTAINER_LEFT_ARROW: + DrawLine( + p_ct->position.x + p_bbox->half_size.x, + p_ct->position.y + p_bbox->half_size.y, + p_ct->position.x + p_bbox->size.x, + p_ct->position.y + p_bbox->half_size.y, + BLACK + ); + break; + default: + break; + } + } + } + + //if (p_ent->m_tag == ARROW_ENT_TAG) + //{ + // DrawLine( + // p_ct->position.x + 10, + // p_ct->position.y + p_bbox->half_size.y, + // p_ct->position.x + p_bbox->size.x, + // p_ct->position.y + p_bbox->half_size.y, + // colour + // ); + //} } + CHurtbox_t* p_hurtbox = get_component(p_ent, CHURTBOX_T); CHitBoxes_t* p_hitbox = get_component(p_ent, CHITBOXES_T); if (p_hitbox != NULL) @@ -228,22 +266,29 @@ static void level_scene_render_func(Scene_t* scene) ); Vector2 draw_pos = {data->game_rec.x, data->game_rec.y + data->game_rec.height + SELECTION_GAP}; - const Color draw_colour[MAX_SPAWN_TYPE] = {BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5), BROWN, GRAY, ColorAlpha(RAYWHITE, 0.5)}; + const Color draw_colour[MAX_SPAWN_TYPE] = {BLACK, MAROON, ORANGE, ColorAlpha(RAYWHITE, 0.5), ColorAlpha(BLUE, 0.5), BROWN, GRAY, BROWN, ColorAlpha(RAYWHITE, 0.5)}; for (uint8_t i = 0; i < MAX_SPAWN_TYPE; ++i) { if (i != current_spawn_selection) { DrawRectangle(draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, draw_colour[i]); + Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE}; switch (i) { - case 3: + case TOGGLE_SPIKE: DrawRectangle(draw_pos.x, draw_pos.y + SELECTION_TILE_HALFSIZE, SELECTION_TILE_SIZE, SELECTION_TILE_HALFSIZE, RED); break; - case 7: - { - Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE}; + case SPAWN_BOULDER: DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, GRAY); - } + break; + case SPAWN_CRATE_ARROW_L: + DrawLine( + draw_pos.x + half_size.x, + draw_pos.y + half_size.y, + draw_pos.x + half_size.x * 2, + draw_pos.y + half_size.y, + BLACK + ); break; } } @@ -256,16 +301,23 @@ static void level_scene_render_func(Scene_t* scene) SELECTION_TILE_SIZE + 4, SELECTION_TILE_SIZE + 4, GREEN ); DrawRectangle(draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, draw_colour[current_spawn_selection]); + const Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE}; switch (current_spawn_selection) { - case 3: + case TOGGLE_SPIKE: DrawRectangle(draw_pos.x, draw_pos.y + SELECTION_TILE_HALFSIZE, SELECTION_TILE_SIZE, SELECTION_TILE_HALFSIZE, RED); break; - case 7: - { - const Vector2 half_size = {SELECTION_TILE_HALFSIZE, SELECTION_TILE_HALFSIZE}; + case SPAWN_BOULDER: DrawCircleV(Vector2Add(draw_pos, half_size), half_size.x, GRAY); - } + break; + case SPAWN_CRATE_ARROW_L: + DrawLine( + draw_pos.x + half_size.x, + draw_pos.y + half_size.y, + draw_pos.x + half_size.x * 2, + draw_pos.y + half_size.y, + BLACK + ); break; } @@ -305,10 +357,10 @@ static void level_scene_render_func(Scene_t* scene) EndDrawing(); } -static void spawn_crate(Scene_t* scene, unsigned int tile_idx, bool metal) +static void spawn_crate(Scene_t* scene, unsigned int tile_idx, bool metal, ContainerItem_t item) { LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data); - Entity_t* p_crate = create_crate(&scene->ent_manager, &scene->engine->assets, metal); + Entity_t* p_crate = create_crate(&scene->ent_manager, &scene->engine->assets, metal, item); CTransform_t* p_ctransform = get_component(p_crate, CTRANSFORM_COMP_T); p_ctransform->position.x = (tile_idx % data->tilemap.width) * TILE_SIZE; @@ -420,14 +472,17 @@ static void toggle_block_system(Scene_t* scene) } break; case SPAWN_CRATE: - spawn_crate(scene, tile_idx, false); + spawn_crate(scene, tile_idx, false, CONTAINER_EMPTY); break; case SPAWN_METAL_CRATE: - spawn_crate(scene, tile_idx, true); + spawn_crate(scene, tile_idx, true, CONTAINER_EMPTY); break; case SPAWN_BOULDER: spawn_boulder(scene, tile_idx); break; + case SPAWN_CRATE_ARROW_L: + spawn_crate(scene, tile_idx, false, CONTAINER_LEFT_ARROW); + break; } if (tilemap.tiles[tile_idx].tile_type == SPIKES) @@ -591,6 +646,7 @@ void init_level_scene(LevelScene_t* scene) sc_array_add(&scene->scene.systems, &spike_collision_system); 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, &container_destroy_system); sc_array_add(&scene->scene.systems, &sprite_animation_system); sc_array_add(&scene->scene.systems, &camera_update_system); sc_array_add(&scene->scene.systems, &player_dir_reset_system); diff --git a/scenes/engine/EC/EC.h b/scenes/engine/EC/EC.h index 6d37d9a..889e560 100644 --- a/scenes/engine/EC/EC.h +++ b/scenes/engine/EC/EC.h @@ -6,7 +6,7 @@ #include "sc/map/sc_map.h" #include "sc/queue/sc_queue.h" -#define N_TAGS 5 +#define N_TAGS 8 #define N_COMPONENTS 11 #define MAX_COMP_POOL_SIZE 1024 typedef struct EntityManager EntityManager_t; @@ -110,6 +110,7 @@ typedef struct _CHitBoxes_t { Rectangle boxes[2]; uint8_t n_boxes; uint8_t atk; + bool one_hit; } CHitBoxes_t; typedef struct _CHurtbox_t { diff --git a/scenes/ent_impl.h b/scenes/ent_impl.h index 19c0978..b07ffec 100644 --- a/scenes/ent_impl.h +++ b/scenes/ent_impl.h @@ -8,12 +8,14 @@ typedef enum EntityTag { ENEMY_ENT_TAG, CRATES_ENT_TAG, BOULDER_ENT_TAG, + ARROW_ENT_TAG, } EntityTag_t; bool init_player_creation(const char* info_file, Assets_t* assets); Entity_t* create_player(EntityManager_t* ent_manager, Assets_t* assets); -Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal); +Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal, ContainerItem_t item); Entity_t* create_boulder(EntityManager_t* ent_manager, Assets_t* assets); +Entity_t* create_arrow(EntityManager_t* ent_manager, Assets_t* assets, uint8_t dir); #endif // __ENT_IMPL_H diff --git a/scenes/game_systems.c b/scenes/game_systems.c index 2669e2f..c15a47a 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -975,7 +975,7 @@ void friction_coefficient_update_system(Scene_t* scene) // Friction - if (p_mstate->water_state & 1) + if (p_mstate != NULL && p_mstate->water_state & 1) { // Apply water friction // Consistent in all direction @@ -1352,6 +1352,8 @@ void movement_update_system(Scene_t* scene) // Level boundary collision Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx); CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T); + if (p_bbox == NULL) continue; + unsigned int level_width = tilemap.width * TILE_SIZE; if(p_ctransform->position.x < 0 || p_ctransform->position.x + p_bbox->size.x > level_width) { @@ -1523,7 +1525,7 @@ void update_tilemap_system(Scene_t* scene) void hitbox_update_system(Scene_t* scene) { - static bool checked_entities[MAX_COMP_POOL_SIZE] = {0}; + //static bool checked_entities[MAX_COMP_POOL_SIZE] = {0}; LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data); TileGrid_t tilemap = data->tilemap; @@ -1534,6 +1536,7 @@ void hitbox_update_system(Scene_t* scene) sc_map_foreach(&scene->ent_manager.component_map[CHITBOXES_T], ent_idx, p_hitbox) { 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); for (uint8_t i = 0; i < p_hitbox->n_boxes; ++i) { @@ -1554,15 +1557,15 @@ void hitbox_update_system(Scene_t* scene) unsigned int tile_idx = tile_y * tilemap.width + tile_x; unsigned int other_ent_idx; Entity_t* p_other_ent; - memset(checked_entities, 0, sizeof(checked_entities)); + //memset(checked_entities, 0, sizeof(checked_entities)); sc_map_foreach(&tilemap.tiles[tile_idx].entities_set, other_ent_idx, p_other_ent) { if (other_ent_idx == ent_idx) continue; - if (checked_entities[other_ent_idx]) continue; + //if (checked_entities[other_ent_idx]) continue; Entity_t* p_other_ent = get_entity(&scene->ent_manager, other_ent_idx); if (!p_other_ent->m_alive) continue; // To only allow one way collision check - if (p_other_ent->m_tag < p_ent->m_tag) continue; // To only allow one way collision check + //if (p_other_ent->m_tag < p_ent->m_tag) continue; // To only allow one way collision check CHurtbox_t* p_other_hurtbox = get_component(p_other_ent, CHURTBOX_T); if (p_other_hurtbox == NULL) continue; @@ -1578,13 +1581,14 @@ void hitbox_update_system(Scene_t* scene) ) ) { - //if (p_other_ent->m_tag == CRATES_ENT_TAG) + if (p_other_ent->m_tag == CRATES_ENT_TAG) { CBBox_t* p_bbox = get_component(p_ent, CBBOX_COMP_T); CPlayerState_t* p_pstate = get_component(p_ent, CPLAYERSTATE_T); if ( - p_ctransform->position.y + p_bbox->size.y <= p_other_ct->position.y + p_pstate != NULL + && p_ctransform->position.y + p_bbox->size.y <= p_other_ct->position.y ) { p_ctransform->velocity.y = -400; @@ -1596,25 +1600,40 @@ void hitbox_update_system(Scene_t* scene) p_cjump->jumped = true; } } + } + CTileCoord_t* p_tilecoord = get_component( + p_other_ent, CTILECOORD_COMP_T + ); - CTileCoord_t* p_tilecoord = get_component( - p_other_ent, CTILECOORD_COMP_T + for (size_t i = 0;i < p_tilecoord->n_tiles; ++i) + { + // Use previously store tile position + // Clear from those positions + unsigned int tile_idx = p_tilecoord->tiles[i]; + sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), other_ent_idx); + } + remove_entity(&scene->ent_manager, other_ent_idx); + if (p_hitbox->one_hit) + { + p_tilecoord = get_component( + p_ent, CTILECOORD_COMP_T ); - for (size_t i = 0;i < p_tilecoord->n_tiles; ++i) { // Use previously store tile position // Clear from those positions unsigned int tile_idx = p_tilecoord->tiles[i]; - sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), other_ent_idx); + sc_map_del_64v(&(tilemap.tiles[tile_idx].entities_set), ent_idx); } - remove_entity(&scene->ent_manager, other_ent_idx); + remove_entity(&scene->ent_manager, ent_idx); + goto hitbox_done; } } } } } } +hitbox_done: continue; } } @@ -1658,6 +1677,33 @@ void boulder_destroy_wooden_tile_system(Scene_t* scene) } } +void container_destroy_system(Scene_t* scene) +{ + unsigned int ent_idx; + CContainer_t* p_container; + sc_map_foreach(&scene->ent_manager.component_map[CCONTAINER_T], ent_idx, p_container) + { + Entity_t* p_ent = get_entity(&scene->ent_manager, ent_idx); + if (!p_ent->m_alive) + { + Entity_t* new_ent; + switch (p_container->item) + { + case CONTAINER_LEFT_ARROW: + { + new_ent = create_arrow(&scene->ent_manager, &scene->engine->assets, 0); + CTransform_t* new_p_ct = get_component(new_ent, CTRANSFORM_COMP_T); + CTransform_t* p_ct = get_component(p_ent, CTRANSFORM_COMP_T); + memcpy(&new_p_ct->position, &p_ct->position, sizeof(Vector2)); + } + break; + default: + break; + } + } + } +} + void sprite_animation_system(Scene_t* scene) { unsigned int ent_idx; diff --git a/scenes/game_systems.h b/scenes/game_systems.h index a9032e6..20f4ba2 100644 --- a/scenes/game_systems.h +++ b/scenes/game_systems.h @@ -20,6 +20,7 @@ void hitbox_update_system(Scene_t* scene); void sprite_animation_system(Scene_t* scene); void boulder_destroy_wooden_tile_system(Scene_t* scene); void camera_update_system(Scene_t* scene); +void container_destroy_system(Scene_t* scene); void player_dir_reset_system(Scene_t* scene); void player_respawn_system(Scene_t* scene); void spike_collision_system(Scene_t* scene); diff --git a/scenes/items_ent.c b/scenes/items_ent.c index 64ec239..b5e1811 100644 --- a/scenes/items_ent.c +++ b/scenes/items_ent.c @@ -1,7 +1,7 @@ #include "ent_impl.h" #include "constants.h" -Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal) +Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool metal, ContainerItem_t item) { Entity_t* p_crate = add_entity(ent_manager, CRATES_ENT_TAG); CBBox_t* p_bbox = add_component(p_crate, CBBOX_COMP_T); @@ -17,6 +17,13 @@ Entity_t* create_crate(EntityManager_t* ent_manager, Assets_t* assets, bool meta CHurtbox_t* p_hurtbox = add_component(p_crate, CHURTBOX_T); p_hurtbox->size = p_bbox->size; p_hurtbox->def = metal ? 2 : 1; + + if (item != CONTAINER_EMPTY) + { + CContainer_t* p_container = add_component(p_crate, CCONTAINER_T); + p_container->item = item; + } + return p_crate; } @@ -41,3 +48,21 @@ Entity_t* create_boulder(EntityManager_t* ent_manager, Assets_t* assets) p_hurtbox->def = 2; return p_boulder; } + +Entity_t* create_arrow(EntityManager_t* ent_manager, Assets_t* assets, uint8_t dir) +{ + Entity_t* p_arrow = add_entity(ent_manager, ARROW_ENT_TAG); + add_component(p_arrow, CTILECOORD_COMP_T); + CHitBoxes_t* p_hitbox = add_component(p_arrow, CHITBOXES_T); + p_hitbox->n_boxes = 1; + p_hitbox->boxes[0] = (Rectangle){TILE_SIZE - 5, TILE_SIZE / 2 - 5, 5, 5}; + p_hitbox->atk = 3; + p_hitbox->one_hit = true; + + CTransform_t* p_ctransform = add_component(p_arrow, CTRANSFORM_COMP_T); + p_ctransform->movement_mode = KINEMATIC_MOVEMENT; + p_ctransform->velocity.x = 500; + p_ctransform->active = true; + + return p_arrow; +}