与2D相机XNA的边界框碰撞

时间:2014-02-24 07:32:01

标签: matrix camera xna-4.0 point

我把头发拉出去尝试这个数字。我有一个简单的按钮,检查鼠标是否结束,然后更改纹理。它工作正常。但是,当我在混音中添加相机时,它会破坏一切。我已经尝试转换我用于边界框碰撞的鼠标和矩形,但它不起作用。这是我的按钮代码:

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

namespace x.Graphics.UI
{
    public enum ButtonStates
    {
        Normal,
        Hover,
        Pressed
    }
    public delegate void ButtonPress();
    public class Button
    {
        public Texture2D Texture
        {
            get
            {
                Texture2D result = null;

                switch (ButtonState)
                {
                    case ButtonStates.Normal:
                        result = NormalTexture;
                        break;

                    case ButtonStates.Hover:
                        result = HoverTexture;
                        break;

                    case ButtonStates.Pressed:
                        result = DownTexture;
                        break;
                }

                return result;
            }
        }
        public Vector2 Position { get; set; }
        public event ButtonPress ButtonPressed;
        public ButtonStates ButtonState { get; set; }
        public Rectangle CollisionRect { get; set; }

        private Texture2D NormalTexture;
        private Texture2D HoverTexture;
        private Texture2D DownTexture;
        private MouseState mouseState;
        private MouseState previousMouseState;

        public Button(Texture2D normalTexture, Texture2D hoverTexture, Texture2D downTexture,
            Vector2 position)
        {
            NormalTexture = normalTexture;
            HoverTexture = hoverTexture;
            DownTexture = downTexture;
            Position = position;

            mouseState = Mouse.GetState();
            previousMouseState = mouseState;

            CollisionRect = new Rectangle((int)Position.X, (int)Position.Y,
                    Texture.Width,
                    Texture.Height);
        }

        public void Update (MouseState currentState)
        {
            mouseState = currentState;

            if (CollisionRect.Contains(new Point(mouseState.X, mouseState.Y)))
            {
                if (mouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    ButtonState = ButtonStates.Pressed;
                    ButtonPressed();
                }
                else
                    ButtonState = ButtonStates.Hover;
            }
            else
                ButtonState = ButtonStates.Normal;
        }

        public void Update(MouseState currentState, Camera camera)
        {
            Vector2 mouse = new Vector2(mouseState.X, mouseState.Y);
            mouse = Vector2.Transform(mouse, camera.InverseTransform);
            CollisionRect = CalculateTransformedBoundingBox(CollisionRect, c.InverseTransform);

            Console.WriteLine("Rectangle[X: {0}, y: {1}], Mouse:[X: {2}, Y: {3}]", CollisionRect.X, CollisionRect.Y, mouse.X, mouse.Y);

            if (CollisionRect.Contains(new Point((int)mouse.X, (int)mouse.Y)))
            {
                if (mouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    ButtonState = ButtonStates.Pressed;
                    ButtonPressed();
                }
                else
                    ButtonState = ButtonStates.Hover;
            }
            else
                ButtonState = ButtonStates.Normal;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Texture, Position, null, Color.White, 0.0f,
                Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);
        }

        private Rectangle CalculateTransformedBoundingBox(Rectangle local, Matrix toWorldSpace)
        {
            Vector2 leftTop = new Vector2(local.Left, local.Top);
            Vector2 rightTop = new Vector2(local.Right, local.Top);
            Vector2 leftBottom = new Vector2(local.Left, local.Bottom);
            Vector2 rightBottom = new Vector2(local.Right, local.Bottom);

            Vector2.Transform(ref leftTop, ref toWorldSpace,
                             out leftTop);
            Vector2.Transform(ref rightTop, ref toWorldSpace,
                             out rightTop);
            Vector2.Transform(ref leftBottom, ref toWorldSpace,
                             out leftBottom);
            Vector2.Transform(ref rightBottom, ref toWorldSpace,
                             out rightBottom);

            // Find the minimum and maximum extents of the
            // rectangle in world space
            Vector2 min = Vector2.Min(Vector2.Min(leftTop, rightTop),
                                     Vector2.Min(leftBottom, rightBottom));
            Vector2 max = Vector2.Max(Vector2.Max(leftTop, rightTop),
                                     Vector2.Max(leftBottom, rightBottom));

            // Return that as a rectangle
            return new Rectangle((int)min.X, (int)min.Y,
                                (int)(max.X - min.X), (int)(max.Y - min.Y));
        }
    }
}

我的相机代码:

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

namespace x.Graphics
{
    public class Camera
    {
        protected float _zoom;
        protected Matrix _transform;
        protected Matrix _inverseTransform;
        protected Vector2 _pos;
        protected float _rotation;
        protected Viewport _viewport;
        protected MouseState _mState;
        protected KeyboardState _keyState;
        protected Int32 _scroll;

        public float Zoom
        {
            get { return _zoom; }
            set { _zoom = value; }
        }
        public Matrix Transform
        {
            get { return _transform; }
            set { _transform = value; }
        }
        public Matrix InverseTransform
        {
            get { return _inverseTransform; }
        }
        public Vector2 Pos
        {
            get { return _pos; }
            set { _pos = value; }
        }
        public float Rotation
        {
            get { return _rotation; }
            set { _rotation = value; }
        }

        public Camera(Viewport viewport)
        {
            _zoom = 1.0f;
            _scroll = 1;
            _rotation = 0.0f;
            _pos = Vector2.Zero;
            _viewport = viewport;
        }

        public void Update()
        {
            Input();
            MathHelper.Clamp(_zoom, 0.01f, 10.0f);
            _rotation = ClampAngle(_rotation);
            _transform =    Matrix.CreateRotationZ(_rotation) *
                            Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
                            Matrix.CreateTranslation(_pos.X, _pos.Y, 0);
            _inverseTransform = Matrix.Invert(_transform);
        }

        protected virtual void Input()
        {
            _mState = Mouse.GetState();
            _keyState = Keyboard.GetState();

            //Check Move
            if (_keyState.IsKeyDown(Keys.A))
            {
                _pos.X += 10f;
            }
            if (_keyState.IsKeyDown(Keys.D))
            {
                _pos.X -= 10f;
            }
            if (_keyState.IsKeyDown(Keys.W))
            {
                _pos.Y -= 10f;
            }
            if (_keyState.IsKeyDown(Keys.S))
            {
                _pos.Y += 10f;
            }
        }

        protected float ClampAngle(float radians)
        {
            while (radians < -MathHelper.Pi)
            {
                radians += MathHelper.TwoPi;
            }
            while (radians > MathHelper.Pi)
            {
                radians -= MathHelper.TwoPi;
            }
            return radians;
        }
    }
}

我不是100%确定出了什么问题,但只有按下按钮才会改变鼠标位置。我真的很困惑,我以前从未使用过相机。任何帮助将非常感激。谢谢!

更新: 在我尝试移动相机之前,它会检测到鼠标位于按钮上方。之后,矩形的坐标会不断增加。

1 个答案:

答案 0 :(得分:1)

不要变换边界框...很容易变换鼠标坐标...;)

使用相机矩阵的逆变换将鼠标坐标转换为边界框的相同空间。