What is best Screen Resolution for pixel art 2d game.

For desktop pixel art 2d game ,should i use 4:3 or 16:9 aspect-ratios

If 4:3 is better for desktop.
Should i use 640:480 or 1024x768 and why?

Thank you.

I think it’s reasonable to assume most people have a 1080p monitor for their desktop. That means a resolution of 1920x1080 which is 16:9.

What happen if desktop 4:3 Run game 16:9

Are images ,graphics going to be weird?

For pixel art it is often best to use a backbuffer of the same size as your design-time resolution (aka the size of your art assets). You can then scale it up for your final render by an integer factor (2, 3, 4, etc) to keep it pixel perfect. When you scale up either letterbox/pillar box or show some extra parts of your scene when the user has a different aspect ratio then your design-time aspect ratio.

I have a similar sounding style (2d, pixel graphics, think nes/snes) I am drawing to a render target of 480 x 280 (might drop to 270 soon). and scale by x2, x3 or x4 so:

480 x 280
960 x 560
1440 x 840
1920 x 1120 (problem here is display is usually 1920 x 1080, however see my full screen notes)

I have written some code to be resolution independent, my game is always keeping its ratio of 480x280 (about 1.714) so depending on the users resolution they will have black bars top/bottom or left/right (letterboxing and pillarboxing).

A slip up I have noticed doing this is my resolution is 1920x1080 (and see above it will want to be at 1920x1120) so I get some tiny black side bars at full screen which look a bit silly.

My solution is to check the ratio of the current screen and if its ~1.714 (say 1.65 - 1.75) then I just stretch that tiny bit and it shouldn’t be noticeable.

1 Like

@Tanakhon_Kaewkunha

Not sure how much use this is as I’m still learning monogame (again after a long break from it) last year when I was looking into it I found the below site, this worked well with my “game” I was messing around with. For my game, when I do all my drawing calculations etc I use the 1280x720 size, so when I create my images I use this size as well. Don’t ask why I use this and not 1920x1080 - I’ve forgotten - I think it’s something to do with xbox resolution and it’s what was in the tutorial.

If the resolution of the window is different aspect ratio to what it was designed for, then you will get the letter/pillar box effect with the black bars.

In my “Game1” class I basically have these rows:

graphics = new GraphicsDeviceManager(this);

// Change Virtual Resolution 
Resolution.Initialize(graphics);
Resolution.SetVirtualResolution(1280, 720);		// Size game is designed for
Resolution.SetResolution(1920, 1080, true);		// Actual size of window to display

Then in my Draw() method I do something like this:

SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
	
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null, Resolution.getTransformationMatrix());
spriteBatch.FillRectangle(Resolution.VirtualViewport, this.BackgroundColor);

string time = String.Format("Time Left: {0,0:D2}:{1,0:D2}", gameLengthLeft.Minutes, gameLengthLeft.Seconds);
spriteBatch.DrawString(Fonts.ScoreFont, time, **new Vector2(300, 5)**, Color.Yellow);

The Vector2(300,5) in the last line where it draws the time at a fixed location - that is based on the “Size game is designed for” >> Resolution.SetVirtualResolution(1280, 720);

http://www.david-amador.com/2010/03/xna-2d-independent-resolution-rendering/

Thank you so much.
I have a question
Resolution.SetVirtualResolution(1280, 720); //Size game is designed

Is it mean if i change as
SetVirtualResolution(640, 480) and
Resolution.SetResolution(1280, 860, true); (6402 and 4802)

Screen will show image of gameObjects as double larger? will images blur?

Will object’ images blur if run 480 x 280 on 2X or 3X resolution

@Tanakhon_Kaewkunha You’re welcome, I’ve not really played around with it that much as I’ve only been doing it for myself in 1920x1080 so I’ve not noticed that much different, but to answer the question - yes if your Virtual resolution is smaller than the actual resolution, it will scale the images up 2* as you say, and yes they will get blurred as well, depending on your target, it’s probably best to design the game and screens to the most used resolution - which for windows desktop is probably still 1920x1080.

For completeness, I’ve pasted the whole resolution code below:

