Matrix XNA 2d绕中心旋转

Matrix XNA 2d绕中心旋转,matrix,xna,Matrix,Xna,我试图包括对围绕视口中心缩放和旋转摄影机类的支持 在我的应用程序中,在输入SpriteBatch.Begin代码之前,我已经根据相机的位置手动定位了精灵(以便更容易实现消隐)。虽然每个精灵都是手动定位的,但我不希望单独旋转和缩放每个精灵 因此,我试图在SpriteBatch.Begin方法上使用matrixTransform参数 下面是我制作的一个硬编码应用程序,用于说明这个问题(使用Car.png内容图像)。旋转速度不如我预期的快(每帧旋转10度?),它在左上角旋转/缩放。我希望它围绕屏幕的中

我试图包括对围绕视口中心缩放和旋转摄影机类的支持

在我的应用程序中,在输入SpriteBatch.Begin代码之前,我已经根据相机的位置手动定位了精灵(以便更容易实现消隐)。虽然每个精灵都是手动定位的,但我不希望单独旋转和缩放每个精灵

因此,我试图在SpriteBatch.Begin方法上使用matrixTransform参数

下面是我制作的一个硬编码应用程序,用于说明这个问题(使用Car.png内容图像)。旋转速度不如我预期的快(每帧旋转10度?),它在左上角旋转/缩放。我希望它围绕屏幕的中心旋转,这将始终保持中间车在中心,并从该点开始缩放

我尝试过创建矩阵转换、按视口的一半距离重新排序/添加/乘以/转换的几种组合,但我并不真正理解矩阵是如何工作的。我也在几个网站上尝试过这些解决方案,但都没有成功

有人能告诉我矩阵翻译我必须创建,或指向我的方向,一个网站,你认为将工作为我的设置

演示问题的Windows XNA应用程序:

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<Texture2D>("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;
        }
    }
}

每次都应该使用相同的矩形,并在矩阵中进行定位


这样做的原因是,在使用矩形定位精灵后,矩阵将应用于精灵。所有子量化矩阵操作都将(0,0)视为原点,而不是您所期望的纹理中心。

据我所知,矩形用于定位精灵。我在不同的地方画了三个单独的精灵(为了简单起见,它们具有相同的纹理)。如果我使用同一个长方形,它们不是都放在彼此的上面吗?对不起,在意识到你想要做什么之前,我有点匆忙地发布了这个消息。您需要将(0,0)视为旋转和缩放所有对象的点,而不是(宽度/2,高度/2)。向上向左移动所有物体,使汽车中心位于(0,0),旋转、缩放,然后向后平移,使汽车中心位于(宽度和高度/2)。我认为这是可行的,但旋转似乎仍然太慢了……你似乎要转换两次弧度;)MathHelper.ToRadians(MathHelper.ToRadians)(不要紧,我将其转换为弧度两次,复制/粘贴错误!值得指出的是,对于
SpriteBatch
,剔除很少是值得优化的,即使是这样,通常也不必太精确(可以忽略旋转,只需绘制更大的区域)。()
    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;
    }