Note that there are some explanatory texts on larger screens.

plurals
  1. POXNA 2d rotation around centre
    text
    copied!<p>I'm trying to include support for zooming and rotating my camera class, around the centre of the viewport.</p> <p>In my application, I've already positioned sprites manually before entering the SpriteBatch.Begin code, according to where the camera is positioned (to make culling easier to implement). Although each sprite is positioned manually, I would rather not rotate and scale each sprite individually.</p> <p>I therefore am trying to use the matrixTransform argument on the SpriteBatch.Begin method.</p> <p>Below is a hard-coded application I've made to illustrate the problem (using a Car.png content image). The rotation isn't as fast as I'd expect (10 degrees rotation every frame?), and it rotates/zooms about the top left. I would like it to rotate around the centre of the screen, which would always keep the middle car in the centre, and also scale from that point.</p> <p>I have tried several combinations of creating matrix translations, reordering/adding/multiplying/translating by the halfway distance of viewport, but I don't really understand how matrices work. I've also tried the solutions on several websites which I haven't managed to make work for me.</p> <p>Can someone tell me the matrix translations I have to create, or point me in the direction of a website you think will work for my setup?</p> <p><strong>Windows XNA application to demonstrate the problem:</strong></p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; namespace RenderTest { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D _carTexture; float _zoom = 1.0f; float _rotationInDegrees = 0.0f; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); _carTexture = Content.Load&lt;Texture2D&gt;("Car"); } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Up)) // Zoom in key _zoom *= 1.1f; if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Down)) // Zoom out key _zoom /= 1.1f; if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Left)) // Rotate anticlockwise key _rotationInDegrees -= 10; if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Right)) // Rotate clockwise key _rotationInDegrees += 10; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullNone, null, GetMatrix(GraphicsDevice)); spriteBatch.Draw(_carTexture, new Rectangle(0, 0, 50, 50), Color.White);//Square car placed top left spriteBatch.Draw(_carTexture, new Rectangle(GraphicsDevice.Viewport.Width / 2 - 25, GraphicsDevice.Viewport.Height / 2 - 50, 50, 100), Color.Green);//Car placed centre spriteBatch.Draw(_carTexture, new Rectangle(GraphicsDevice.Viewport.Width / 2 + 100, GraphicsDevice.Viewport.Height / 2 + 100, 50, 50), Color.Black);//Off centre but always within screen spriteBatch.End(); base.Draw(gameTime); } Matrix GetMatrix(GraphicsDevice graphicsDevice) { Matrix translationMatrix = Matrix.CreateTranslation(0, 0, 0); Matrix rotationMatrix = Matrix.CreateRotationZ(MathHelper.ToRadians(MathHelper.ToRadians(_rotationInDegrees))); Matrix zoomMatrix = Matrix.CreateScale(_zoom); Matrix compositeMatrix = translationMatrix * rotationMatrix * zoomMatrix; return compositeMatrix; } } } </code></pre> <p>Thanks,</p> <p>Lee</p> <p><strong>Solution</strong></p> <pre><code> Matrix GetMatrix(GraphicsDevice graphicsDevice) { Matrix translateToOrigin = Matrix.CreateTranslation(-graphicsDevice.Viewport.Width / 2, -graphicsDevice.Viewport.Height / 2, 0); Matrix rotationMatrix = Matrix.CreateRotationZ(MathHelper.ToRadians(_rotationInDegrees)); Matrix zoomMatrix = Matrix.CreateScale(_zoom); Matrix translateBackToPosition = Matrix.CreateTranslation(graphicsDevice.Viewport.Width / 2, graphicsDevice.Viewport.Height / 2, 0); Matrix compositeMatrix = translateToOrigin * rotationMatrix * zoomMatrix * translateBackToPosition; return compositeMatrix; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload