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

时间:2011-07-11 21:15:00

标签: c# image xna scroll xna-4.0

我正在为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()方法来实现这个目标?

感谢您阅读.....

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

这似乎有效。可能有一个更优雅的解决方案,但它确定要解决一个简洁的问题。

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

    }
}