2013-10-14 48 views
0

所以当我的船只是一个纹理时,我会点击屏幕,船只会面对那个点击点并慢慢向它移动,只有当纹理的中间达到所述点时停止我想了)。所以现在我尝试对它进行动画处理。动画工作正常,但现在船舶不会面向我点击的位置的方向,它会面向左或右几度,并且船驶向该点,但是当船停在其确切点时就像它只是一个纹理时所做的一样,而不是它总是停下来。动画帧旋转不正确

我的动画类

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

回答

0

如果你的飞船面临几度到左或右,我认为它意味着您的spriteBatch.DrawsourceRectangle参数不符合RECT。

对于第二个问题,当飞船停下来时,它永远不会在确切点上,当它接近mousePosition时,您必须手动设置它的位置,因为设置speedForThisFrame = 0无法确保它处于正确的位置,您仍然存在(mousePosition - position).Length()的不确定性。

编辑

我的意思是这样的:

​​

假设position在你的飞船精灵的弓为中心,或任何你需要的。

EDIT 2

当你position相同mousePosition XNA不会让你Normalize一个Vector2其lenght为0。因此,尝试这样的事:

if (mousePosition != position) 
{ 
    distance = mousePosition - position; 
    distance.Normalize(); 

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

在这方式你的rotation将保持不变,在飞船到达mousePosition之前。

+0

Ive搞砸了sourceRectangle,我无法修复它,如果这就是问题,至于speedForThisFrame = 0是因为如果我没有这个图像超过了鼠标位置,然后意识到它过去了,回去了,如此如此,并在图像上产生一种抽动效果。 speedForThisFrame不是问题,它的工作原理是当我不在动画类中包含旋转时draw() – Oblivion

+0

你不明白,你不必删除它,你需要设置你的飞船位置时你设置'speedForThisFrame = 0',因为你有一个不确定的'(mousePosition - position).Length()',你不知道你到底在哪里。 – pinckerman

+0

我不确定你的意思,你把什么放在哪里? – Oblivion