From 567c422f8cd42eba2437f9a8c2522716a1649be7 Mon Sep 17 00:00:00 2001 From: hazel Date: Mon, 26 Jan 2026 22:04:39 +0100 Subject: celesteia archive, last updated april 9th 2024 Signed-off-by: hazel --- source/graphics/Camera2D.cs | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 source/graphics/Camera2D.cs (limited to 'source/graphics/Camera2D.cs') diff --git a/source/graphics/Camera2D.cs b/source/graphics/Camera2D.cs new file mode 100644 index 0000000..1bae764 --- /dev/null +++ b/source/graphics/Camera2D.cs @@ -0,0 +1,63 @@ +using System; +using Celesteia.Resources; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Celesteia.Graphics { + public class Camera2D { + private GraphicsDevice _graphicsDevice; + + // Viewport macros. + private int ViewportX => _graphicsDevice.Viewport.X; + private int ViewportY => _graphicsDevice.Viewport.Y; + private int ViewportWidth => _graphicsDevice.Viewport.Width; + private int ViewportHeight => _graphicsDevice.Viewport.Height; + + private int _zoom = 0; + public int ScaledZoom { get; private set; } = 0; + // The zoom value of the camera. + public int Zoom { + get { return _zoom; } + set { + _zoom = MathHelper.Clamp(value, 1, 8); + ScaledZoom = _zoom * ResourceManager.INVERSE_SPRITE_SCALING; + } + } + + public Camera2D(GraphicsDevice graphicsDevice) { + _graphicsDevice = graphicsDevice; + Zoom = 2; + } + + // The camera's center. + public Vector2 Center = Vector2.Zero; + + private float _rotation; + // The rotation applied to the camera. + public float Rotation { + get { return _rotation; } + set { _rotation = value % 360f; } + } + + /* + Creates a matrix with the following steps: + - Create a translation to match (0, 0) to the center point of the camera. + - Apply Z rotation. + - Scale according to zoom value and inverse sprite scaling. + - Always round the viewport width and height to prevent half-pixel rounding issues. + */ + private float maxScale = 0f; + public Matrix GetViewMatrix() { + maxScale = MathF.Max(MathF.Ceiling(ViewportWidth / 1920f), MathF.Ceiling(ViewportHeight / 1080f)); + return Matrix.CreateTranslation(-Center.X, -Center.Y, 0f) * + Matrix.CreateRotationZ(Rotation) * + Matrix.CreateScale(ScaledZoom, ScaledZoom, 1f) * + Matrix.CreateScale(maxScale, maxScale, 1f) * + Matrix.CreateTranslation(ViewportWidth / 2f, ViewportHeight / 2f, 0f); + } + + // Transform the viewport relative mouse position to the inverse view matrix to get the pointer's position in the world. + public Vector2 ScreenToWorld(Point point) + => Vector2.Transform(new Vector2(point.X - ViewportX, point.Y - ViewportY), Matrix.Invert(GetViewMatrix())); + } +} \ No newline at end of file -- cgit v1.2.3