När man bygger retrospel med en upplösning på omkring 320 x 200 pixlar, vill man gärna skala upp spelet så att sprites och andra objekt inte blir så små på en modern skärm. För den som programmerar Monogame finns flera lösningar. Jag tycker att den enklaste metoden är att använda ett transform matrix. När jag debuggar mitt spel, tycker jag att en uppskalning på 3 x 3 är rätt lämplig, vilket innebär att ett fönster på 960 x 600 pixlar är lämpligt. Detta är spelets konstruktor, spelet har kompletterats med en medlemsvariabel vid namn transformMatrix av typen Matrix.

graphics.PreferredBackBufferWidth = 960;
graphics.PreferredBackBufferHeight = 600;
graphics.IsFullScreen = false;
transformMatrix = Matrix.CreateScale(960 / 320, 600 / 200, 1.0f);

I skarpt läge låter jag skärmupplösningen styra skalningen, eftersom jag vill att spelet ska köras i fullskärm.

var width = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
var height = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
graphics.PreferredBackBufferWidth = width;
graphics.PreferredBackBufferHeight = height;
graphics.IsFullScreen = true;
transformMatrix = Matrix.CreateScale(width / 320, height / 200, 1.0f);

För att effekten ska slå igenom, ska Matrix-objektet skickas med till SpriteBatch-objektets Begin-metod. För att undvika oönskad kantutjämning använder jag en sampler state som heter PointClamp.

spriteBatch.Begin(transformMatrix: transformMatrix, samplerState: SamplerState.PointClamp);

Ett exempelspel skulle kunna se ut så här:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Game1
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Matrix transformMatrix;
        Texture2D testtexture { get; set; }
        private int x = 0;
        private int y = 0;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
#if DEBUG
            graphics.PreferredBackBufferWidth = 960;
            graphics.PreferredBackBufferHeight = 600;
            graphics.IsFullScreen = false;
            transformMatrix = Matrix.CreateScale(960 / 320, 600 / 200, 1.0f);
#else
            var width = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
            var height = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
            graphics.PreferredBackBufferWidth = width;
            graphics.PreferredBackBufferHeight = height;
            graphics.IsFullScreen = true;
            transformMatrix = Matrix.CreateScale(width / 320, height / 200, 1.0f);
#endif
            Content.RootDirectory = "Content";
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            testtexture = Content.Load<Texture2D>("my_folder");
        }
        protected override void Update(GameTime gameTime)
        {
            var state = Keyboard.GetState();
            if (state.IsKeyDown(Keys.Escape))
                Exit();
            if (state.IsKeyDown(Keys.Left))
                x--;
            else if (state.IsKeyDown(Keys.Right))
                x++;
            if (state.IsKeyDown(Keys.Up))
                y--;
            else if (state.IsKeyDown(Keys.Down))
                y++;
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin(transformMatrix: transformMatrix, samplerState: SamplerState.PointClamp);
            spriteBatch.Draw(testtexture, new Vector2(x, y), Color.White);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Ett problem som man bör känna till, är att om bildförhållandet mellan den virtuella upplösningen och den fysiska upplösningen inte är samma, så kommer fler pixlar än önskat att synas. När man kör i fönster, så kan man styra detta så att bildförhållandet är detsamma. 960 x 600 har samma bildförhållande som 320 x 200. Men i fullskärmsläge bör man ha detta i åtanke.

Leave a Reply

Your email address will not be published. Required fields are marked *