XNA 2D相机-如何将其锁定/居中放置到动画精灵上? [英] XNA 2D Camera - How to lock/center it to an animated sprite?

查看:73
本文介绍了XNA 2D相机-如何将其锁定/居中放置到动画精灵上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿,我试图让我的相机跟随我的精灵移动,由于某种原因,精灵始终比我的相机移动得快,并且我的相机无法固定在屏幕上。我想这样做,以使相机始终位于小精灵的中心,并在他移动时跟随他。

Hey I'm trying to make my camera follow my sprite and for some reason the sprite is always moving faster than my camera and my camera is unable to clamp to the screen. I would like to make it so that the camera is constantly centered on the sprite and follows him as he moves.

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


推荐答案

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

Your camera needs to generate a view matrix for the SpriteBatch.Begin method. The view matrix must make two translations.


  1. 将原点从顶部
    左移到窗口中心。
    (添加一半视图大小)

  2. 进行翻译,使
    字符位于窗口的中央
    处。 (减去字符
    位置)

以下代码显示了执行此操作的摄像头类:

The following code shows a camera class that does this:

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方法中的视图矩阵:

Then you just need to set the view matrix in the SpriteBatch.Begin method:

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

这篇关于XNA 2D相机-如何将其锁定/居中放置到动画精灵上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