diff --git a/game/main.c b/game/main.c index 0000668..d1ead4b 100644 --- a/game/main.c +++ b/game/main.c @@ -120,6 +120,7 @@ void loadMap(Game *game, const char *path) { game->camera = (Camera2D){ 0 }; game->camera.target = (Vector2) {0, 0}; + game->camera.offset = (Vector2) { GetScreenWidth() * 0.5f, GetScreenHeight() * 0.5f }; game->camera.rotation = 0.0f; game->camera.zoom = 3.0f; diff --git a/game/systems/s_input.c b/game/systems/s_input.c index ab34b55..2a15dc2 100644 --- a/game/systems/s_input.c +++ b/game/systems/s_input.c @@ -140,16 +140,57 @@ void updatePlayerInput() { Game *game = ecs_singleton_get_mut(ECS, Game); InputState *input = ecs_singleton_get_mut(ECS, InputState); - if (IsKeyDown(KEY_W)) game->camera.target.y -= 5; - if (IsKeyDown(KEY_S)) game->camera.target.y += 5; - if (IsKeyDown(KEY_A)) game->camera.target.x -= 5; - if (IsKeyDown(KEY_D)) game->camera.target.x += 5; + + const f32 maxZoom = 4.5f; + const f32 minZoom = 0.9f; + float moveSpeed = 100.0f * dt * (1 + maxZoom - game->camera.zoom); + if (IsKeyDown(KEY_W)) game->camera.target.y -= moveSpeed; + if (IsKeyDown(KEY_S)) game->camera.target.y += moveSpeed; + if (IsKeyDown(KEY_A)) game->camera.target.x -= moveSpeed; + if (IsKeyDown(KEY_D)) game->camera.target.x += moveSpeed; if (IsKeyDown(KEY_Q)) game->camera.rotation--; if (IsKeyDown(KEY_E)) game->camera.rotation++; + // https://gamedev.stackexchange.com/questions/9330/zoom-to-cursor-calculation + float wheel = GetMouseWheelMove(); + if (wheel != 0.0f) { + const float zoomIncrement = 0.125f; + f32 oldZoom = game->camera.zoom; + f32 newZoom = oldZoom + wheel * zoomIncrement; + newZoom = Clamp(newZoom, minZoom, maxZoom); + + Vector2 mouse = GetMousePosition(); + f32 mapWidth = GetScreenWidth() / oldZoom; + f32 mapHeight = GetScreenHeight() / oldZoom; + f32 widthRatio = (mouse.x - (GetScreenWidth() / 2)) / GetScreenWidth(); + + f32 newMapWidth = GetScreenWidth() / newZoom; + f32 newMapHeight = GetScreenHeight() / newZoom; + f32 heightRatio = (mouse.y - (GetScreenHeight() / 2)) / GetScreenHeight(); + + game->camera.target.x += (mapWidth - newMapWidth) * widthRatio; + game->camera.target.y += (mapHeight - newMapHeight) * heightRatio; + + game->camera.zoom = newZoom; + } + + // Limit camera to world + { + const f32 zoom = game->camera.zoom; + const f32 width = GetScreenWidth() / zoom; + const f32 height = GetScreenHeight() / zoom; + const f32 mapWidth = game->map.width * game->map.tileWidth; + const f32 mapHeight = game->map.height * game->map.tileHeight; + game->camera.target.x = Clamp(game->camera.target.x, + width * 0.5f - game->map.tileWidth, + mapWidth - width + game->map.tileWidth + width * 0.5f); + game->camera.target.y = Clamp(game->camera.target.y, + height * 0.5f - game->map.tileHeight, + mapHeight - height + game->map.tileHeight + height * 0.5f); + } + - game->camera.zoom += GetMouseWheelMove() * 0.05f; BzTileMap *map = &game->map; BzTile tileX = 0, tileY = 0;