//////////////////////////////////////////////////////////////////////////
////License:  The MIT License (MIT)
////Copyright (c) 2010 David Amador (http://www.david-amador.com)
////Direct Link: http://www.david-amador.com/2010/03/xna-2d-independent-resolution-rendering/
////Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
////
////The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
////
////THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Ballz
{
	public static class MouseHelper
	{
		/// <summary>
		/// Translates the actual mouse position obtained from Mouse.GetState() into the virtual mouse position after a scaling matrix is applied to the viewport
		/// </summary>
		public static Point CurrentMousePosition
		{
			get
			{
				MouseState mouse = Mouse.GetState();

				var mousePosition = new Vector2(mouse.X, mouse.Y);
				var virtualViewport = new Vector2(Resolution.VirtualViewportX, Resolution.VirtualViewportY);
				mousePosition = Vector2.Transform(mousePosition - virtualViewport, Matrix.Invert(Resolution.GetTransformationMatrix()));

				var virtualMousePosition = new Point((int)mousePosition.X, (int)mousePosition.Y);
				return virtualMousePosition;
			}
		}
	}

	internal static class Resolution
	{
		private static bool _fullScreen = false;
		private static GraphicsDeviceManager _graphicsDevice = null;
		private static bool _recreateScaleMatrix = true;
		private static Matrix _scaleMatrix;
		private static int _screenHeight = 1080;  // Actual Screen size
		private static int _screenWidth = 1920;   // Actual Screen size
		private static int _virtualHeight = 1080; // Size to display at / design size
		private static int _virtualWidth = 1920; // Size to display at / design size



		static public Rectangle VirtualViewport
		{
			get
			{
				return new Rectangle(0, 0, _virtualWidth, _virtualHeight);
			}
		}

		public static int VirtualViewportX { get; private set; }

		public static int VirtualViewportY { get; private set; }



		/// <summary>
		/// Sets the device to use the draw pump
		/// Sets correct aspect ratio
		/// </summary>
		static public void BeginDraw()
		{
			// Start by reseting viewport to (0,0,1,1)
			FullViewport();
			// Calculate Proper Viewport according to Aspect Ratio
			ResetViewport();
			// Clear to Black
			_graphicsDevice.GraphicsDevice.Clear(Color.Black);
		}

		static public void FullViewport()
		{
			var viewport = new Viewport();
			viewport.X = viewport.Y = 0;
			viewport.Width = _screenWidth;
			viewport.Height = _screenHeight;
			_graphicsDevice.GraphicsDevice.Viewport = viewport;
		}

		static public Matrix GetTransformationMatrix()
		{
			if (_recreateScaleMatrix)
			{
				RecreateScaleMatrix();
			}

			return _scaleMatrix;
		}

		/// <summary>
		/// Get virtual Mode Aspect Ratio
		/// </summary>
		/// <returns>aspect ratio</returns>
		static public float GetVirtualAspectRatio()
		{
			return (float)_virtualWidth / (float)_virtualHeight;
		}

		static public void Initialize(GraphicsDeviceManager device)
		{
			_screenWidth = device.PreferredBackBufferWidth;
			_screenHeight = device.PreferredBackBufferHeight;
			_graphicsDevice = device;
			_recreateScaleMatrix = true;
			ApplyResolutionSettings();
		}

		static public void ResetViewport()
		{
			float targetAspectRatio = GetVirtualAspectRatio();
			// figure out the largest area that fits in this resolution at the desired aspect ratio
			int width = _graphicsDevice.PreferredBackBufferWidth;
			int height = (int)(width / targetAspectRatio + .5f);
			bool changed = false;

			if (height > _graphicsDevice.PreferredBackBufferHeight)
			{
				height = _graphicsDevice.PreferredBackBufferHeight;
				// PillarBox
				width = (int)(height * targetAspectRatio + .5f);
				changed = true;
			}

			// set up the new viewport centered in the back buffer
			var viewport = new Viewport();

			viewport.X = (_graphicsDevice.PreferredBackBufferWidth / 2) - (width / 2);
			viewport.Y = (_graphicsDevice.PreferredBackBufferHeight / 2) - (height / 2);
			viewport.Width = width;
			viewport.Height = height;
			viewport.MinDepth = 0;
			viewport.MaxDepth = 1;

			VirtualViewportX = viewport.X;
			VirtualViewportY = viewport.Y;
			if (changed)
			{
				_recreateScaleMatrix = true;
			}
			_graphicsDevice.GraphicsDevice.Viewport = viewport;
		}

		static public void SetResolution(int width, int height, bool fullScreen)
		{
			_screenWidth = width;
			_screenHeight = height;
			_fullScreen = fullScreen;

			ApplyResolutionSettings();
		}

		static public void SetVirtualResolution(int virtualWidth, int virtualHeight)
		{
			_virtualWidth = virtualWidth;
			_virtualHeight = virtualHeight;
			_recreateScaleMatrix = true;
		}



		static private void ApplyResolutionSettings()
		{
#if XBOX360
		   Resolution.fullScreen = true;
#endif

			// If we aren't using a full screen mode, the height and width of the window can
			// be set to anything equal to or smaller than the actual screen size.
			if (_fullScreen == false)
			{
				if ((_screenWidth <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width)
					&& (_screenHeight <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height))
				{
					_graphicsDevice.PreferredBackBufferWidth = _screenWidth;
					_graphicsDevice.PreferredBackBufferHeight = _screenHeight;
					_graphicsDevice.IsFullScreen = _fullScreen;
					_graphicsDevice.ApplyChanges();
				}
			}
			else
			{
				// If we are using full screen mode, we should check to make sure that the display
				// adapter can handle the video mode we are trying to set.  To do this, we will
				// iterate through the display modes supported by the adapter and check them against
				// the mode we want to set.
				foreach (DisplayMode displayMode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
				{
					// Check the width and height of each mode against the passed values
					if (displayMode.Width == _screenWidth && displayMode.Height == _screenHeight)
					{
						// The mode is supported, so set the buffer formats, apply changes and return
						_graphicsDevice.PreferredBackBufferWidth = _screenWidth;
						_graphicsDevice.PreferredBackBufferHeight = _screenHeight;
						_graphicsDevice.IsFullScreen = _fullScreen;
						_graphicsDevice.ApplyChanges();
						break;
					}
				}
			}
			_recreateScaleMatrix = true;
			_screenWidth = _graphicsDevice.PreferredBackBufferWidth;
			_screenHeight = _graphicsDevice.PreferredBackBufferHeight;
		}

		static private void RecreateScaleMatrix()
		{
			_recreateScaleMatrix = false;
			_scaleMatrix = Matrix.CreateScale(
											(float)_graphicsDevice.GraphicsDevice.Viewport.Width / _virtualWidth,
											(float)_graphicsDevice.GraphicsDevice.Viewport.Height / _virtualHeight,
											1f);
		}
	}
}
1 Like