动画帧无法正确旋转

时间:2013-10-14 22:28:28

标签: c# animation xna

所以,当我的船只是一个纹理时,我会点击屏幕,船会面对那个点击点并慢慢向它移动,只有当纹理的中间到达所述点(我想要的)时才停止。所以现在我尝试动画它。动画工作正常,但现在船不会面向我点击的位置方向,它朝向左侧或右侧几度,并且船行进到该点但是当它停止时它从不在确切点就像它只是一个纹理时所做的那样,相反它总是会远离它。

我的动画类

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace AsteroidAvoider
{
    class Animation
    {
        float rotation;

        // The image representing the collection of images used for animation
        Texture2D spriteStrip;

        // The scale used to display the sprite strip
        float scale;

        // The time since we last updated the frame
        int elapsedTime;

        // The time we display a frame until the next one
        int frameTime;

        // The number of frames that the animation contains
        int frameCount;

        // The index of the current frame we are displaying
        int currentFrame;

        // The color of the frame we will be displaying
        Color color;

        // The area of the image strip we want to display
        Rectangle sourceRect = new Rectangle();

        // The area where we want to display the image strip in the game
        Rectangle destinationRect = new Rectangle();

        // Width of a given frame
        public int FrameWidth;

        // Height of a given frame
        public int FrameHeight;

        // The state of the Animation
        public bool Active;

        // Determines if the animation will keep playing or deactivate after one run
        public bool Looping;

        public Vector2 Position;

        public void Initialize(Texture2D texture, Vector2 position, int frameWidth, int frameHeight, int frameCount, int frametime, Color color, float scale, bool looping)
        {

            // Keep a local copy of the values passed in
            this.color = color;
            this.FrameWidth = frameWidth;
            this.FrameHeight = frameHeight;
            this.frameCount = frameCount;
            this.frameTime = frametime;
            this.scale = scale;

            Looping = looping;
            Position = position;
            spriteStrip = texture;

            // Set the time to zero
            elapsedTime = 0;
            currentFrame = 0;

            // Set the Animation to active by default
            Active = true;
        }

        public void Update(GameTime gameTime)
        {
            // Do not update the game if we are not active
            if (Active == false)
                return;

            // Update the elapsed time
            elapsedTime += (int)gameTime.ElapsedGameTime.TotalMilliseconds;

            // If the elapsed time is larger than the frame time
            // we need to switch frames
            if (elapsedTime > frameTime)
            {
                // Move to the next frame
                currentFrame++;

                // If the currentFrame is equal to frameCount reset currentFrame to zero
                if (currentFrame == frameCount)
                {
                    currentFrame = 0;
                    // If we are not looping deactivate the animation
                    if (Looping == false)
                        Active = false;
                }

                // Reset the elapsed time to zero
                elapsedTime = 0;
            }

            // Grab the correct frame in the image strip by multiplying the currentFrame index by the frame width
            sourceRect = new Rectangle(currentFrame * FrameWidth, 0, FrameWidth, FrameHeight);

            // Grab the correct frame in the image strip by multiplying the currentFrame index by the frame width
            destinationRect = new Rectangle((int)Position.X - (int)(FrameWidth * scale) / 2,
            (int)Position.Y - (int)(FrameHeight * scale) / 2,
            (int)(FrameWidth * scale),
            (int)(FrameHeight * scale));
        }

        // Draw the Animation Strip
        public void Draw(SpriteBatch spriteBatch, float rotation)
        {
            this.rotation = rotation;

            // Only draw the animation when we are active
            if (Active)
            {
                //spriteBatch.Draw(spriteStrip, destinationRect, sourceRect, color);

                spriteBatch.Draw(spriteStrip, destinationRect, sourceRect, color, rotation, new Vector2(100, 75), SpriteEffects.None, 1);
            }
        }
    }
}

我的播放器课程

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 AsteroidAvoider
{
    class Player
    {
        public Vector2 position, distance, mousePosition;
        public float speed;
        public float rotation;
        public MouseState mouseState;
        public bool canMove = false;
        Animation playerAnimation;

        public Player(Animation playerAnimation, Vector2 position, float speed)
        {
            this.playerAnimation = playerAnimation;
            this.position = position;
            this.speed = speed;
            playerAnimation = new Animation();
        }

        public void Update(GameTime gameTime)
        {
            mouseState = Mouse.GetState();

            float speedForThisFrame = speed;

            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                mousePosition.X = mouseState.X;
                mousePosition.Y = mouseState.Y;
            }

            if ((mousePosition - position).Length() < speed)
                speedForThisFrame = 0;

            if ((mousePosition - position).Length() > speed)
                speedForThisFrame = 2.0f;

            distance = mousePosition - position;
            distance.Normalize();

            rotation = (float)Math.Atan2(distance.Y, distance.X);

            //position += distance * speedForThisFrame;

            if (speedForThisFrame == 0)
                position = mousePosition;
            else
                position += distance * speedForThisFrame;

            playerAnimation.Position = position;
            playerAnimation.Update(gameTime);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            playerAnimation.Draw(spriteBatch, rotation);
        }
    }
}

我的game1课程

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 AsteroidAvoider
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Player player;
        Texture2D playerImage;
        Animation playerAnimation;
        Vector2 playerPosition = new Vector2(550, 550);
        float playerSpeed = 2f;
        ParallaxingBackground bg;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.PreferredBackBufferWidth = 1500;
            graphics.PreferredBackBufferHeight = 600;
        }

        protected override void Initialize()
        {
            Animation playerAnimation = new Animation();
            playerImage = Content.Load<Texture2D>("player");
            player = new Player(playerAnimation, playerPosition, playerSpeed);

            playerAnimation.Initialize(playerImage, playerPosition, 200, 150, 4, 30, Color.White, 1f, true);
            this.IsMouseVisible = true;

            bg = new ParallaxingBackground();
            bg.Initialize(Content, "background", GraphicsDevice.Viewport.Width, -1);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here

        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            player.Update(gameTime);
            bg.Update();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            // TODO: Add your drawing code here
            bg.Draw(spriteBatch);
            player.Draw(spriteBatch);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

如果您的太空飞船朝向左侧或右侧倾斜几度,我认为这意味着您sourceRectangle的{​​{1}}参数不正确。

对于你的第二个问题,当宇宙飞船停止时它永远不会在确切的位置,你必须在它靠近spriteBatch.Draw时手动设置它的位置,因为设置mousePosition无法确保你它处于正确的位置,你仍然有speedForThisFrame = 0的不确定性。

修改

我的意思是这样的:

(mousePosition - position).Length()

假设if (speedForThisFrame == 0) position = mousePosition; else position += distance * speedForThisFrame; 位于您的飞船精灵的弓箭中心,或者您需要的任何地方。

编辑2

当您的positionposition相同时,XNA不允许您mousePosition {长度为0的Normalize。请尝试以下操作:

Vector2

这样,您的if (mousePosition != position) { distance = mousePosition - position; distance.Normalize(); rotation = (float)Math.Atan2(distance.Y, distance.X); } 将保持与宇宙飞船到达之前的rotation相同。