Startsidan  ▸  Texter  ▸  Teknikblogg

Anders Hesselbom

Programmerare, skeptiker, sekulärhumanist, antirasist.
Författare till bok om C64 och senbliven lantis.
Röstar pirat.

Fullskärm med exakt virtuell bildupplösning

2017-02-07

Om du vill bygga ett spel med Monogame som 1) körs i fullsärmsläge och 2) har en låg virtuell upplösning, typ 320 x 200 pixlar, så finns en enkel lösning. Istället för att rendera spelet på din backbuffer, så renderar du till en render target som är just 320 x 200 pixlar stor. För att åstadkomma detta, skapa en ny property i ditt spel, av typen RenderTarget2D.

private RenderTarget2D renderTarget { get; set; }

I konstruktorn, givet att vi befinner oss i release-kompileringen, skapar man en backbuffer som är lika stor som skärmen.

            graphics = new GraphicsDeviceManager(this);
#if DEBUG
            ScreenWidth = 640;
            ScreenHeight = 400;
            graphics.PreferredBackBufferWidth = ScreenWidth;
            graphics.PreferredBackBufferHeight = ScreenHeight;
            graphics.IsFullScreen = false;
#else
            ScreenWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
            ScreenHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
            graphics.PreferredBackBufferWidth = ScreenWidth;
            graphics.PreferredBackBufferHeight = ScreenHeight;
            graphics.IsFullScreen = true;
#endif
            Content.RootDirectory = "Content";

Funktionen Initialize är en lämplig plats att skapa RenderTarget2D-objektet. Det är storleken på den som styr den virtuella upplösningen.

renderTarget = new RenderTarget2D(GraphicsDevice, 320, 200);

Slutligen renderas spelet mot RenderTarget2D-objektet. Funktionen Draw skulle kunna se ut så här:

protected override void Draw(GameTime gameTime)
{
    graphics.GraphicsDevice.SetRenderTarget(renderTarget);
    graphics.GraphicsDevice.Clear(Color.Black);

    //Rita spelet här!
    spriteBatch.Begin();
    spriteBatch.Draw(hej, new Vector2(0, 0), Color.White);
    spriteBatch.Draw(hej, new Vector2(310, 190), Color.White);
    spriteBatch.End();

    graphics.GraphicsDevice.SetRenderTarget(null);
    spriteBatch.Begin(samplerState: SamplerState.PointClamp);
    spriteBatch.Draw(renderTarget, new Rectangle(0, 0, ScreenWidth, ScreenHeight), new Rectangle(0, 0, 320, 200), Color.White);
    spriteBatch.End();
    base.Draw(gameTime);
}

Notera det sista anropet på spriteBatch.Draw, den tredje sista raden. Den skalar upp spelet till den riktiga back bufferten. Om man vill ha rektangulära pixlar, ska det hanteras där. Denna exempelkod tar inte hänsyn till olika bildförhållanden.

Så här ser hela koden ut:

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

namespace Game1
{
    public class Game1 : Game
    {
        private RenderTarget2D renderTarget { get; set; }
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private int ScreenWidth { get; }
        private int ScreenHeight { get; }
        private Texture2D hej;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
#if DEBUG
            ScreenWidth = 640;
            ScreenHeight = 400;
            graphics.PreferredBackBufferWidth = ScreenWidth;
            graphics.PreferredBackBufferHeight = ScreenHeight;
            graphics.IsFullScreen = false;
#else
            ScreenWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
            ScreenHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
            graphics.PreferredBackBufferWidth = ScreenWidth;
            graphics.PreferredBackBufferHeight = ScreenHeight;
            graphics.IsFullScreen = true;
#endif
            Content.RootDirectory = "Content";
        }
        protected override void Initialize()
        {
            renderTarget = new RenderTarget2D(GraphicsDevice, 320, 200);
            base.Initialize();
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            hej = Content.Load<Texture2D>("hej");
        }
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.SetRenderTarget(renderTarget);
            graphics.GraphicsDevice.Clear(Color.Black);

            //Rita spelet här!
            spriteBatch.Begin();
            spriteBatch.Draw(hej, new Vector2(0, 0), Color.White);
            spriteBatch.Draw(hej, new Vector2(310, 190), Color.White);
            spriteBatch.End();

            graphics.GraphicsDevice.SetRenderTarget(null);
            spriteBatch.Begin(samplerState: SamplerState.PointClamp);
            spriteBatch.Draw(renderTarget, new Rectangle(0, 0, ScreenWidth, ScreenHeight), new Rectangle(0, 0, 320, 200), Color.White);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Jag utvecklar detta på min arbetsgivares blogg.

Categories: C#

Tags: Monogame, Retro

Leave a Reply

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



En kopp kaffe!

Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll!

Bjud på en kopp kaffe!

Om...

Kontaktuppgifter, med mera, finns här.

Följ mig

Twitter Instagram
GitHub RSS

Public Service

Folkbildning om public service.

Hem   |   linktr.ee/hesselbom   |   winsoft.se   |   80tal.se   |   Filmtips