0
votes

I am creating a 2D platformer type game in XNA.

I currently have a camera object, with a position/rotation/zoomlevel that I use to generate a transformation matrix to pass to SpriteBatch.Begin(). This allows me to draw at in game coordinates instead of screen coordinates.

The relevant bit of the Camera code:

public Matrix GetViewMatrix() {
            cameraMatrix = Matrix.CreateScale(new Vector3(1f, -1f, 1f))                   
                   * Matrix.CreateTranslation(position.X, position.Y, 0f)
                   * Matrix.CreateScale(new Vector3(zoom,zoom,1f))
                   * Matrix.CreateRotationZ(rotation)
                   * Matrix.CreateTranslation(new Vector3(screenWidth*0.5f,screenHeight*0.5f,0));
            return cameraMatrix;
}

Which is used like so:

spriteBatch.Begin(SpriteSortMode.BackToFront, null, null, null, 
                  null, null, camera.GetViewMatrix());
//Draw Stuff
spriteBatch.End();

The problem is, that in order to get anything to actually draw, I have to scale by (1,-1) when I call spriteBatch.Draw(), otherwise I believe the textures get depth culled.

spriteBatch.Draw(content.Load<Texture2D>("whiteSquare"), Vector2.Zero, null, 
                 Color.White, 0f, Vector2.Zero, 
                 new Vector2(1f, -1f), 
                 SpriteEffects.None,0f);

Notice the Vector scaling argument in the 3rd line of the last sample. My question is twofold:

  1. How do I avoid having to pass this scaling argument/calling the longest form of spriteBatch.Draw() (kind of a violation of DRY, though I could wrap it I suppose).
  2. Am I doing something wrong (not "it doesnt work wrong" but "thats the wrong way to approach that problem" wrong)? I have seen mentions of viewport.Update() functions and Matrix.CreateOrthagonal etc, but I'm not quite sure if using them is simpler/better than a simple custom camera sort of deal.

Thank you very much.

1

1 Answers

0
votes

Why you are using Matrix.CreateScale(new Vector3(1f, -1f, 1f))? If you creating 2d platformer correct way to create camera transform is:

 Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0))*
 Matrix.CreateRotationZ(Rotation)*
 Matrix.CreateScale(new Vector3(Zoom, Zoom, 1))*
 Matrix.CreateTranslation(
    new Vector3(
       GraphicsDevice.Viewport.Width*0.5f,
       GraphicsDevice.Viewport.Height*0.5f, 0));

When using this camera transformation you can use default scale (1;1) on sprites.

Answering your questions:

  1. In the end you most likely will need to call longest form of spriteBatch.Draw() anyway, because it gives most options to manipulate sprites - which most likely you will need later. So this is not a problem, however negative scale does not seem like the correct way of drawing sprites.
  2. You are using the right way to draw sprites with camera transform in 2D, however as I mentioned before - transform itself seems incorrect.

P.S. Don't load content in the draw call ( content.Load<Texture2D>("whiteSquare") ), although it's cached and will not load each time you still should never do that.