Skip to main content
Tweeted twitter.com/#!/StackGameDev/status/471874138647171072
Added new code and additional information.
Source Link
Homer_Simpson
  • 615
  • 1
  • 7
  • 19

UPDATE: I changed my code and tried it without scaling the sprites and Farseer objects. In addition, I changed my code in the Camera class to:

public Matrix GetMatrix()
{
    return Matrix.CreateTranslation(new Vector3(-BallPosition.X, -BallPosition.Y, 0))
 * Matrix.CreateTranslation(Viewport.X / 2, Viewport.Y / 2, 0);
}

But it's still not working. I get the following result if I don't use scaling: http://s7.directupload.net/images/140523/oumh3e7c.jpg

Why is the DebugView drawn on another position than the sprites? I found out that if I change something in this code block, then the DebugView is drawn on another position, but I don't know how to change this code block so that the DebugView is drawn on the correct position(on the same position as their corresponding sprites). I know that it's not working because I use a Camera class, but how should I change this code block so that it works with the Camera class?

if (Draw_debugView == true)
    {
        // calculate the projection and view adjustments for the debug view
        Matrix projection = Matrix.CreateOrthographicOffCenter(0f, graphics.GraphicsDevice.Viewport.Width / _displayUnitsToSimUnitsRatio,
                                                         graphics.GraphicsDevice.Viewport.Height / _displayUnitsToSimUnitsRatio, 0f, 0f,
                                                         1f);
        Matrix view = Matrix.CreateTranslation(new Vector3((_cameraPosition / _displayUnitsToSimUnitsRatio) - (_screenCenter / _displayUnitsToSimUnitsRatio), 0f)) * Matrix.CreateTranslation(new Vector3((_screenCenter / _displayUnitsToSimUnitsRatio), 0f));
        // draw the debug view
       physicsDebug.RenderDebugData(ref projection, ref view);
    }

UPDATE: I changed my code and tried it without scaling the sprites and Farseer objects. In addition, I changed my code in the Camera class to:

public Matrix GetMatrix()
{
    return Matrix.CreateTranslation(new Vector3(-BallPosition.X, -BallPosition.Y, 0))
 * Matrix.CreateTranslation(Viewport.X / 2, Viewport.Y / 2, 0);
}

But it's still not working. I get the following result if I don't use scaling: http://s7.directupload.net/images/140523/oumh3e7c.jpg

Why is the DebugView drawn on another position than the sprites? I found out that if I change something in this code block, then the DebugView is drawn on another position, but I don't know how to change this code block so that the DebugView is drawn on the correct position(on the same position as their corresponding sprites). I know that it's not working because I use a Camera class, but how should I change this code block so that it works with the Camera class?

if (Draw_debugView == true)
    {
        // calculate the projection and view adjustments for the debug view
        Matrix projection = Matrix.CreateOrthographicOffCenter(0f, graphics.GraphicsDevice.Viewport.Width / _displayUnitsToSimUnitsRatio,
                                                         graphics.GraphicsDevice.Viewport.Height / _displayUnitsToSimUnitsRatio, 0f, 0f,
                                                         1f);
        Matrix view = Matrix.CreateTranslation(new Vector3((_cameraPosition / _displayUnitsToSimUnitsRatio) - (_screenCenter / _displayUnitsToSimUnitsRatio), 0f)) * Matrix.CreateTranslation(new Vector3((_screenCenter / _displayUnitsToSimUnitsRatio), 0f));
        // draw the debug view
       physicsDebug.RenderDebugData(ref projection, ref view);
    }
Source Link
Homer_Simpson
  • 615
  • 1
  • 7
  • 19

How can I scale Farseer bodies so that they work on different screen resolutions?

I created a little Windows Phone 8 game that supports multiple resolutions. If the resolution of the device is less than 720p, then the sprites and their corresponding Farseer bodies need to be scaled down. If I run my project with the 720p emulator, then everything looks fine. But if I choose an emulator with a lower resolution(for example WVGA emulator), then everything looks weird.

In this picture, I use the 720p emulator: http://s1.directupload.net/images/140520/gnpwvjsw.jpg

In this picture, I use the WVGA emulator: http://s14.directupload.net/images/140520/hxhicnph.jpg

