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

C# XNA 2D相机-如何将其锁定/居中到动画精灵?,c#,xna,camera,sprite,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.

嘿,我试图让我的相机跟随我的精灵,由于某种原因,精灵总是比我的相机移动得快,我的相机无法夹在屏幕上。我想让它,使相机是不断集中在精灵和跟随他,因为他移动

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);
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用Microsoft.Xna.Framework;
使用Microsoft.Xna.Framework.Graphics;
使用Microsoft.Xna.Framework.Input;
名称空间WintermRPG
{
公共类动画精灵
{
面向公共枚举
{
左边
正确的,
向上的
向下
}
面向公众的方向;
公共字典动画=新建字典();
摄像头=新摄像头();
公共向量2位置=向量2.0;
纹理2D纹理;
public bool IsCharacter=false;
公共bool isAnimating=true;
字符串animationName=null;
浮动速度=2f;
公共浮动速度
{
获取{返回速度;}
设置{speed=Math.Max(值,.1f);}
}
公共字符串CurrentAnimationName
{
获取{return animationName;}
设置
{
if(Animations.ContainsKey(值))
animationName=值;
}
}
公共向量2 OriginOffset=Vector2.0;
公共矢量源
{
获取{return Position+OriginOffset;}
}
公共矢量2中心
{
得到
{
返回位置+新矢量2(
CurrentAnimation.currentRect.Width/2,
CurrentAnimation.currentRect.Height/2);
}
}
公共框架动画
{
得到
{
如果(!string.IsNullOrEmpty(animationName))
返回动画[动画名称];
其他的
返回null;
}
}
公共动画精灵(纹理2D纹理,布尔isCharacter)
{
这个纹理=纹理;
IsCharacter=IsCharacter;
}
公共动画精灵(纹理2D纹理、布尔isCharacter、摄像头)
{
这个纹理=纹理;
IsCharacter=IsCharacter;
this.cam=cam;
}
公共空隙区域(内部宽度、内部高度)
{
如果(位置X<0)
位置X=0;
如果(位置Y<0)
位置Y=0;
if(位置X>宽度-CurrentAnimation.currentRect.width)
位置.X=宽度-CurrentAnimation.currentRect.width;
if(位置Y>高度-CurrentAnimation.currentRect.height)
Position.Y=高度-CurrentAnimation.currentRect.height;
}
私有void updateScreetAnimation(矢量2运动)
{
float motionAngle=(float)Math.Atan2(motion.Y,motion.X);
如果(运动角度>=-MathHelper.PiOver4&&
motionAngle=-MathHelper.PiOver4&&
运动角度(0)
{
movement.X++;
朝向方向=朝向。右侧;
}
if(state.ThumbSticks.Left.Y>0)
{  
运动-Y;
朝向方向=朝上;
}
if(状态.拇指杆.左.Y<0)
{
movement.Y++;
朝向方向=朝下;
}
if(运动!=Vector2.Zero)
{
运动。正常化();
位置+=移动;
凸轮位置=位置;
更新脚本动画(运动);
isAnimating=true;
}
其他的
isAnimating=假;
}
如果(!isAnimating)
返回;
FrameAnimation=当前动画;
如果(动画==null)
{
如果(Animations.Count>0)
{
string[]keys=新字符串[Animations.Count];
动画.key.CopyTo(key,0);
animationName=关键点[0];
动画=当前动画;
}
其他的
返回;
}
动画。更新(游戏时间);
}
公开作废抽签(SpriteBatch sb)
{
FrameAnimation=当前动画;
如果(动画!=null)
{
绘制(纹理、位置、动画、当前矩形、颜色、白色);
}
}
}
}

对于您正在尝试的操作,这里可能有一个更简单的解决方案

将角色放置在屏幕上一个不可见的框中。每当角色尝试移出此边界框时,您都会将级别滚动到其移动。如果你想让相机绝对聚焦在你的角色上,你可以在你的角色周围滚动水平。您仍然需要跟踪屏幕上的字符位置和关卡的偏移滚动。如果您同时拥有这两个属性,您就知道角色在“级别”中的碰撞位置


如果这不是您想要的,我很抱歉,但这是一种更简单的方法。

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

  • 从顶部平移原点 从左到窗户中央。 (添加半视图大小)
  • 这样翻译 角色在中心 窗边。(减法字符 (职位)
  • 下面的代码显示了一个doe的camera类
    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(SpriteSortMode.Deferred, null, null, null, null, null, m_camera.viewMatrix);