How can I use a camera with Farseer DebugView?

Topics: User Forum
May 24, 2014 at 8:54 AM
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 need to be scaled down. In addition, their corresponding Farseer bodies will be created with smaller measures.
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).

Why is the DebugView drawn on another position than the sprites? I know that it's not working because I use a camera class, but what should I change so that the DebugView is working correctly with my camera class?

Game1:
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);
    }
}
My 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);
    }
}
May 25, 2014 at 7:53 PM
I found the answer in this thread. The code from the user Beringela.
http://farseerphysics.codeplex.com/discussions/258898
Marked as answer by Wizard999 on 5/25/2014 at 12:53 PM