Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

using System; using System.IO; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; using Microsoft.Xna.Framework.Input.Touch;

here is the ICamera2D

  public interface IFocusable
{
Vector2 Position { get; }
}

 public interface ICamera2D
{
/// <summary>
/// Gets or sets the position of the camera
/// </summary>
/// <value>The position.</value>
Vector2 Position { get; set; }

/// <summary>
/// Gets or sets the move speed of the camera.
/// The camera will tween to its destination.
/// </summary>
/// <value>The move speed.</value>
float MoveSpeed { get; set; }

/// <summary>
/// Gets or sets the rotation of the camera.
/// </summary>
/// <value>The rotation.</value>
float Rotation { get; set; }

/// <summary>
/// Gets the origin of the viewport (accounts for Scale)
/// </summary>        
/// <value>The origin.</value>
Vector2 Origin { get; }

/// <summary>
/// Gets or sets the scale of the Camera
/// </summary>
/// <value>The scale.</value>
float Scale { get; set; }

/// <summary>
/// Gets the screen center (does not account for Scale)
/// </summary>
/// <value>The screen center.</value>
Vector2 ScreenCenter { get; }

/// <summary>
/// Gets the transform that can be applied to 
/// the SpriteBatch Class.
/// </summary>
/// <see cref="SpriteBatch"/>
/// <value>The transform.</value>
Matrix Transform { get; }

/// <summary>
/// Gets or sets the focus of the Camera.
/// </summary>
/// <seealso cref="IFocusable"/>
/// <value>The focus.</value>
IFocusable Focus { get; set; }

/// <summary>
/// Determines whether the target is in view given the specified position.
/// This can be used to increase performance by not drawing objects
/// directly in the viewport
/// </summary>
/// <param name="position">The position.</param>
/// <param name="texture">The texture.</param>
 /// <returns>


 ///     <c>true</c> if the target is in view at the specified position; otherwise,    < c  >false</c>.
/// </returns>
bool IsInView(Vector2 position, Texture2D texture);
}

This is my main Camera2D Class

  public class Camera2D : GameComponent, ICamera2D
 {
private Vector2 _position;
protected float _viewportHeight;
protected float _viewportWidth;

public Camera2D(Game game)
    : base(game)
{}

#region Properties

public Vector2 Position
{
    get { return _position; }
    set { _position = value; }
}
public float Rotation { get; set; }
public Vector2 Origin { get; set; }
public float Scale { get; set; }
public Vector2 ScreenCenter { get; protected set; }
public Matrix Transform { get; set; }
public IFocusable Focus { get; set; }
public float MoveSpeed { get; set; }

#endregion

/// <summary>
/// Called when the GameComponent needs to be initialized. 
/// </summary>
public override void Initialize()
{
    _viewportWidth = Game.GraphicsDevice.Viewport.Width;
    _viewportHeight = Game.GraphicsDevice.Viewport.Height;

    ScreenCenter = new Vector2(_viewportWidth/2, _viewportHeight/2);
    Scale = 1;
    MoveSpeed = 1.25f;

    base.Initialize();
}

public override void Update(GameTime gameTime)
{
    // Create the Transform used by any
    // spritebatch process
    Transform = Matrix.Identity*
                Matrix.CreateTranslation(-Position.X, -Position.Y, 0)*
                Matrix.CreateRotationZ(Rotation)*
                Matrix.CreateTranslation(Origin.X, Origin.Y, 0)*
                Matrix.CreateScale(new Vector3(Scale, Scale, Scale));

    Origin = ScreenCenter / Scale;

    // Move the Camera to the position that it needs to go
    var delta = (float) gameTime.ElapsedGameTime.TotalSeconds;

    _position.X += (Focus.Position.X - Position.X) * MoveSpeed * delta;
    _position.Y += (Focus.Position.Y - Position.Y) * MoveSpeed * delta;

    base.Update(gameTime);
}

/// <summary>
/// Determines whether the target is in view given the specified position.
/// This can be used to increase performance by not drawing objects
/// directly in the viewport
/// </summary>
/// <param name="position">The position.</param>
/// <param name="texture">The texture.</param>
/// <returns>
///     <c>true</c> if [is in view] [the specified position]; otherwise, <c>false</c>.
/// </returns>
public bool IsInView(Vector2 position, Texture2D texture)
{
    // If the object is not within the horizontal bounds of the screen

    if ( (position.X + texture.Width) < (Position.X - Origin.X) || (position.X) >      (Position.X + Origin.X) )
        return false;

    // If the object is not within the vertical bounds of the screen
    if ((position.Y + texture.Height) < (Position.Y - Origin.Y) || (position.Y) > (Position.Y + Origin.Y))
        return false;

    // In View
    return true;
}

 Here is my draw method i cannot get camera.transform to work properly 


 // cam.Zoom = 2.0f // Example of Zoom in
 // cam.Zoom = 0.5f // Example of Zoom out     



  public void Draw(GameTime gameTime, SpriteBatch spriteBatch)   
  {

      spriteBatch.Begin(BlendState.AlphaBlend, SpriteSortMode.FrontToBack, 
          null,
          null,
          null,
          null, 
          Camera.Transform);

    spriteBatch.End();          

  }
}
share|improve this question
7  
seriously?? Just here's my code, somebody fix it please?. -Or- did you have a specific question about your snippet that you'd like to ask? –  Steve H Apr 4 '13 at 23:58
2  
yes sorry the problem is in the draw metthod i cannot get it to work properly for one thing the camera transform wont work properly –  jason mabrey Apr 5 '13 at 0:15
1  
@jasonmabrey edit the question and add more information about the problem –  user25712 Apr 5 '13 at 0:29
    
