rigidbody, forces and collision testing
This commit is contained in:
188
PhysicsEngine/Graphics/Camera.cs
Normal file
188
PhysicsEngine/Graphics/Camera.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using Raylib_cs;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace PhysicsEngine
|
||||
{
|
||||
public class Camera
|
||||
{
|
||||
public const float PixelsPerMeter = 100.0f;
|
||||
private const float GridSpacing = 1.0f; // meters
|
||||
private const float ZoomLerpSpeed = 30.0f;
|
||||
private const float MoveLerpSpeed = 20.0f;
|
||||
private const float ZoomFactor = 0.1f;
|
||||
private const float MinZoom = 0.2f;
|
||||
private const float MaxZoom = 50.0f;
|
||||
|
||||
public Camera2D RaylibCamera { get; private set; }
|
||||
public Vector2 Position => RaylibCamera.Target / PixelsPerMeter;
|
||||
public float Zoom => RaylibCamera.Zoom;
|
||||
|
||||
private float targetZoom;
|
||||
private Vector2 targetPosition;
|
||||
private Vector2 dragStartMouseScreen;
|
||||
private Vector2 dragStartTarget;
|
||||
private bool isDragging = false;
|
||||
|
||||
public Camera()
|
||||
{
|
||||
RaylibCamera = new Camera2D
|
||||
{
|
||||
Target = Vector2.Zero,
|
||||
Offset = new Vector2(Raylib.GetScreenWidth() / 2.0f, Raylib.GetScreenHeight() / 2.0f),
|
||||
Rotation = 0.0f,
|
||||
Zoom = 1.0f
|
||||
};
|
||||
|
||||
targetZoom = 1.0f;
|
||||
targetPosition = RaylibCamera.Target;
|
||||
}
|
||||
|
||||
public void Update(float frameTime)
|
||||
{
|
||||
Camera2D cam = RaylibCamera;
|
||||
cam.Offset = new Vector2(Raylib.GetScreenWidth() / 2.0f, Raylib.GetScreenHeight() / 2.0f);
|
||||
|
||||
// panning
|
||||
if (Raylib.IsMouseButtonPressed(MouseButton.Middle))
|
||||
{
|
||||
isDragging = true;
|
||||
dragStartMouseScreen = Raylib.GetMousePosition();
|
||||
dragStartTarget = targetPosition;
|
||||
}
|
||||
|
||||
if (isDragging)
|
||||
{
|
||||
if (Raylib.IsMouseButtonDown(MouseButton.Middle))
|
||||
{
|
||||
Vector2 currentMouseScreen = Raylib.GetMousePosition();
|
||||
Vector2 screenDelta = currentMouseScreen - dragStartMouseScreen;
|
||||
|
||||
targetPosition = dragStartTarget - (screenDelta / cam.Zoom);
|
||||
cam.Target = targetPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
isDragging = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// arrow key panning
|
||||
float moveSpeed = 5.0f * PixelsPerMeter;
|
||||
if (Raylib.IsKeyDown(KeyboardKey.Right)) targetPosition.X += moveSpeed * frameTime;
|
||||
if (Raylib.IsKeyDown(KeyboardKey.Left)) targetPosition.X -= moveSpeed * frameTime;
|
||||
if (Raylib.IsKeyDown(KeyboardKey.Down)) targetPosition.Y += moveSpeed * frameTime;
|
||||
if (Raylib.IsKeyDown(KeyboardKey.Up)) targetPosition.Y -= moveSpeed * frameTime;
|
||||
}
|
||||
|
||||
// recenter
|
||||
if (Raylib.IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
targetPosition = Vector2.Zero;
|
||||
targetZoom = 1.0f;
|
||||
isDragging = false;
|
||||
cam.Target = Vector2.Zero;
|
||||
cam.Zoom = 1.0f;
|
||||
}
|
||||
|
||||
// zooming
|
||||
float wheel = Raylib.GetMouseWheelMove();
|
||||
if (wheel != 0.0f)
|
||||
{
|
||||
targetZoom *= MathF.Pow(1 + ZoomFactor, wheel);
|
||||
targetZoom = Math.Clamp(targetZoom, MinZoom, MaxZoom);
|
||||
}
|
||||
|
||||
// lerp zoom
|
||||
if (MathF.Abs(cam.Zoom - targetZoom) > 0.0001f)
|
||||
{
|
||||
Vector2 mouseWorldBefore = Raylib.GetScreenToWorld2D(Raylib.GetMousePosition(), cam);
|
||||
|
||||
cam.Zoom += (targetZoom - cam.Zoom) * ZoomLerpSpeed * frameTime;
|
||||
cam.Zoom = Math.Clamp(cam.Zoom, MinZoom, MaxZoom);
|
||||
|
||||
Vector2 mouseWorldAfter = Raylib.GetScreenToWorld2D(Raylib.GetMousePosition(), cam);
|
||||
targetPosition += (mouseWorldBefore - mouseWorldAfter);
|
||||
cam.Target = targetPosition;
|
||||
|
||||
if (isDragging)
|
||||
{
|
||||
dragStartMouseScreen = Raylib.GetMousePosition();
|
||||
dragStartTarget = targetPosition;
|
||||
}
|
||||
}
|
||||
else if (!isDragging)
|
||||
{
|
||||
cam.Target.X += (targetPosition.X - cam.Target.X) * MoveLerpSpeed * frameTime;
|
||||
cam.Target.Y += (targetPosition.Y - cam.Target.Y) * MoveLerpSpeed * frameTime;
|
||||
}
|
||||
|
||||
RaylibCamera = cam;
|
||||
}
|
||||
|
||||
public void DrawGrid()
|
||||
{
|
||||
float screenW = Raylib.GetScreenWidth();
|
||||
float screenH = Raylib.GetScreenHeight();
|
||||
|
||||
float cellPixels = GridSpacing * PixelsPerMeter * RaylibCamera.Zoom;
|
||||
float subCellPixels = cellPixels / 5.0f;
|
||||
|
||||
Vector2 originScreen = Raylib.GetWorldToScreen2D(Vector2.Zero, RaylibCamera);
|
||||
|
||||
Color gridColor = MuiDarkColor.SurfaceVariant.ToColor();
|
||||
Color subGridColor = new Color((byte)gridColor.R, (byte)gridColor.G, (byte)gridColor.B, (byte)75);
|
||||
Color mainGridColor = new Color((byte)gridColor.R, (byte)gridColor.G, (byte)gridColor.B, (byte)150);
|
||||
|
||||
// subgrid lines
|
||||
float startSubX = originScreen.X % subCellPixels;
|
||||
if (startSubX > 0) startSubX -= subCellPixels;
|
||||
for (float x = startSubX; x <= screenW; x += subCellPixels)
|
||||
{
|
||||
float relativeToOriginX = x - originScreen.X;
|
||||
int indexX = (int)Math.Round(relativeToOriginX / subCellPixels);
|
||||
if (indexX % 5 == 0) continue;
|
||||
|
||||
int ix = (int)Math.Round(x);
|
||||
Raylib.DrawLineEx(new Vector2(ix, 0), new Vector2(ix, screenH), 2.0f, subGridColor);
|
||||
}
|
||||
|
||||
float startSubY = originScreen.Y % subCellPixels;
|
||||
if (startSubY > 0) startSubY -= subCellPixels;
|
||||
for (float y = startSubY; y <= screenH; y += subCellPixels)
|
||||
{
|
||||
float relativeToOriginY = y - originScreen.Y;
|
||||
int indexY = (int)Math.Round(relativeToOriginY / subCellPixels);
|
||||
if (indexY % 5 == 0) continue;
|
||||
|
||||
int iy = (int)Math.Round(y);
|
||||
Raylib.DrawLineEx(new Vector2(0, iy), new Vector2(screenW, iy), 2.0f, subGridColor);
|
||||
}
|
||||
|
||||
// main grid lines
|
||||
float startMainX = originScreen.X % cellPixels;
|
||||
if (startMainX > 0) startMainX -= cellPixels;
|
||||
for (float x = startMainX; x <= screenW; x += cellPixels)
|
||||
{
|
||||
int ix = (int)Math.Round(x);
|
||||
Raylib.DrawLineEx(new Vector2(ix, 0), new Vector2(ix, screenH), 3.0f, mainGridColor);
|
||||
}
|
||||
|
||||
float startMainY = originScreen.Y % cellPixels;
|
||||
if (startMainY > 0) startMainY -= cellPixels;
|
||||
for (float y = startMainY; y <= screenH; y += cellPixels)
|
||||
{
|
||||
int iy = (int)Math.Round(y);
|
||||
Raylib.DrawLineEx(new Vector2(0, iy), new Vector2(screenW, iy), 3.0f, mainGridColor);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawHUD()
|
||||
{
|
||||
float screenH = Raylib.GetScreenHeight();
|
||||
string hudText = $"X: {Position.X:F2}m Y: {Position.Y:F2}m Zoom: {Zoom:F2}x";
|
||||
Program.DrawText(hudText, 20, (int)screenH - 40, 20, MuiDarkColor.TextPrimary.ToColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user