Код, который я использую для управления четырехсторонним движением спрайта игрока в моей 2D-игре, проявляет некоторую нежелательную привязанность. Я понимаю, что эта привязанность обусловлена тем, что условия if, которые впервые встречаются, будут превзойти более поздние if if ... Итак, направленная привязанность, которую показывает мой код: left> right> up> down.Оптимизированные элементы управления клавиатурой для игры XNA
Какая привязанность я хочу: нажатие первого направления> нажатие второго направления> нажатие третьего направления> нажатие четвертого направления.
Я также хочу, чтобы он помнил, в каком порядке нажаты клавиши, пока они не выпущены.
Пример: Я держусь влево, спрайт перемещается влево. Я отжимаю, продолжая удерживать влево, и спрайт немедленно движется вверх. Я освобождаюсь, удерживая влево, и спрайт возобновляет движение влево.
Эта память должна охватывать все четыре направленные клавиши, чтобы элементы управления не чувствовали себя плохо, если пользователь имеет «толстые пальцы».
Это код, который я использую для движения до сих пор:
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;
}
Я имею в виду, я мог бы использовать список и просто положить направление нажатой (влево, вправо, вверх, вниз) в виде строки в списке если он еще не включен в список, а затем всегда проверяйте, какой последний элемент в списке должен решить, для какого directio двигаться. И, конечно, удалите строки, когда соответствующие клавиши будут выпущены. Будет ли это хорошим способом его решения?
Вот моя попытка на этом:
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), в то время как мой спрайт стоит на месте. Любые советы о том, как остановить это?
Я не просто ищу решение, которое работает, но и для чего-то долговечного и эффективного, которое чувствует себя солидно и профессионально, поэтому обсуждение темы более чем приветствуется.
Использование вашего кода и изменение второго, третьего и четвертого, если в противном случае, если ближе к тому, что я хочу. Он хорошо работает, когда я держусь влево или вправо, а затем нажимаю вверх или вниз, но влево и вправо не реагирует, когда я уже держусь вверх или вниз.Кроме того, пока я держу левый, а затем нажимаю вправо, персонаж останавливается, а не сразу начинает двигаться вправо, поэтому я не совсем понимаю точность, которую я ищу, если персонаж останавливается, если удерживаются два противоположных направления. – Dzyu
Если вы ищете такую точность, тогда вам придется бросить немного больше состояния. Например, если вы хотите нажимать вправо, сразу же двигайтесь вправо, аннулируя оставшееся нажатие левой кнопки, тогда вам нужно начать отслеживать нажатия клавиш/нажатия клавиш. В этом случае вам нужно будет использовать обработчик нажатия клавиш для L & R, задав «movingLeft» или аналогичный bool, а затем установите значение false при нажатии противоположного направления, а затем сохраните его false до тех пор, пока L не будет выпущен и т. Д. и т. д. –
Я считаю, что это отлично работает для противоположных направлений, но как бы я справился с этим для левого и правого движения, двигаясь вверх или вниз, и наоборот? Я тоже попробовал свое собственное новое решение. Добавлено его как редактирование. Единственная проблема, которая, по-видимому, состоит в том, что она генерирует исключения в каждом кадре, где спрайт стоит на месте. Я не совсем понимаю, почему это происходит, поэтому любые отзывы о моем коде очень ценятся! :) – Dzyu