using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace LunaLightXMG { public class RenderHandler { // fields private GraphicsDevice graphicsDevice; private SpriteBatch spriteBatch; private RenderTarget2D renderTarget; private Rectangle renderDestination; private readonly float retroWidth; private readonly float retroHeight; private float zoomLevel = 1.0f; private float zoomTarget = 1.0f; private readonly float zoomMin = 0.50f; private readonly float zoomNorm = 1.0f; private readonly float zoomMax = 1.50f; private readonly float zoomSpeed = 0.1f; public float ZoomLevel {get => zoomLevel;} // constructor public RenderHandler(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch, int retroWidth, int retroHeight) { this.graphicsDevice = graphicsDevice; this.spriteBatch = spriteBatch; this.retroWidth = retroWidth; this.retroHeight = retroHeight; renderTarget = new RenderTarget2D(graphicsDevice, retroWidth, retroHeight); CalculateRenderDestination(); } public void ZoomIn() { zoomTarget = zoomMin; } public void ZoomNormalize() { zoomTarget = zoomNorm; } public void ZoomOut() { zoomTarget = zoomMax; } public void UpdateZoom() { // interpolate to target zoomLevel = MathHelper.Lerp(zoomLevel, zoomTarget, zoomSpeed); // snap to target when we're close enough if (Math.Abs(zoomLevel - zoomTarget) < 0.001f) { zoomLevel = zoomTarget; } // stay in bounds (just in case) zoomLevel = MathHelper.Clamp(zoomLevel, zoomMin, zoomMax); // calc new zoomed render destination CalculateRenderDestination(); } public void CalculateRenderDestination() { Point screenSize = graphicsDevice.Viewport.Bounds.Size; // Calculate the integer scale factor float scaleX = screenSize.X / (retroWidth * zoomLevel); float scaleY = screenSize.Y / (retroHeight * zoomLevel); float scale = Math.Min(scaleX, scaleY); // Set renderDestination renderDestination.Width = (int)(retroWidth * scale); renderDestination.Height = (int)(retroHeight * scale); renderDestination.X = (screenSize.X - renderDestination.Width) / 2; renderDestination.Y = (screenSize.Y - renderDestination.Height) / 2; } public void BeginRenderTarget(Matrix cameraMatrix) { graphicsDevice.SetRenderTarget(renderTarget); graphicsDevice.Clear(Color.Black); spriteBatch.Begin(transformMatrix: cameraMatrix, samplerState: SamplerState.PointClamp); } public void EndRenderTarget() { spriteBatch.End(); graphicsDevice.SetRenderTarget(null); } public void DrawRenderTarget() { spriteBatch.Begin(samplerState: SamplerState.PointClamp); spriteBatch.Draw(renderTarget, renderDestination, Color.White); spriteBatch.End(); } } }