2011-01-11 94 views
2

嘿,我试图让我的相机跟随我的精灵,出于某种原因精灵总是比我的相机移动更快,我的相机无法夹紧到屏幕上。我想做的是让相机始终以精灵为中心,并在他移动时跟随他。XNA 2D相机 - 如何锁定/居中它为动画精灵?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 

namespace wintertermrpg 
{ 
    public class AnimatedSprite 
    { 
     public enum Facing 
     { 
      Left, 
      Right, 
      Up, 
      Down 
     } 
     public Facing facingDirection; 

     public Dictionary<string, FrameAnimation> Animations = new Dictionary<string,  FrameAnimation>(); 
     Camera cam = new Camera(); 
     public Vector2 Position = Vector2.Zero; 
     Texture2D texture; 
     public bool IsCharacter = false; 
     public bool isAnimating = true; 
     string animationName = null; 
     float speed = 2f; 

     public float Speed 
     { 
      get { return speed; } 
      set { speed = Math.Max(value, .1f); } 
     } 

     public string CurrentAnimationName 
     { 
      get { return animationName; } 
      set 
      { 
       if (Animations.ContainsKey(value)) 
        animationName = value; 
      } 
     } 

     public Vector2 OriginOffset = Vector2.Zero; 
     public Vector2 Origin 
     { 
      get { return Position + OriginOffset; } 
     } 

     public Vector2 Center 
     { 
      get 
      { 
       return Position + new Vector2(
        CurrentAnimation.currentRect.Width/2, 
        CurrentAnimation.currentRect.Height/2); 
      } 
     } 

     public FrameAnimation CurrentAnimation 
     { 
      get 
      { 
       if (!string.IsNullOrEmpty(animationName)) 
        return Animations[animationName]; 
       else 
        return null; 
      } 
     } 

     public AnimatedSprite(Texture2D texture, bool isCharacter) 
     { 
      this.texture = texture; 
      IsCharacter = isCharacter; 
     } 

     public AnimatedSprite(Texture2D texture, bool isCharacter, Camera cam) 
     { 
      this.texture = texture; 
      IsCharacter = isCharacter; 
      this.cam = cam; 
     } 

     public void clampToArea(int width, int height) 
     { 
      if (Position.X < 0) 
       Position.X = 0; 
      if (Position.Y < 0) 
       Position.Y = 0; 
      if (Position.X > width - CurrentAnimation.currentRect.Width) 
       Position.X = width - CurrentAnimation.currentRect.Width; 
      if (Position.Y > height - CurrentAnimation.currentRect.Height) 
       Position.Y = height - CurrentAnimation.currentRect.Height; 
     } 

     private void updateSpriteAnimation(Vector2 motion) 
     { 
      float motionAngle = (float)Math.Atan2(motion.Y, motion.X); 

      if (motionAngle >= -MathHelper.PiOver4 && 
       motionAngle <= MathHelper.PiOver4) 
       CurrentAnimationName = "Right"; 
      else if (motionAngle >= -MathHelper.PiOver4 && 
       motionAngle <= 3f * MathHelper.PiOver4) 
       CurrentAnimationName = "Down"; 
      else if (motionAngle <= -MathHelper.PiOver4 && 
       motionAngle >= -3f * MathHelper.PiOver4) 
       CurrentAnimationName = "Up"; 
      else 
       CurrentAnimationName = "Left"; 
     } 

     public void update(GameTime gameTime) 
     { 
      GamePadState state = GamePad.GetState(PlayerIndex.One); 
      if (IsCharacter) 
      { 
       Vector2 movement = Vector2.Zero; 
       if (state.ThumbSticks.Left.X < 0) 
       { 
        movement.X--; 
        facingDirection = Facing.Left; 
       } 
       if (state.ThumbSticks.Left.X > 0) 
       { 
        movement.X++; 
        facingDirection = Facing.Right; 
       } 
       if (state.ThumbSticks.Left.Y > 0) 
       { 
        movement.Y--; 
        facingDirection = Facing.Up; 
       } 
       if (state.ThumbSticks.Left.Y < 0) 
       { 
        movement.Y++; 
        facingDirection = Facing.Down; 
       } 
       if (movement != Vector2.Zero) 
       { 
        movement.Normalize(); 
        Position += movement; 
        cam.Pos = Position; 
        updateSpriteAnimation(movement); 
        isAnimating = true; 
       } 
       else 
        isAnimating = false; 

      } 

      if (!isAnimating) 
       return; 
      FrameAnimation animation = CurrentAnimation; 

      if (animation == null) 
      { 
       if (Animations.Count > 0) 
       { 
        string[] keys = new string[Animations.Count]; 
        Animations.Keys.CopyTo(keys, 0); 
        animationName = keys[0]; 
        animation = CurrentAnimation; 
       } 
       else 
        return; 
      } 
      animation.Update(gameTime); 

     } 

     public void draw(SpriteBatch sb) 
     { 
      FrameAnimation animation = CurrentAnimation; 
      if (animation != null) 
      { 
       sb.Draw(texture, Position, animation.currentRect, Color.White); 
      } 
     } 
    } 
} 
+0

那么先调用updateSpriteAnimation,然后将相机的位置设置为新的精灵位置呢? – 2011-01-11 21:35:58

回答

0

这可能是一个更简单的解决方案,你正在尝试做什么。

将您的角色置于不可见框内的屏幕上。只要角色试图移动到该边界框外,就可以将该级别滚动至其移动。如果你想让你的角色有绝对的相机对焦,你可以在角色周围滚动。您仍然需要跟踪屏幕上的字符位置和关卡的偏移滚动条。如果你有这两种情况,你就知道你的角色在哪个级别上碰撞。

如果这不是你正在寻找的,我很抱歉,但它是一个更简单的方法。

6

您的相机需要为SpriteBatch.Begin方法生成视图矩阵。视图矩阵必须进行两次翻译。

  1. 将顶部 的原点翻译为左边的窗口中心。 (Add half view size)
  2. 这样翻译就是 该字符位于窗口的中心 。 (减去字符 位置)

下面的代码显示一个照相机类,这是否:

using Microsoft.Xna.Framework; 

namespace wintertermrpg 
{ 
    public class Camera 
    { 
     public Matrix viewMatrix; 
     private Vector2 m_position; 
     private Vector2 m_halfViewSize; 

     public Camera(Rectangle clientRect) 
     { 
      m_halfViewSize = new Vector2(clientRect.Width * 0.5f, clientRect.Height * 0.5f); 
      UpdateViewMatrix(); 
     } 

     public Vector2 Pos 
     { 
      get 
      { 
       return m_position; 
      } 

      set 
      { 
       m_position = value; 
       UpdateViewMatrix(); 
      } 
     } 

     private void UpdateViewMatrix() 
     { 
      viewMatrix = Matrix.CreateTranslation(m_halfViewSize.X - m_position.X, m_halfViewSize.Y - m_position.Y, 0.0f); 
     } 
    } 
} 

然后,你只需要设置在SpriteBatch.Begin方法视图矩阵:

spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, m_camera.viewMatrix);