2012-03-19 2 views
0

Код, который я использую для управления четырехсторонним движением спрайта игрока в моей 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), в то время как мой спрайт стоит на месте. Любые советы о том, как остановить это?

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

ответ

1

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

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

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 в том же фрейме.

+0

Использование вашего кода и изменение второго, третьего и четвертого, если в противном случае, если ближе к тому, что я хочу. Он хорошо работает, когда я держусь влево или вправо, а затем нажимаю вверх или вниз, но влево и вправо не реагирует, когда я уже держусь вверх или вниз.Кроме того, пока я держу левый, а затем нажимаю вправо, персонаж останавливается, а не сразу начинает двигаться вправо, поэтому я не совсем понимаю точность, которую я ищу, если персонаж останавливается, если удерживаются два противоположных направления. – Dzyu

+0

Если вы ищете такую ​​точность, тогда вам придется бросить немного больше состояния. Например, если вы хотите нажимать вправо, сразу же двигайтесь вправо, аннулируя оставшееся нажатие левой кнопки, тогда вам нужно начать отслеживать нажатия клавиш/нажатия клавиш. В этом случае вам нужно будет использовать обработчик нажатия клавиш для L & R, задав «movingLeft» или аналогичный bool, а затем установите значение false при нажатии противоположного направления, а затем сохраните его false до тех пор, пока L не будет выпущен и т. Д. и т. д. –

+0

Я считаю, что это отлично работает для противоположных направлений, но как бы я справился с этим для левого и правого движения, двигаясь вверх или вниз, и наоборот? Я тоже попробовал свое собственное новое решение. Добавлено его как редактирование. Единственная проблема, которая, по-видимому, состоит в том, что она генерирует исключения в каждом кадре, где спрайт стоит на месте. Я не совсем понимаю, почему это происходит, поэтому любые отзывы о моем коде очень ценятся! :) – Dzyu

Смежные вопросы