mirror of
https://github.com/TheRavenwoodArts/LunaLightXMG.git
synced 2026-07-30 21:55:03 -07:00
123 lines
3.9 KiB
C#
123 lines
3.9 KiB
C#
using System;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
|
|
namespace LunaLightXMG
|
|
{
|
|
public class Camera2D
|
|
{
|
|
// Fields
|
|
private readonly Viewport viewport;
|
|
private float zoom;
|
|
private float rotation;
|
|
private Vector2 position;
|
|
private Rectangle levelBounds;
|
|
private readonly float camSpeed = 5.0f;
|
|
|
|
// Screen Shake
|
|
private float shakeTimeRemaining = 0f;
|
|
private float shakeMagnitudeCurrent = 0f;
|
|
private bool shaking = false;
|
|
|
|
// Util
|
|
readonly Utilities util;
|
|
|
|
// Getters and setters
|
|
public Vector2 Position
|
|
{
|
|
get => position;
|
|
set => position = value;
|
|
}
|
|
public float Zoom
|
|
{
|
|
get => zoom;
|
|
set => zoom = (int)Math.Floor(MathHelper.Clamp(value, 1f, 2f));
|
|
}
|
|
public float Rotation
|
|
{
|
|
get => rotation;
|
|
set => rotation = value;
|
|
}
|
|
|
|
// constructor
|
|
public Camera2D(int width, int height)
|
|
{
|
|
viewport = new Viewport(0, 0, width, height);
|
|
levelBounds = new Rectangle(0, 0, 320, 180); // Default
|
|
zoom = 1f;
|
|
rotation = 0f;
|
|
position = Vector2.Zero;
|
|
util = new Utilities();
|
|
}
|
|
|
|
public Matrix GetViewMatrix()
|
|
{
|
|
return
|
|
Matrix.CreateTranslation(new Vector3(-position, 0f)) *
|
|
Matrix.CreateRotationZ(rotation) *
|
|
Matrix.CreateScale(zoom, zoom, 1f) *
|
|
Matrix.CreateTranslation(new Vector3(viewport.Width * 0.5f, viewport.Height * 0.5f, 0f));
|
|
}
|
|
|
|
public void SetLevelBounds(Rectangle bounds)
|
|
{
|
|
levelBounds = bounds;
|
|
}
|
|
|
|
public void Follow(GameTime gameTime, Vector2 targetPostion)
|
|
{
|
|
float smoothSpeed = camSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
|
|
position = Vector2.Lerp(position, targetPostion, smoothSpeed);
|
|
if (Vector2.Distance(position, targetPostion) < 1.0f)
|
|
{
|
|
position = targetPostion;
|
|
}
|
|
ClampToBounds();
|
|
}
|
|
|
|
public void ScreenShake(float shakeTime, float shakeMagnitude)
|
|
{
|
|
shakeTimeRemaining = shakeTime;
|
|
shakeMagnitudeCurrent = shakeMagnitude;
|
|
shaking = true;
|
|
}
|
|
|
|
public void UpdateScreenShake(GameTime gameTime)
|
|
{
|
|
if (!shaking) return;
|
|
|
|
if (shakeTimeRemaining > 0)
|
|
{
|
|
float shakeX = util.RandomFromRange(-shakeMagnitudeCurrent, shakeMagnitudeCurrent);
|
|
float shakeY = util.RandomFromRange(-shakeMagnitudeCurrent, shakeMagnitudeCurrent);
|
|
position.X += shakeX;
|
|
position.Y += shakeY;
|
|
shakeTimeRemaining -= (float)gameTime.ElapsedGameTime.TotalSeconds;
|
|
shakeMagnitudeCurrent *= 0.9f;
|
|
}
|
|
else
|
|
{
|
|
shaking = false;
|
|
shakeTimeRemaining = 0f;
|
|
shakeMagnitudeCurrent = 0f;
|
|
}
|
|
}
|
|
|
|
private void ClampToBounds()
|
|
{
|
|
// Calculate the cam's half viewport size
|
|
var halfViewportWidth = viewport.Width * 0.5f / zoom;
|
|
var halfViewportHeight = viewport.Height * 0.5f / zoom;
|
|
|
|
// Clamp cam to level bounds
|
|
float minX = levelBounds.Left + halfViewportWidth;
|
|
float maxX = levelBounds.Right - halfViewportWidth;
|
|
float minY = levelBounds.Top + halfViewportHeight;
|
|
float maxY = levelBounds.Bottom - halfViewportHeight;
|
|
|
|
// Set cam position within level bounds
|
|
position.X = MathHelper.Clamp(position.X, minX, maxX);
|
|
position.Y = MathHelper.Clamp(position.Y, minY, maxY);
|
|
}
|
|
}
|
|
} |