2019-08-23 19:46:36 +02:00
|
|
|
using System;
|
2019-08-07 01:21:32 +02:00
|
|
|
using Microsoft.Xna.Framework;
|
|
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
|
|
using MLEM.Extensions;
|
|
|
|
|
|
|
|
namespace MLEM.Cameras {
|
|
|
|
public class Camera {
|
|
|
|
|
|
|
|
public Vector2 Position;
|
2019-09-19 20:23:18 +02:00
|
|
|
public float Scale = 1;
|
2019-08-23 19:46:36 +02:00
|
|
|
public bool AutoScaleWithScreen;
|
|
|
|
public Point AutoScaleReferenceSize;
|
|
|
|
public float ActualScale {
|
|
|
|
get {
|
|
|
|
if (!this.AutoScaleWithScreen)
|
|
|
|
return this.Scale;
|
|
|
|
return Math.Min(this.Viewport.Width / (float) this.AutoScaleReferenceSize.X, this.Viewport.Height / (float) this.AutoScaleReferenceSize.Y) * this.Scale;
|
|
|
|
}
|
|
|
|
}
|
2019-08-07 01:21:32 +02:00
|
|
|
public Matrix ViewMatrix {
|
|
|
|
get {
|
2019-08-23 19:46:36 +02:00
|
|
|
var sc = this.ActualScale;
|
|
|
|
var pos = -this.Position * sc;
|
2019-08-07 01:21:32 +02:00
|
|
|
if (this.roundPosition)
|
|
|
|
pos = pos.Floor();
|
2019-08-23 19:46:36 +02:00
|
|
|
return Matrix.CreateScale(sc, sc, 1) * Matrix.CreateTranslation(new Vector3(pos, 0));
|
2019-08-07 01:21:32 +02:00
|
|
|
}
|
|
|
|
}
|
2019-08-07 16:32:19 +02:00
|
|
|
public Vector2 Max {
|
|
|
|
get => this.Position + this.ScaledViewport;
|
|
|
|
set => this.Position = value - this.ScaledViewport;
|
|
|
|
}
|
|
|
|
public Vector2 LookingPosition {
|
|
|
|
get => this.Position + this.ScaledViewport / 2;
|
|
|
|
set => this.Position = value - this.ScaledViewport / 2;
|
|
|
|
}
|
2019-08-23 19:46:36 +02:00
|
|
|
public Rectangle Viewport => this.graphicsDevice.Viewport.Bounds;
|
|
|
|
public Vector2 ScaledViewport => new Vector2(this.Viewport.Width, this.Viewport.Height) / this.ActualScale;
|
2019-08-07 01:21:32 +02:00
|
|
|
|
|
|
|
private readonly bool roundPosition;
|
|
|
|
private readonly GraphicsDevice graphicsDevice;
|
|
|
|
|
|
|
|
public Camera(GraphicsDevice graphicsDevice, bool roundPosition = true) {
|
|
|
|
this.graphicsDevice = graphicsDevice;
|
2019-08-23 19:46:36 +02:00
|
|
|
this.AutoScaleReferenceSize = this.Viewport.Size;
|
2019-08-07 01:21:32 +02:00
|
|
|
this.roundPosition = roundPosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vector2 ToWorldPos(Vector2 pos) {
|
|
|
|
return Vector2.Transform(pos, Matrix.Invert(this.ViewMatrix));
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vector2 ToCameraPos(Vector2 pos) {
|
|
|
|
return Vector2.Transform(pos, this.ViewMatrix);
|
|
|
|
}
|
|
|
|
|
|
|
|
public (Vector2 topLeft, Vector2 bottomRight) GetVisibleArea() {
|
|
|
|
return (this.ToWorldPos(Vector2.Zero), this.ToWorldPos(new Vector2(this.Viewport.Width, this.Viewport.Height)));
|
|
|
|
}
|
|
|
|
|
2019-08-07 16:32:19 +02:00
|
|
|
public void ConstrainWorldBounds(Vector2 min, Vector2 max) {
|
|
|
|
if (this.Position.X < min.X)
|
|
|
|
this.Position.X = min.X;
|
|
|
|
if (this.Position.Y < min.Y)
|
|
|
|
this.Position.Y = min.Y;
|
|
|
|
|
|
|
|
if (this.Max.X > max.X)
|
|
|
|
this.Max = new Vector2(max.X, this.Max.Y);
|
|
|
|
if (this.Max.Y > max.Y)
|
|
|
|
this.Max = new Vector2(this.Max.X, max.Y);
|
|
|
|
}
|
|
|
|
|
2019-08-07 01:21:32 +02:00
|
|
|
}
|
|
|
|
}
|