2
\$\begingroup\$

I want that the screen looks the same on every Android device without distorting the sprites.

One player should not see more of the map than another player just because they have a bigger screen or different resolution on their device.

I use (1334, 750) as my virtual resolution and only landscape mode is supported. But at the moment, you can see more of the map on top and on the bottom if you have a device with different aspect ratio.

How would I create a letterbox on top and on the bottom so that the visible game window keeps the same aspect ratio and portion of the game world visible on every device?

Do I need to modify my 2D camera when I create a letterbox screen?

At the moment it looks like this:

Android emulator

But it should look like this so that everyone can see the same map on the screen:

Letterboxed

 public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Camera camera;
        Vector2 vp, gameWorldSize = new Vector2(1334, 750); 
        float ScaleX, ScaleY, Scale;
        Vector2 Newcameraposition;
        Texture2D Background;         

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.IsFullScreen = true;
            graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Background = Content.Load<Texture2D>("background");              
            vp = new Vector2(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
            ScaleX = vp.X / gameWorldSize.X;
            ScaleY = vp.Y / gameWorldSize.Y;
            Scale = Math.Min(ScaleX, ScaleY);               
            camera = new Camera(new Vector2(gameWorldSize.X / 2, gameWorldSize.Y / 2), Scale, vp);
        }

        protected override void Update(GameTime gameTime)
        {
            Newcameraposition = new Vector2(gameWorldSize.X / 2, gameWorldSize.Y / 2);
            camera.Update(gameTime, Newcameraposition, Scale, vp);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, camera.GetMatrix());
            spriteBatch.Draw(Background, new Rectangle((int)gameWorldSize.X / 2, (int)gameWorldSize.Y / 2, Background.Width, Background.Height), null, Color.White, 0, new Vector2(Background.Width / 2, Background.Height / 2), SpriteEffects.None, 0.0f);         
            spriteBatch.End();    

            base.Draw(gameTime);
        }
    }

My 2D camera:

 public class Camera
    {
        public Vector2 PlayerPosition;
        private Vector2 Viewport;
        private float Scale;

        public Camera(Vector2 playerposition, float scale, Vector2 viewport)
        {
            PlayerPosition = playerposition;
            Scale = scale;
            Viewport = viewport;
        }

        public void Update(GameTime gameTime, Vector2 playerposition, float scale, Vector2 viewport)
        {
            PlayerPosition = playerposition;
            Scale = scale;
            Viewport = viewport;
        }

        public Matrix GetMatrix()
        {
            return Matrix.CreateTranslation(new Vector3(-PlayerPosition.X, -PlayerPosition.Y, 0))
         * Matrix.CreateScale(Scale, Scale, 1)
         * Matrix.CreateTranslation(Viewport.X / 2, Viewport.Y / 2, 0);
        }
    }
\$\endgroup\$
0
\$\begingroup\$

You have two options in my view:

  1. Stretching (Bad): I have no idea about the engine you're using (if any), but I'm pretty sure in every modern render engine there's an option for handling multi-resolution. For instance, in V-Box and Cocos2d-x engines you have the Exact fit option for that.
  2. Fog of War: As you mention, you can put some opaque element around the must-be-visible. I wouldn't touch Camera as it's not a camera-issue, instead, a game-design decision. The nature of the problem is the same in many games which the map shouldn't be shown unless the player discovered it by moving there.

    I don't know the framework you're using, but I think you need to modify Draw() method and in the most simplified version draw for black rectangle, like:

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.