protected virtual void OnPlayerMoveAttempt(PlayerMoveAttemptEventArgs e) => PlayerMoveAttempt(this, e);
        public void Update(GameTime gameTime)
        {
            var keys = Keyboard.GetState();

            if (gameTime.TotalGameTime - _lastMovementTime >= _movementCooldown)
            {
                var(dx, dy) = (0, 0);

                // check for movement input
                if (keys.IsKeyDown(Keys.NumPad8) || keys.IsKeyDown(Keys.W))
                {
                    dy -= 1;
                }
                else if (keys.IsKeyDown(Keys.NumPad2) || keys.IsKeyDown(Keys.S))
                {
                    dy += 1;
                }
                else if (keys.IsKeyDown(Keys.NumPad4) || keys.IsKeyDown(Keys.A))
                {
                    dx -= 1;
                }
                else if (keys.IsKeyDown(Keys.NumPad6) || keys.IsKeyDown(Keys.D))
                {
                    dx += 1;
                }
                else if (keys.IsKeyDown(Keys.NumPad7))
                {
                    dx -= 1;
                    dy -= 1;
                }
                else if (keys.IsKeyDown(Keys.NumPad9))
                {
                    dx += 1;
                    dy -= 1;
                }
                else if (keys.IsKeyDown(Keys.NumPad1))
                {
                    dx -= 1;
                    dy += 1;
                }
                else if (keys.IsKeyDown(Keys.NumPad3))
                {
                    dx += 1;
                    dy += 1;
                }

                if (dx != 0 || dy != 0)
                {
                    var destination     = new Point(Position.X + dx, Position.Y + dy);
                    var moveAttemptArgs = new PlayerMoveAttemptEventArgs(destination);
                    if (PlayerMoveAttempt != null)
                    {
                        OnPlayerMoveAttempt(moveAttemptArgs);
                    }
                    if (!moveAttemptArgs.Cancel)
                    {
                        Position = destination;
                        if (PlayerMoved != null)
                        {
                            OnPlayerMoved(EventArgs.Empty);
                        }
                        _lastMovementTime = gameTime.TotalGameTime;
                    }
                }
            }
        }