C# XNA Handle mouse events?

Posted by user406470 on Game Development See other posts from Game Development or by user406470
Published on 2012-07-04T00:56:00Z Indexed on 2012/07/04 3:23 UTC
Read the original article Hit count: 448

Filed under:
|
|
|
|

I'm making a 2D game engine called Clixel over on GitHub. The problem I have relates to two classes, ClxMouse and ClxButton. In it I have a mouse class - the code for that can be viewed here.

ClxMouse

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace org.clixel
{
    public class ClxMouse : ClxSprite
    {
        private MouseState _curmouse, _lastmouse;
        public int Sensitivity = 3;
        public bool Lock = true;

        public Vector2 Change
        {
            get
            {
                return new Vector2(_curmouse.X - _lastmouse.X, _curmouse.Y - _lastmouse.Y);
            }
        }

        private int _scrollwheel;

        public int ScrollWheel
        {
            get
            {
                return _scrollwheel;
            }
        }

        public bool LeftDown
        {
            get
            {
                if (_curmouse.LeftButton == ButtonState.Pressed)
                    return true;
                else
                    return false;
            }
        }

        public bool RightDown
        {
            get
            {
                if (_curmouse.RightButton == ButtonState.Pressed)
                    return true;
                else
                    return false;
            }
        }

        public bool MiddleDown
        {
            get
            {
                if (_curmouse.MiddleButton == ButtonState.Pressed)
                    return true;
                else
                    return false;
            }
        }

        public bool LeftPressed
        {
            get
            {
                if (_curmouse.LeftButton == ButtonState.Pressed && _lastmouse.LeftButton == ButtonState.Released)
                    return true;
                else
                    return false;
            }
        }

        public bool RightPressed
        {
            get
            {
                if (_curmouse.RightButton == ButtonState.Pressed && _lastmouse.RightButton == ButtonState.Released)
                    return true;
                else
                    return false;
            }
        }

        public bool MiddlePressed
        {
            get
            {
                if (_curmouse.MiddleButton == ButtonState.Pressed && _lastmouse.MiddleButton == ButtonState.Released)
                    return true;
                else
                    return false;
            }
        }

        public bool LeftReleased
        {
            get
            {
                if (_curmouse.LeftButton == ButtonState.Released && _lastmouse.LeftButton == ButtonState.Pressed)
                    return true;
                else
                    return false;
            }
        }

        public bool RightReleased
        {
            get
            {
                if (_curmouse.RightButton == ButtonState.Released && _lastmouse.RightButton == ButtonState.Pressed)
                    return true;
                else
                    return false;
            }
        }

        public bool MiddleReleased
        {
            get
            {
                if (_curmouse.MiddleButton == ButtonState.Released && _lastmouse.MiddleButton == ButtonState.Pressed)
                    return true;
                else
                    return false;
            }
        }

        public MouseState CurMouse
        {
            get
            {
                return _curmouse;
            }
        }

        public MouseState LastMouse
        {
            get
            {
                return _lastmouse;
            }
        }

        public ClxMouse()
            : base(ClxG.Textures.Default.Cursor)
        {
            _curmouse = Mouse.GetState();
            _lastmouse = _curmouse;
            CollisionBox = new Rectangle(ClxG.Screen.Center.X, ClxG.Screen.Center.Y, Texture.Width, Texture.Height);
            this.Solid = false;
            DefaultPosition = new Vector2(CollisionBox.X, CollisionBox.Y);
            Mouse.SetPosition(CollisionBox.X, CollisionBox.Y);
        }

        public ClxMouse(Texture2D _texture)
            : base(_texture)
        {
            _curmouse = Mouse.GetState();
            _lastmouse = _curmouse;
            CollisionBox = new Rectangle(ClxG.Screen.Center.X, ClxG.Screen.Center.Y, Texture.Width, Texture.Height);
            DefaultPosition = new Vector2(CollisionBox.X, CollisionBox.Y);
        }

        public override void Update()
        {
            _lastmouse = _curmouse;
            _curmouse = Mouse.GetState();
            if (_curmouse != _lastmouse)
            {
                if (ClxG.Game.IsActive)
                {
                    _scrollwheel = _curmouse.ScrollWheelValue;
                    Velocity = new Vector2(Change.X / Sensitivity, Change.Y / Sensitivity);
                    if (Lock)
                        Mouse.SetPosition(ClxG.Screen.Center.X, ClxG.Screen.Center.Y);
                    _curmouse = Mouse.GetState();
                }

                base.Update();
            }
        }

        public override void Draw(SpriteBatch _sb)
        {
            base.Draw(_sb);
        }
    }
}

