fix: ScreenToWorldPosition & vice versa methods on MonoGameCamera2D fixed

This commit is contained in:
2026-01-28 11:06:15 +03:00
parent e30280f1f8
commit efa4da4398

View File

@@ -1,12 +1,11 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Engine.Core; using Engine.Core;
namespace Engine.Integration.MonoGame; namespace Engine.Integration.MonoGame;
public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw, IUpdate public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw
{ {
public Event<MonoGameCamera2D> OnViewMatrixChanged { get; } = new(); public Event<MonoGameCamera2D> OnViewMatrixChanged { get; } = new();
public Event<MonoGameCamera2D> OnProjectionMatrixChanged { get; } = new(); public Event<MonoGameCamera2D> OnProjectionMatrixChanged { get; } = new();
@@ -73,13 +72,34 @@ public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFr
// TODO This causes delay since OnPreDraw calls assuming this is called in in Update // TODO This causes delay since OnPreDraw calls assuming this is called in in Update
public Vector2D ScreenToWorldPosition(Vector2D screenPosition) public Vector2D ScreenToWorldPosition(Vector2D screenPosition)
{ {
Vector2D worldPosition = Vector2.Transform(screenPosition.ToVector2(), ViewMatrix.Inverse.ToXnaMatrix()).ToVector2D(); float x = 2f * screenPosition.X / Viewport.Width - 1f;
return worldPosition.Scale(EngineConverterExtensions.screenScale); float y = 2f * screenPosition.Y / Viewport.Height - 1f;
Vector4D normalizedCoordinates = new(x, y, 0f, 1f);
Matrix4x4 invertedViewProjectionMatrix = (ProjectionMatrix * ViewMatrix).Inverse;
Vector4D worldPosition = invertedViewProjectionMatrix * normalizedCoordinates;
if (worldPosition.W != 0f)
worldPosition /= worldPosition.W;
return new(worldPosition.X, worldPosition.Y);
} }
public Vector2D WorldToScreenPosition(Vector2D worldPosition) public Vector2D WorldToScreenPosition(Vector2D worldPosition)
{ {
Vector2D screenPosition = Vector2.Transform(worldPosition.ToVector2(), ViewMatrix.ToXnaMatrix()).ToVector2D(); Vector4D worldPosition4D = new(worldPosition.X, worldPosition.Y, 0f, 1f);
return screenPosition.Scale(EngineConverterExtensions.screenScale);
Matrix4x4 viewProjection = ProjectionMatrix * ViewMatrix;
Vector4D clip = viewProjection * worldPosition4D;
if (clip.W != 0f)
clip /= clip.W;
float screenX = (clip.X + 1f) * .5f * Viewport.Width;
float screenY = (clip.Y + 1f) * .5f * Viewport.Height;
return new(screenX, screenY);
} }
public void LastActiveFrame() => Transform = null!; public void LastActiveFrame() => Transform = null!;
@@ -99,13 +119,4 @@ public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFr
.ApplyScale(Transform.Scale.X.Max(Transform.Scale.Y)) .ApplyScale(Transform.Scale.X.Max(Transform.Scale.Y))
.ApplyScale(Zoom); .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;
}
} }