2011-01-11 69 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);