ClxButton

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace org.clixel
{
    public class ClxButton : ClxSprite
    {
        /// <summary>
        /// The color when the mouse is over the button
        /// </summary>
        public Color HoverColor;

        /// <summary>
        /// The color when the color is being clicked
        /// </summary>
        public Color ClickColor;

        /// <summary>
        /// The color when the button is inactive
        /// </summary>
        public Color InactiveColor;

        /// <summary>
        /// The color when the button is active
        /// </summary>
        public Color ActiveColor;

        /// <summary>
        /// The color after the button has been clicked.
        /// </summary>
        public Color ClickedColor;

        /// <summary>
        /// The text to be displayed on the button, set to "" if no text is needed.
        /// </summary>
        public string Text;

        /// <summary>
        /// The ClxText object to be displayed.
        /// </summary>
        public ClxText TextRender;

        /// <summary>
        /// The ClxState that should be ResetAndShow() when the button is clicked.
        /// </summary>
        public ClxState ClickState;

        /// <summary>
        /// Collision check to make sure onCollide() only runs once per frame,
        /// since only the mouse needs to be collision checked.
        /// </summary>
        private bool _runonce = false;

        /// <summary>
        /// Gets a value indicating whether this instance is colliding.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is colliding; otherwise, <c>false</c>.
        /// </value>
        public bool IsColliding
        {
            get
            {
                return _runonce;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ClxButton"/> class.
        /// </summary>
        public ClxButton()
            : base(ClxG.Textures.Default.Button)
        {
            HoverColor = Color.Red;
            ClickColor = Color.Blue;
            InactiveColor = Color.Gray;
            ActiveColor = Color.White;
            ClickedColor = Color.Yellow;

            Text = Name + ID + " Unset!";
            TextRender = new ClxText();
            TextRender.Text = Text;
            TextRender.TextPadding = new Vector2(5, 5);

            ClickState = null;
            CollideObjects(ClxG.Mouse);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ClxButton"/> class.
        /// </summary>
        /// <param name="_texture">The button texture.</param>
        public ClxButton(Texture2D _texture)
            : base(_texture)
        {
            HoverColor = Color.Red;
            ClickColor = Color.Blue;
            InactiveColor = Color.Gray;
            ActiveColor = Color.White;
            ClickedColor = Color.Yellow;
            Texture = _texture;

            Text = Name + ID;
            TextRender = new ClxText();
            TextRender.Name = this.Name + ".TextRender";
            TextRender.Text = Text;
            TextRender.TextPadding = new Vector2(5, 5);
            TextRender.Reset();

            ClickState = null;

            CollideObjects(ClxG.Mouse);
        }

        /// <summary>
        /// Draws the debug information, run from ClxG.DrawDebug unless manual control is assumed.
        /// </summary>
        /// <param name="_sb">SpriteBatch used for drawing.</param>
        public override void DrawDebug(SpriteBatch _sb)
        {
            _runonce = false;
            TextRender.DrawDebug(_sb);
            _sb.Draw(Texture, ActualRectangle, new Rectangle(0, 0, Texture.Width, Texture.Height), DebugColor, Rotation, Origin, Flip, Layer);
            _sb.Draw(ClxG.Textures.Default.DebugBG, new Rectangle(ActualRectangle.X - DebugLineWidth, ActualRectangle.Y - DebugLineWidth, ActualRectangle.Width + DebugLineWidth * 2, ActualRectangle.Height + DebugLineWidth * 2), new Rectangle(0, 0, ClxG.Textures.Default.DebugBG.Width, ClxG.Textures.Default.DebugBG.Height), DebugOutline, Rotation, Origin, Flip, Layer - 0.1f);
            _sb.Draw(ClxG.Textures.Default.DebugBG, ActualRectangle, new Rectangle(0, 0, ClxG.Textures.Default.DebugBG.Width, ClxG.Textures.Default.DebugBG.Height), DebugBGColor, Rotation, Origin, Flip, Layer - 0.01f);
        }

        /// <summary>
        /// Draws using the SpriteBatch, run from ClxG.Draw unless manual control is assumed.
        /// </summary>
        /// <param name="_sb">SpriteBatch used for drawing.</param>
        public override void Draw(SpriteBatch _sb)
        {
            _runonce = false;
            TextRender.Draw(_sb);
            if (Visible)
                if (Debug)
                {
                    DrawDebug(_sb);
                }
                else
                    _sb.Draw(Texture, ActualRectangle, new Rectangle(0, 0, Texture.Width, Texture.Height), Color, Rotation, Origin, Flip, Layer);
        }

        /// <summary>
        /// Updates this instance.
        /// </summary>
        public override void Update()
        {
            if (this.Color != ActiveColor)
                this.Color = ActiveColor;

            TextRender.Layer = this.Layer + 0.03f;
            TextRender.Text = Text;
            TextRender.Scale = .5f;
            TextRender.Name = this.Name + ".TextRender";
            TextRender.Origin = new Vector2(TextRender.CollisionBox.Center.X, TextRender.CollisionBox.Center.Y);
            TextRender.Center(this);

            TextRender.Update();

            this.CollisionBox.Width = (int)(TextRender.CollisionBox.Width * TextRender.Scale) + (int)(TextRender.TextPadding.X * 2);
            this.CollisionBox.Height = (int)(TextRender.CollisionBox.Height * TextRender.Scale) + (int)(TextRender.TextPadding.Y * 2);
            base.Update();
        }

        /// <summary>
        /// Collide event, takes the colliding object to call it's proper collision code.
        /// You'd want to use something like if(typeof(collider) == typeof(ClxObject)
        /// </summary>
        /// <param name="collider">The colliding object.</param>
        public override void onCollide(ClxObject collider)
        {
            if (!_runonce)
            {
                _runonce = true;
                UpdateEvents();
                base.onCollide(collider);
            }
        }

        /// <summary>
        /// Updates the mouse based events.
        /// </summary>
        public void UpdateEvents()
        {
            onHover();

            if (ClxG.Mouse.LeftReleased)
            {
                onLeftReleased();
                return;
            }

            if (ClxG.Mouse.RightReleased)
            {
                onRightReleased();
                return;
            }

            if (ClxG.Mouse.MiddleReleased)
            {
                onMiddleReleased();
                return;
            }

            if (ClxG.Mouse.LeftPressed)
            {
                onLeftClicked();
                return;
            }

            if (ClxG.Mouse.RightPressed)
            {
                onRightClicked();
                return;
            }

            if (ClxG.Mouse.MiddlePressed)
            {
                onMiddleClicked();
                return;
            }

            if (ClxG.Mouse.LeftDown)
            {
                onLeftClick();
                return;
            }

            if (ClxG.Mouse.RightDown)
            {
                onRightClick();
                return;
            }

            if (ClxG.Mouse.MiddleDown)
            {
                onMiddleClick();
                return;
            }
        }

        /// <summary>
        /// Shows the state of the click.
        /// </summary>
        public void ShowClickState()
        {
            if (ClickState != null)
            {
                ClickState.ResetAndShow();
            }
        }

        /// <summary>
        /// Hover event
        /// </summary>
        virtual public void onHover()
        {
            this.Color = HoverColor;
        }

        /// <summary>
        /// Left click event
        /// </summary>
        virtual public void onLeftClick()
        {
            this.Color = ClickColor;
        }

        /// <summary>
        /// Right click event
        /// </summary>
        virtual public void onRightClick()
        {
        }

        /// <summary>
        /// Middle click event
        /// </summary>
        virtual public void onMiddleClick()
        {
        }

        /// <summary>
        /// Left click event, called once per click
        /// </summary>
        virtual public void onLeftClicked()
        {
            ShowClickState();
        }

        /// <summary>
        /// Right click event, called once per click
        /// </summary>
        virtual public void onRightClicked()
        {
            this.Reset();
        }

        /// <summary>
        /// Middle click event, called once per click
        /// </summary>
        virtual public void onMiddleClicked()
        {
        }

        /// <summary>
        /// Ons the left released.
        /// </summary>
        virtual public void onLeftReleased()
        {
            this.Color = ClickedColor;
        }

        virtual public void onRightReleased()
        {
        }

        virtual public void onMiddleReleased()
        {
        }
    }
}

The issue I have is that I have all these have event styled methods, especially in ClxButton with all the onLeftClick, onRightClick, etc, etc.

Is there a better way for me to handle these events to be a lot more easier for a programmer to use? I was looking at normal events on some other sites, (I'd post them but I need more rep.) and didn't really see a good way to implement delegate events into my framework. I'm not really sure how these events work, could someone possibly lay out how these events are processed for me?

TL:DR * Is there a better way to handle events like this? * Are events a viable solution to this problem?

Thanks in advance for any help.

© Game Development or respective owner

Related posts about XNA

Related posts about c#