Zoom the god camera toward the cursor

The mouse-wheel zoom now keeps the world point under the cursor fixed
(cursor-anchored zoom) by shifting the camera position after applying the
new zoom, instead of zooming around the camera centre. GodCameraSystem
takes the renderer to map the cursor to world space.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Leonid Pershin
2026-06-12 13:29:49 +03:00
co-authored by Claude Opus 4.8
parent 26e234a35e
commit 9f67c478a2
2 changed files with 21 additions and 4 deletions
+3 -1
View File
@@ -101,7 +101,9 @@ public sealed class WorldScene : Scene
RegisterCommands(console, content, atlases); RegisterCommands(console, content, atlases);
UpdateSystems.Add(new PlantGrowthSystem(plants, calendar, CellSize)); UpdateSystems.Add(new PlantGrowthSystem(plants, calendar, CellSize));
UpdateSystems.Add(new GodCameraSystem(camera, input, console, () => _pause.IsOpen)); UpdateSystems.Add(
new GodCameraSystem(camera, input, renderer, console, () => _pause.IsOpen)
);
UpdateSystems.Add( UpdateSystems.Add(
new HudSystem(Context, content.Languages, hudLabel, "hud.world", _config.Seed, calendar) new HudSystem(Context, content.Languages, hudLabel, "hud.world", _config.Seed, calendar)
); );
+18 -3
View File
@@ -117,12 +117,14 @@ public sealed class SeparationSystem(MrGameEng.Collisions.CollisionWorld world)
} }
/// <summary> /// <summary>
/// Камера бога: WASD/стрелки — панорамирование, колесо — зум. Молчит, пока открыта консоль /// Камера бога: WASD/стрелки — панорамирование, колесо — зум к курсору (мировая точка под мышью
/// или активен <paramref name="blocked"/> (например, открыто меню-пауза). /// остаётся под мышью). Молчит, пока открыта консоль или активен <paramref name="blocked"/>
/// (например, открыто меню-пауза).
/// </summary> /// </summary>
public sealed class GodCameraSystem( public sealed class GodCameraSystem(
Entity cameraEntity, Entity cameraEntity,
InputManager input, InputManager input,
Renderer2D renderer,
MrGameEng.DevConsole.DevConsole console, MrGameEng.DevConsole.DevConsole console,
Func<bool>? blocked = null Func<bool>? blocked = null
) : BaseSystem ) : BaseSystem
@@ -146,7 +148,20 @@ public sealed class GodCameraSystem(
camera.Position += pan * (500f / camera.Zoom) * Tick.deltaTime; camera.Position += pan * (500f / camera.Zoom) * Tick.deltaTime;
} }
camera.Zoom = Math.Clamp(camera.Zoom * (1f + input.WheelDelta * 0.001f), 0.4f, 8f); if (input.WheelDelta != 0)
{
var oldZoom = camera.Zoom;
var newZoom = Math.Clamp(oldZoom * (1f + input.WheelDelta * 0.001f), 0.4f, 8f);
if (newZoom != oldZoom)
{
// Точка мира под курсором до зума; после — сдвигаем камеру, чтобы она осталась там же.
var anchor = renderer.ScreenToWorld(
new Vector2(input.MousePosition.X, input.MousePosition.Y)
);
camera.Zoom = newZoom;
camera.Position = anchor - (anchor - camera.Position) * (oldZoom / newZoom);
}
}
} }
private static float Axis( private static float Axis(