If I use the WVGA emulator, then the Farseer collision shapes are drawn on another position than their corresponding sprites. In addition, a part of the red ball sprite is drawn in the blue rectangle sprite, but their corresponding shapes are drawn differently(the ball shape isn't in the rectangle shape).

How can I scale the Farseer bodies so that everything works correctly?

Here is my entire code:

Game1 class:

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    bool Draw_debugView = true;
    World world;
    Body Rectangle, Ball;
    Texture2D RectangleSprite, BallSprite;

    public Camera camera;

    public const int VirtualScreenWidth = 1280;
    public const int VirtualScreenHeight = 720;
    Vector2 vp, gameWorldSize = new Vector2(1280, 720);
    float ScaleX, ScaleY, Scale;

    DebugViewXNA physicsDebug;
    private Matrix _view;
    private Vector2 _cameraPosition;
    private Vector2 _screenCenter;

    private static float _displayUnitsToSimUnitsRatio = 100f;

    public static Vector2 ToDisplayUnits(Vector2 simUnits)
    {
        return simUnits * _displayUnitsToSimUnitsRatio;
    }   

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.IsFullScreen = true;
    }

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

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        BallSprite = Content.Load<Texture2D>("ball");
        RectangleSprite = Content.Load<Texture2D>("tile");

        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(640,360), Scale, vp);

        _view = Matrix.Identity;
        _cameraPosition = Vector2.Zero;

        _screenCenter = new Vector2(graphics.GraphicsDevice.Viewport.Width / 2f,
                                            graphics.GraphicsDevice.Viewport.Height / 2f);


        if (world == null)
        {
            world = new World(new Vector2(0, 1));
        }
        else
        {
            world.Clear();
        }

        physicsDebug = new DebugViewXNA(world);
        physicsDebug.DefaultShapeColor = Color.White;
        physicsDebug.SleepingShapeColor = Color.LightGray;
        physicsDebug.LoadContent(GraphicsDevice, Content);

        Ball = BodyFactory.CreateCircle(world, 0.25f*ScaleX, 1.0f);
        Ball.BodyType = BodyType.Dynamic;
        Ball.Position = new Vector2(6.4f, 0.6f);
        Ball.LinearVelocity = new Vector2(0, 2.0f);

        Rectangle = BodyFactory.CreateRectangle(world, 1.50f*ScaleX, 0.50f*ScaleY, 1.0f);
        Rectangle.BodyType = BodyType.Static;
        Rectangle.Position = new Vector2(6.4f, 3.6f);
        Rectangle.Rotation = 0f;
        Rectangle.Restitution = 0.5f;
        Rectangle.CollisionCategories = Category.Cat5;         
    }

    protected override void Update(GameTime gameTime)
    {
        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
        world.Step(Math.Min(elapsed, (1f / 60f)));

        ScaleX = vp.X / gameWorldSize.X;
        ScaleY = vp.Y / gameWorldSize.Y;
        Scale = Math.Min(ScaleX, ScaleY);

        //The ball should always be the center of the camera
        camera.Update(gameTime, new Vector2(Ball.Position.X*100f, Ball.Position.Y*100f), 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(RectangleSprite, ConvertUnits.ToDisplayUnits(Rectangle.Position),
                                           null,
                                           Color.White, Rectangle.Rotation, new Vector2(RectangleSprite.Width / 2.0f, RectangleSprite.Height / 2.0f), 1f,
                                           SpriteEffects.None, 0f);



            spriteBatch.Draw(BallSprite, ConvertUnits.ToDisplayUnits(Ball.Position),
                                     null,
                                     Color.White, Ball.Rotation, new Vector2(BallSprite.Width / 2.0f, BallSprite.Height / 2.0f), 1f,
                                     SpriteEffects.None, 0f);

        spriteBatch.End();

        if (Draw_debugView == true)
        {
            // calculate the projection and view adjustments for the debug view
            Matrix projection = Matrix.CreateOrthographicOffCenter(0f, graphics.GraphicsDevice.Viewport.Width / _displayUnitsToSimUnitsRatio,
                                                             graphics.GraphicsDevice.Viewport.Height / _displayUnitsToSimUnitsRatio, 0f, 0f,
                                                             1f);
            Matrix view = Matrix.CreateTranslation(new Vector3((_cameraPosition / _displayUnitsToSimUnitsRatio) - (_screenCenter / _displayUnitsToSimUnitsRatio), 0f)) * Matrix.CreateTranslation(new Vector3((_screenCenter / _displayUnitsToSimUnitsRatio), 0f));
            // draw the debug view
           physicsDebug.RenderDebugData(ref projection, ref view);
        }
        base.Draw(gameTime);
    }
}

Camera class:

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


    public Camera(Vector2 ballposition, float scale, Vector2 viewport)
    {
        BallPosition = ballposition;
        Scale = scale;
        Viewport = viewport;
    }

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

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