@SteveH Snippet? –  Byte56 Apr 5 '13 at 1:36
1  
Sigh - a "please debug my code for me" question. –  Jimmy Shelter Apr 5 '13 at 8:56
show 1 more comment

closed as not a real question by Byte56, bummzack, Jimmy Shelter, Maik Semder, Trevor Powell Apr 6 '13 at 4:27

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

1 Answer

The problem with your Camera 2D is how you create the translation. A matrix has to be calculated in the right order and that is or "(Origin), Scale, Rotation, Translation". Otherwise it could rotate around the wrong axis.

2D Transformation = Scale * Rotation * Translation

1. Scale the object to the correct size, say the width and height of the window
   If it's scaled 2x it will contain half the size of the objects on screen

2. Now you have the double the radius of the object, you rotate it 90 degrees
   It can now rotate the object according to it's size, so an object half width
   and half height will get another "translation" position than if wasn't scaled or
   rotated. Normally the origin is the 0,0 point but when scaling and rotating
   it will change, what you set as 0,0 after rotating and scaling will be somewhere else.

3. Translation, you translate the position according to it's rotation and scale

In your case:

1. Translate the position
   It's at say 0,0

2. Rotate the object along it's size without scaling it
   Rotate screen 180 degrees, which means 0, 0 is at Width, Height

3. Scale the object up (to say 2x)
   Then scale it which fails because the rotation will rotate around an invalid size
   Instead it will rotate around the wrong axis because the size is changed after
   The rotation has occured.

This is a simple implementation of a 2D Camera with Origin, Scale, Rotation and Translation.

public class Camera2D
{
    public Camera2D()
    {
        Origin = Vector2.Zero;
        Position = Vector2.Zero;
        Scale = 1f;
        Rotation = 0;
    }

    public void Move(float x, float y) { Position += new Vector2(x, y); }
    public void Zoom(float value) { Scale = Math.Max(Scale + value, 0.01f); }
    public void Rotate(float value) { Rotation += value; }
    public void SetOrigin(Vector2 originPosition) { Origin = originPosition; }
    public void SetPosition(Vector2 newPosition) { Position = newPosition; }

    private Vector2 position;
    public Vector2 Position
    {
        get { return position; } protected set { position = value; }
    }

    private Vector2 origin;
    public Vector2 Origin
    {
        get { return origin; } protected set { origin = value; }
    }

    public float Rotation { get; protected set; }
    public float Scale { get; protected set; }

    public Matrix Transformation
    {
        get
        {
            return
                Matrix.CreateTranslation(Origin.X, Origin.Y, 0) *
                Matrix.CreateScale(Scale) *
                Matrix.CreateRotationZ(MathHelper.ToRadians(Rotation)) *
                Matrix.CreateTranslation(Position.X, Position.Y, 0);
        }
    }

    public Matrix TransformationNoOrigin
    {
        get
        {
            return
                Matrix.CreateScale(Scale) *
                Matrix.CreateRotationZ(MathHelper.ToRadians(Rotation)) *
                Matrix.CreateTranslation(Position.X, Position.Y, 0);
        }
    }
}

A concrete example:

ScreenWidth = 1280; ScreenHeight = 720;

Matrix transformation =
Matrix.CreateTranslation(-(ScreenWidth /2), -(ScreenHeight/2), 0) *
Matrix.CreateScale(1) *
Matrix.CreateRotationZ(MathHelper.ToRadians(180f)) *
Matrix.CreateTranslation(ScreenWidth /2, ScreenHeight/2, 0);

The origin is at the middle of the screen, which is where it will start to rotate So take a paper and rotate around the middle, after rotating it 180 degrees it will be upside down. It will look as if it hasn't moved at all but it will be upside down.

Set origin to 0, 0 and rotate it. If you rotate the paper at the top left corner, it will now rotate so that it's so to speak at X = -ScreenWidth, Y = -ScreenHeight. It will be flipped so it's to your left and above your hand.

So the matrix transformation above is for a screen that is upside down.

If you rotate it and then later scale it, the paper will be rotating around the wrong axis because it's size is incorrect. So it's important for it to be calculated in the correct order.

share|improve this answer
add comment

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