Оптимизированное управление клавиатурой для игры XNA - PullRequest
0 голосов
/ 20 марта 2012

Код, который я использую для управления четырехнаправленным движением спрайта игрока в моей 2D-игре, демонстрирует некоторую нежелательную привязанность. Я понимаю, что эта привязанность вызвана тем, что условия if, которые будут выполнены в первую очередь, превзойдут последующие ifs ... Таким образом, привязанность направления, которую показывает мой код сейчас: left> right> up> down.

Какая привязанность мне нужна: первое нажатое направление> второе нажатое направление> третье нажатое направление> четвертое нажатое направление.

Я также хочу, чтобы он запомнил, в каком порядке нажатия клавиш, пока они не отпущены.

Пример: Я держу влево, спрайт движется влево. Я толкаю вверх, все еще удерживая влево, и спрайт немедленно движется вверх. Я отпускаю вверх, все еще удерживая левую, и спрайт возобновляет свое движение влево.

Эта память должна охватывать все четыре клавиши со стрелками, чтобы элементы управления не выглядели глючными, если у пользователя "толстые пальцы".

Это код, который я использую для движения:

            if (CurrentKeyboardState.IsKeyDown(Keys.Left) == true)
            {
                Speed.X = moveSpeed;
                Direction.X = moveLeft;
            }
            else if (CurrentKeyboardState.IsKeyDown(Keys.Right) == true)
            {
                Speed.X = moveSpeed;
                Direction.X = moveRight;
            }
            else if (CurrentKeyboardState.IsKeyDown(Keys.Up) == true)
            {
                Speed.Y = moveSpeed;
                Direction.Y = moveUp;
            }
            else if (CurrentKeyboardState.IsKeyDown(Keys.Down) == true)
            {
                Speed.Y = moveSpeed;
                Direction.Y = moveDown;
            }

Я думаю, что мог бы использовать Список и просто указать направление нажатия (влево, вправо, вверх, вниз) как строки в списке, если его еще нет в списке, а затем всегда проверять, какой последний элемент в список должен решить, какое направление переместить. И, конечно, удалить строки, когда соответствующие ключи отпущены. Будет ли это хорошим способом ее решения?

Вот моя попытка:

            if (currentKeyboardState.IsKeyDown(Keys.Left))
            {
                if (!keyDownList.Contains("left"))
                {
                    keyDownList.Add("left");
                    System.Diagnostics.Debug.WriteLine("left inserted");
                }
            }
            else if (oldKeyboardState.IsKeyDown(Keys.Left))
            {
                keyDownList.Remove("left");
                System.Diagnostics.Debug.WriteLine("left removed");
            }



            if (currentKeyboardState.IsKeyDown(Keys.Right))
            {
                if (!keyDownList.Contains("right"))
                {
                    keyDownList.Add("right");
                    System.Diagnostics.Debug.WriteLine("right added");
                }
            }
            else if (oldKeyboardState.IsKeyDown(Keys.Right))
            {
                keyDownList.Remove("right");
                System.Diagnostics.Debug.WriteLine("right removed");
            }



            if (currentKeyboardState.IsKeyDown(Keys.Up))
            {
                if (!keyDownList.Contains("up"))
                {
                    keyDownList.Add("up");
                    System.Diagnostics.Debug.WriteLine("up added");
                }
            }
            else if (oldKeyboardState.IsKeyDown(Keys.Up))
            {
                keyDownList.Remove("up");
                System.Diagnostics.Debug.WriteLine("up removed");
            }



            if (currentKeyboardState.IsKeyDown(Keys.Down))
            {
                if (!keyDownList.Contains("down"))
                {
                    keyDownList.Add("down");
                    System.Diagnostics.Debug.WriteLine("down added");
                }
            }
            else if (oldKeyboardState.IsKeyDown(Keys.Down))
            {
                keyDownList.Remove("down");
                System.Diagnostics.Debug.WriteLine("down removed");
            }


            try
            {
                if (keyDownList[keyDownList.Count-1].Contains("left"))
                {
                    //move left
                    speed.X = moveSpeed;
                    direction.X = moveLeft;
                }
                else if (keyDownList[keyDownList.Count-1].Contains("right"))
                {
                    //move right
                    speed.X = moveSpeed;
                    direction.X = moveRight;
                }
                else if (keyDownList[keyDownList.Count-1].Contains("up"))
                {
                    //move up
                    speed.Y = moveSpeed;
                    direction.Y = moveUp;
                }
                else if (keyDownList[keyDownList.Count-1].Contains("down"))
                {
                    //move down
                    speed.Y = moveSpeed;
                    direction.Y = moveDown;
                }
            }
            catch (Exception e)
            {
            }

Первоначально у меня были некоторые проблемы с ним, но теперь он, кажется, работает нормально, за исключением того, что он генерирует исключения (первое случайное исключение типа «System.ArgumentOutOfRangeException» произошло в mscorlib.dll), пока мой спрайт стоит на месте. Любые советы о том, как это остановить?

Я не просто ищу решение, которое работает, но что-то долговечное и эффективное, которое кажется прочным и профессиональным, поэтому обсуждение этой темы приветствуется.

1 Ответ

1 голос
/ 20 марта 2012

Надежный, эффективный, надежный и т. Д. Это может быть не так, но то, что вы говорите с вашим блоком if / else if, заключается в том, что вас интересует только одно состояние ключа на кадр, когда я надеваюНе думаю, что это так.

Что произойдет, если вы попробуете:

if (CurrentKeyboardState.IsKeyDown(Keys.Down) & !CurrentKeyboardState.IsKeyDown(Keys.Up))
{
    Speed.Y = moveSpeed;
    Direction.Y = moveDown;
}
if (CurrentKeyboardState.IsKeyDown(Keys.Up) & !CurrentKeyboardState.IsKeyDown(Keys.Down))
{
    Speed.Y = moveSpeed;
    Direction.Y = moveUp;
}

И повторите аналогичные для левой и правой.Испытывая взаимную исключительность между противоположными направлениями, вы удерживаете себя от сложения и вычитания направления в одном кадре.Кроме того, используя отдельные условия вместо цепочки if / elseif, вы разрешаете обрабатывать Left + Up в одном кадре.

...