【问题标题】:XNA: Scrolling A Linearly Wrapped, Rotating Texture, Up, Down, Left, And Right:XNA:向上、向下、向左和向右滚动线性环绕、旋转纹理:
【发布时间】:2011-12-13 11:33:08
【问题描述】:

我正在为 PC 开发一个基于 XNA 的简单游戏,我的游戏屏幕窗口大小为 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() 方法来实现这一点?

感谢阅读.....

【问题讨论】:

    标签: c# image xna scroll xna-4.0


    【解决方案1】:

    根据您的问题,我推测您希望鼠标控制相机,而旋转仅影响纹理。 为此,所需的更改会影响 Draw 方法。调用 Spritebatch.Begin 时,您应该使用 x 和 y 值将转换矩阵作为参数传递。这允许您在世界坐标中旋转纹理,同时独立于旋转移动相机。

    检查这个问题 - Spritebatch.Begin() Transform Matrix - 了解变换矩阵的工作原理。

    【讨论】:

    • 感谢您的回复,Elideb。我所有的“相机”都由一个矩形组成,它显示了我的 1280 X 1280 线性包裹纹理的一部分。我可能是错的,但我不相信我需要一个转换矩阵来做我想做的事情,因为我发布的代码工作正常,直到我引入纹理围绕其原点的旋转。我需要以某种方式调整 x 和 y 值以补偿旋转运动。例如 - 如果我将鼠标水平向左移动,我希望纹理在围绕其原点旋转时向左滚动。
    【解决方案2】:

    这似乎有效。可能有一个更优雅的解决方案,但它肯定是一个需要解决的巧妙问题。

    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);
    
        }
    }  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多