diff --git a/scenes/CMakeLists.txt b/scenes/CMakeLists.txt index 5239a74..0ea5404 100644 --- a/scenes/CMakeLists.txt +++ b/scenes/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(lib_scenes STATIC game_scene.c game_systems.c scene_systems.c + camera_systems.c ) target_include_directories(lib_scenes PUBLIC diff --git a/scenes/camera_systems.c b/scenes/camera_systems.c new file mode 100644 index 0000000..9854e3e --- /dev/null +++ b/scenes/camera_systems.c @@ -0,0 +1,78 @@ +#include "game_systems.h" +#include "ent_impl.h" +#include "raymath.h" + +void camera_update_system(Scene_t* scene) +{ + LevelSceneData_t* data = &CONTAINER_OF(scene, LevelScene_t, scene)->data; + Entity_t* p_player; + const int width = data->game_rec.width; + const int height =data->game_rec.height; + data->camera.cam.offset = (Vector2){ width/2.0f, height/2.0f }; + + Vector2 target_vel = {0}; + sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player) + { + CTransform_t* p_ctransform = get_component(p_player, CTRANSFORM_COMP_T); + data->camera.target_pos.x = p_player->position.x; + target_vel = p_ctransform->velocity; + CMovementState_t* p_movement = get_component(p_player, CMOVEMENTSTATE_T); + CPlayerState_t* p_pstate = get_component(p_player, CPLAYERSTATE_T); + data->camera.target_pos.x += (p_movement->x_dir == 1) ? width/6: -width/6; + + if (p_movement->ground_state == 0b01 + || (p_movement->water_state & 1) + || (p_pstate->ladder_state & 1) + ) + { + data->camera.base_y = p_player->position.y; + } + if (p_player->position.y >= data->camera.base_y) + { + data->camera.target_pos.y = p_player->position.y; + data->camera.target_pos.y += p_ctransform->velocity.y * 0.2; + } + } + data->camera.target_pos.x = Clamp(data->camera.target_pos.x, data->game_rec.width / 2, + fmax(data->tilemap.width * data->tilemap.tile_size, data->game_rec.width) - data->game_rec.width / 2); + data->camera.target_pos.y = Clamp(data->camera.target_pos.y, data->game_rec.height / 2, + fmax(data->tilemap.height * data->tilemap.tile_size, data->game_rec.width) - data->game_rec.height / 2); + + // Mass-Spring damper update in x direction + float x = data->camera.target_pos.x - data->camera.cam.target.x; + float v = data->camera.current_vel.x - target_vel.x; + float F = data->camera.k * x - data->camera.c * v; + // Kinematics update + const float dt = scene->delta_time; + float a_dt = F * dt / data->camera.mass; + data->camera.cam.target.x += (data->camera.current_vel.x + a_dt * 0.5) * dt; + + data->camera.current_vel.x += a_dt; + + // Simple lerp for y direction + float dy = (data->camera.target_pos.y - data->camera.cam.target.y); + data->camera.cam.target.y += dy * 0.1f; + + Vector2 max = GetWorldToScreen2D( + (Vector2){ + fmax(data->tilemap.width * data->tilemap.tile_size, data->game_rec.width), + fmax(data->tilemap.height * data->tilemap.tile_size, data->game_rec.height) + }, + data->camera.cam + ); + Vector2 min = GetWorldToScreen2D((Vector2){0, 0}, data->camera.cam); + + if (max.x < width) + { + data->camera.cam.offset.x = width - (max.x - width/2.0f); + data->camera.cam.target.x = fmax(data->tilemap.width * data->tilemap.tile_size, data->game_rec.width) - (width >> 1); + data->camera.current_vel.x = 0; + } + if (min.x > 0) + { + data->camera.cam.offset.x = (width >> 1) - min.x; + data->camera.cam.target.x = (width >> 1); + data->camera.current_vel.x = 0; + } + +} diff --git a/scenes/game_systems.c b/scenes/game_systems.c index aa90e12..07125d8 100644 --- a/scenes/game_systems.c +++ b/scenes/game_systems.c @@ -2007,81 +2007,6 @@ void sprite_animation_system(Scene_t* scene) } } -void camera_update_system(Scene_t* scene) -{ - LevelSceneData_t* data = &CONTAINER_OF(scene, LevelScene_t, scene)->data; - Entity_t* p_player; - const int width = data->game_rec.width; - const int height =data->game_rec.height; - data->camera.cam.offset = (Vector2){ width/2.0f, height/2.0f }; - - Vector2 target_vel = {0}; - sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_player) - { - CTransform_t* p_ctransform = get_component(p_player, CTRANSFORM_COMP_T); - data->camera.target_pos.x = p_player->position.x; - target_vel = p_ctransform->velocity; - CMovementState_t* p_movement = get_component(p_player, CMOVEMENTSTATE_T); - CPlayerState_t* p_pstate = get_component(p_player, CPLAYERSTATE_T); - data->camera.target_pos.x += (p_movement->x_dir == 1) ? width/6: -width/6; - - if (p_movement->ground_state == 0b01 - || (p_movement->water_state & 1) - || (p_pstate->ladder_state & 1) - ) - { - data->camera.base_y = p_player->position.y; - } - if (p_player->position.y >= data->camera.base_y) - { - data->camera.target_pos.y = p_player->position.y; - data->camera.target_pos.y += p_ctransform->velocity.y * 0.2; - } - } - data->camera.target_pos.x = Clamp(data->camera.target_pos.x, data->game_rec.width / 2, - fmax(data->tilemap.width * TILE_SIZE, data->game_rec.width) - data->game_rec.width / 2); - data->camera.target_pos.y = Clamp(data->camera.target_pos.y, data->game_rec.height / 2, - fmax(data->tilemap.height * TILE_SIZE, data->game_rec.width) - data->game_rec.height / 2); - - // Mass-Spring damper update in x direction - float x = data->camera.target_pos.x - data->camera.cam.target.x; - float v = data->camera.current_vel.x - target_vel.x; - float F = data->camera.k * x - data->camera.c * v; - // Kinematics update - const float dt = scene->delta_time; - float a_dt = F * dt / data->camera.mass; - data->camera.cam.target.x += (data->camera.current_vel.x + a_dt * 0.5) * dt; - - data->camera.current_vel.x += a_dt; - - // Simple lerp for y direction - float dy = (data->camera.target_pos.y - data->camera.cam.target.y); - data->camera.cam.target.y += dy * 0.1f; - - Vector2 max = GetWorldToScreen2D( - (Vector2){ - fmax(data->tilemap.width * TILE_SIZE, data->game_rec.width), - fmax(data->tilemap.height * TILE_SIZE, data->game_rec.height) - }, - data->camera.cam - ); - Vector2 min = GetWorldToScreen2D((Vector2){0, 0}, data->camera.cam); - - if (max.x < width) - { - data->camera.cam.offset.x = width - (max.x - width/2.0f); - data->camera.cam.target.x = fmax(data->tilemap.width * TILE_SIZE, data->game_rec.width) - width / 2; - data->camera.current_vel.x = 0; - } - if (min.x > 0) - { - data->camera.cam.offset.x = width/2.0f - min.x; - data->camera.cam.target.x = width / 2; - data->camera.current_vel.x = 0; - } - -} - void level_end_detection_system(Scene_t* scene) { LevelScene_t* lvl_scene = CONTAINER_OF(scene, LevelScene_t, scene);