Files
Syntriax.Engine/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera2D.cs

112 lines
3.7 KiB
C#

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Engine.Core;
namespace Engine.Integration.MonoGame;
public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw, IUpdate
{
public Event<MonoGameCamera2D> OnViewMatrixChanged { get; } = new();
public Event<MonoGameCamera2D> OnProjectionMatrixChanged { get; } = new();
public Event<MonoGameCamera2D> OnViewportChanged { get; } = new();
public Event<MonoGameCamera2D> OnZoomChanged { get; } = new();
public GraphicsDeviceManager Graphics { get; private set; } = null!;
public ITransform2D Transform { get; private set; } = null!;
public Matrix4x4 ProjectionMatrix
{
get;
private set
{
if (field == value)
return;
field = value;
OnProjectionMatrixChanged.Invoke(this);
}
} = Matrix4x4.Identity;
public Matrix4x4 ViewMatrix
{
get;
private set
{
if (field == value)
return;
field = value;
OnViewMatrixChanged.Invoke(this);
}
} = Matrix4x4.Identity;
public Viewport Viewport
{
get;
set
{
if (field.Equals(value))
return;
field = value;
OnViewportChanged.Invoke(this);
}
} = default;
public float Zoom
{
get;
set
{
float newValue = Math.Max(0.1f, value);
if (field == newValue)
return;
field = newValue;
OnZoomChanged.Invoke(this);
}
} = 1f;
// TODO This causes delay since OnPreDraw calls assuming this is called in in Update
public Vector2D ScreenToWorldPosition(Vector2D screenPosition)
{
Vector2D worldPosition = Vector2.Transform(screenPosition.ToVector2(), ViewMatrix.Inverse.ToXnaMatrix()).ToVector2D();
return worldPosition.Scale(EngineConverterExtensions.screenScale);
}
public Vector2D WorldToScreenPosition(Vector2D worldPosition)
{
Vector2D screenPosition = Vector2.Transform(worldPosition.ToVector2(), ViewMatrix.ToXnaMatrix()).ToVector2D();
return screenPosition.Scale(EngineConverterExtensions.screenScale);
}
public void LastActiveFrame() => Transform = null!;
public void FirstActiveFrame()
{
Graphics = BehaviourController.UniverseObject.Universe.FindRequiredBehaviour<MonoGameWindowContainer>().Window.Graphics;
Viewport = Graphics.GraphicsDevice.Viewport;
Transform = BehaviourController.GetRequiredBehaviour<ITransform2D>();
}
public void PreDraw()
{
ProjectionMatrix = Matrix4x4.CreateOrthographicViewCentered(Viewport.Width, -Viewport.Height);
ViewMatrix =
Matrix4x4.CreateTranslation(new Vector3D(-Transform.Position.X, Transform.Position.Y, 0f))
.ApplyRotationZ(Transform.Rotation * Math.DegreeToRadian)
.ApplyScale(Transform.Scale.X.Max(Transform.Scale.Y))
.ApplyScale(Zoom);
}
public void Update()
{
KeyboardInputs keyboardInputs = Universe.FindRequiredBehaviour<KeyboardInputs>();
if (keyboardInputs.IsPressed(Keys.Right)) Transform.Position += Transform.Right * Universe.Time.DeltaTime * 100;
if (keyboardInputs.IsPressed(Keys.Up)) Transform.Position += Transform.Up * Universe.Time.DeltaTime * 100;
if (keyboardInputs.IsPressed(Keys.Down)) Transform.Position += Transform.Down * Universe.Time.DeltaTime * 100;
if (keyboardInputs.IsPressed(Keys.Left)) Transform.Position += Transform.Left * Universe.Time.DeltaTime * 100;
}
}