滚动线性包裹,旋转纹理,上,下,左,右:

本文关键字:纹理 线性 包裹 旋转 滚动 | 更新日期: 2023-09-27 18:01:42

我正在制作一款简单的基于XNA的PC游戏,我有一个游戏屏幕窗口大小为1024 X 768,我想滚动,在我移动鼠标的方向,线性包裹,旋转纹理,大小为1280 X 1280。

这个纹理的原点被设置为它的中心点(640,640),然后我将这个纹理放在屏幕上游戏窗口的中间位置(512,384)。

到目前为止,我的代码(粘贴在下面的全部代码)工作完美,直到我引入旋转的混合。

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    int x;
    int y;
    float z = 250f;
    Texture2D Overlay;
    Texture2D RotatingBackground;
    Rectangle? sourceRectangle;
    Color color;
    float rotation;
    Vector2 ScreenCenter;
    Vector2 Origin;
    Vector2 scale;
    Vector2 Direction;
    SpriteEffects effects;
    float layerDepth;
    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }
    protected override void Initialize()
    {
        graphics.PreferredBackBufferWidth = 1024;
        graphics.PreferredBackBufferHeight = 768;
        graphics.ApplyChanges();
        Direction = Vector2.Zero;    
        IsMouseVisible = true;
        ScreenCenter = new Vector2(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2);
        Mouse.SetPosition((int)graphics.PreferredBackBufferWidth / 2, (int)graphics.PreferredBackBufferHeight / 2);
        sourceRectangle = null;
        color = Color.White;
        rotation = 0.0f;
        scale = new Vector2(1.0f, 1.0f);
        effects = SpriteEffects.None;
        layerDepth = 1.0f;
        base.Initialize();
    }
    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        Overlay = Content.Load<Texture2D>("Overlay");
        RotatingBackground = Content.Load<Texture2D>("Background");
        Origin = new Vector2((int)RotatingBackground.Width / 2, (int)RotatingBackground.Height / 2);
    }

    protected override void UnloadContent()
    {
    }
    protected override void Update(GameTime gameTime)
    {
        float timePassed = (float)gameTime.ElapsedGameTime.TotalSeconds;
        MouseState ms = Mouse.GetState();
        Vector2 MousePosition = new Vector2(ms.X, ms.Y);
        Direction = ScreenCenter - MousePosition;
        if (Direction != Vector2.Zero)
        {
            Direction.Normalize();
        }
        x += (int)(Direction.X * z * timePassed);
        y += (int)(Direction.Y * z * timePassed);

        //No rotation = texture scrolls as intended, With rotation = texture no longer scrolls in the direction of the mouse. My update method needs to somehow compensate for this.         
        //rotation += 0.01f;  
        base.Update(gameTime);
    }
    protected override void Draw(GameTime gameTime)
    {
        spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null);
        spriteBatch.Draw(RotatingBackground, ScreenCenter, new Rectangle(x, y, RotatingBackground.Width, RotatingBackground.Height), color, rotation, Origin, scale, effects, layerDepth);
        spriteBatch.Draw(Overlay, Vector2.Zero, Color.White);
        spriteBatch.End();
        base.Draw(gameTime);
    }
}  

例如,如果我要向右旋转纹理,那么从屏幕中心直接向上移动鼠标会导致纹理对角线向上和向右滚动-这不是我的意图-如果我在任何方向移动鼠标,我希望纹理在该方向上滚动,就像我从未在混合中引入旋转一样。

我如何改变我的Update()方法来实现这一点?

感谢阅读.....

滚动线性包裹,旋转纹理,上,下,左,右:

从你的问题,我收集到你想要鼠标来控制相机,旋转只影响纹理。为此,所需的更改会影响Draw方法。调用Spritebatch时。首先,您应该使用x和y值传递一个变换矩阵作为参数。这允许你在世界坐标中旋转纹理,同时移动相机独立于旋转。

检查这个问题- Spritebatch.Begin() Transform Matrix -了解变换矩阵是如何工作的

这似乎行得通。也许有一个更优雅的解决方案,但这肯定是一个需要解决的整洁问题。

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    int x;
    int y;
    float z = 250f;
    Texture2D Overlay;
    Texture2D RotatingBackground;
    Rectangle? sourceRectangle;
    Color color;
    float rotation;
    Vector2 ScreenCenter;
    Vector2 Origin;
    Vector2 scale;
    Vector2 Direction;
    SpriteEffects effects;
    float layerDepth;
    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }
    protected override void Initialize()
    {
        graphics.PreferredBackBufferWidth = 1024;
        graphics.PreferredBackBufferHeight = 768;
        graphics.ApplyChanges();
        Direction = Vector2.Zero;
        IsMouseVisible = true;
        ScreenCenter = new Vector2(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2);
        Mouse.SetPosition((int)graphics.PreferredBackBufferWidth / 2, (int)graphics.PreferredBackBufferHeight / 2);
        sourceRectangle = null;
        color = Color.White;
        rotation = 0.0f;
        scale = new Vector2(1.0f, 1.0f);
        effects = SpriteEffects.None;
        layerDepth = 1.0f;
        base.Initialize();
    }
    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        Overlay = Content.Load<Texture2D>("Overlay");
        RotatingBackground = Content.Load<Texture2D>("Background");
        Origin = new Vector2((int)RotatingBackground.Width / 2, (int)RotatingBackground.Height / 2);
    }

    protected override void UnloadContent()
    {
    }
    protected override void Update(GameTime gameTime)
    {
        float timePassed = (float)gameTime.ElapsedGameTime.TotalSeconds;
        MouseState ms = Mouse.GetState();
        Vector2 MousePosition = new Vector2(ms.X, ms.Y);
        Direction = ScreenCenter - MousePosition;
        if (Direction != Vector2.Zero)
        {
            float angle = 0;
            angle = (float)Math.Atan2(Direction.Y, Direction.X) - rotation;
            Direction.X = (float)Math.Cos(angle);
            Direction.Y = (float)Math.Sin(angle);
            Direction.Normalize();
        }
        x += (int)(Direction.X * z * timePassed);
        y += (int)(Direction.Y * z * timePassed);

        //No rotation = texture scrolls as intended, With rotation = texture no longer scrolls in the direction of the mouse. My update method needs to somehow compensate for this.         
        rotation += .01f ;
        if (rotation > MathHelper.Pi * 2)
        {
            rotation -= (MathHelper.Pi * 2);
        }
        base.Update(gameTime);
    }
    protected override void Draw(GameTime gameTime)
    {
        spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null);
        spriteBatch.Draw(RotatingBackground, ScreenCenter, new Rectangle(x, y, RotatingBackground.Width, RotatingBackground.Height), color, rotation, Origin, scale, effects, layerDepth);
        spriteBatch.Draw(Overlay, Vector2.Zero, Color.White);
        spriteBatch.End();
        base.Draw(gameTime);
    }
}