XNA 2D相机 - 如何将其锁定/居中到动画精灵?

mra*_*guy 2 c# xna camera sprite

嘿我正试图让我的相机跟着我的精灵,由于某种原因,精灵总是比我的相机移动得更快,我的相机无法夹到屏幕上.我想这样做,以便摄像机始终以精灵为中心,并在他移动时跟随他.

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Emp*_*ean 6

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

  1. 将原点从左上角翻译到窗口的中心.(添加半视图大小)
  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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, m_camera.viewMatrix);
Run Code Online (Sandbox Code Playgroud)