Если условное исполнение - PullRequest
0 голосов
/ 22 ноября 2010

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

Вот код -

if (mouseState.LeftButton == ButtonState.Pressed)
{
     if (mouseState.LeftButton == ButtonState.Released)
     {
          //move sprite to clicked position
          spritePos.X = mouseState.X;
          spritePos.Y = mouseState.Y;
     }
}

У меня есть пара вопросов.Меня учили, что условный аргумент проверяется только один раз, если он оценивается как true, тогда выполняются следующие операторы. Это правда или действительно проверяется перед выполнением каждого оператора в блоке?- поскольку последнее, очевидно, вызовет конфликт с моим вложенным, если.

Если это правда, то почему мой метод нажатия кнопки не работает?Спрайт никогда не двигается, как будто отпускание мыши никогда не выполняется. Это потому, что задержка между проверкой обоих условий настолько мала, что я не могу физически отпустить кнопку за это время?Могу ли я быть немного хакером по этому поводу и преодолеть его с задержкой , которая может быть достаточно большой, чтобы позволить отпускание кнопки мыши к моменту проверки вложенного условного выражения?

Методы длядействия щелчка мышью, которые я видел, использовать свойства мыши из предыдущего кадра и сравнить с новым кадром, чтобы проверить наличие щелчка мыши.Но этот метод должен ввести задержку, по крайней мере, на один кадр, чтобы фактически обработать действие.Это может быть незаметно при высокой частоте смены кадров, но ради аргумента скажем, у меня была игра, рендерившая 20 кадров в секунду.UpdateInput () будет вызываться перед рендерингом любого кадра, позиции должны обновляться, а затем фрейм должен отображаться последним.

Если операция полного щелчка мышью может сработать менее чем за 1/20 секунды, не так липредпочтительнее обрабатывать действие сразу, а не сохранять переменную при первом нажатии и сравнивать состояния в следующем кадре?Это, безусловно, было бы лучше, чем вводить дополнительную задержку при вводе.

Я уверен, что это, должно быть, уже рассматривалось другими ранее, и, возможно, я не думаю правильно о операции задержки, фактически приостанавливающей выполнениекод. Могут ли временные задержки приостановить выполнение процессором кода или только результат этих выполнений, таких как рендеринг и прием ввода?Они не являются чем-то, что я имею опыт использования, и я, возможно, путаю, как будет работать задержка.

Спасибо, Андрей.

Ответы [ 3 ]

2 голосов
/ 23 ноября 2010

О, здесь так много неправильного ...

То, что вы, вероятно, делаете до того, как ваш блок if выражений:

MouseState mouseState = Mouse.GetState();

Теперь функция GetStateчто фактически определяет текущее состояние мыши и упаковывает его в структуру MouseState= вы присваиваете это состояние переменной mouseState.

Единственный раз, когда mouseState изменится, это когда вы измените его самостоятельно!Итак, ваше условие выглядит следующим образом:

if (mouseState.LeftButton == ButtonState.Pressed) {
    if (mouseState.LeftButton == ButtonState.Released) { /* "do stuff" */ }
}

Вы проверяете, равняется ли mouseState.LeftButton, который не меняется, двум совершенно разным вещам!Очевидно, что «делать вещи» никогда не будет.

Теперь другую часть проблемы, которую я могу проиллюстрировать, заставляя код работать так, как вы, кажется, думаете, он должен работать:

if (Mouse.GetState().LeftButton == ButtonState.Pressed) {
    // Some kind of delay, perhaps?
    if (Mouse.GetState().LeftButton == ButtonState.Released) { /* "do stuff" */ }
}

Таким образом, состояние обновляется каждый раз, когда вы проверяете его.

Теперь вот проблема с этим кодом.Ваша мышь должна перейти из состояния «нажата» в состояние «отпущено» между двумя операторами if .Если этого не произойдет, условие не сработает.

Увеличение длительности задержки не исправит ее по многим причинам: во-первых, это отнимает время от фактического запуска вашей игры.Во-вторых, невозможно увеличить его до 100% времени кадра - поэтому всегда будет процентная вероятность того, что ваше условие не сработает.

Поэтому лучший способ обработки ввода - отслеживать состояниесостояние между кадрами .И лучший способ сделать это, как и во всех учебных руководствах, хранить MouseState lastMouseState; между вызовами вашей Update функции.Таким образом, ваш код должен выглядеть примерно так:

MouseState mouseState = Mouse.GetState();
if (lastMouseState.LeftButton == ButtonState.Pressed)
{
    if (mouseState.LeftButton == ButtonState.Released)
    {
        /* "do stuff" */
    }
}
lastMouseState = mouseState;

Теперь, вы можете сказать, что это все еще оставляет вас с реальной проблемой, которую вы упомянули в первую очередь: что, если использование щелкает так быстро, чтосостояние мыши меняется, а затем переключается обратно между вызовами на GetState?

Что ж, мой первый ответ на это - «не беспокойся об этом». - известная проблема с платформой ввода XNA.Но на практике вы обнаружите, что люди обычно не нажимают или не набирают текст так быстро, что это вызывает фактических проблем при 60FPS.

Если ваша игра работает со скоростью значительно меньшей 60FPS, вы все равно можете запуститьваши обновления на 60FPS.Чтобы уменьшить свою ничью, вы можете использовать Game.SupressDraw или заставить Game.BeginDraw вернуть false (см. здесь и здесь ).Если вам также нужно запускать обновления со скоростью менее 60FPS, вы все равно можете обновить ввод со скоростью 60FPS (или быстрее!), Но это намного больше работы.(Обратите внимание, что ввод XNA должен выполняться в главном потоке .)

(Лично я бы посоветовал вам просто работать со скоростью 60FPS и перестать беспокоиться об этом!)

И, наконец, если вам этого недостаточно, вы можете связываться с interop, подключать насос сообщений и ловить сообщения WM_LBUTTONUP.Это огромное излишество, но это «правильный» способ получить то, что вы хотите.

1 голос
/ 23 ноября 2010

Андрей, ваша проблема не имеет ничего общего с тем, как работают заявления.mouseState представляет состояние мыши, когда был вызван GetState ().Он не изменится только потому, что мышь меняет свое состояние.Чтобы ваш фрагмент кода работал так, как вы ожидаете, вы должны вызывать GetState () перед каждым оператором if.Состояние мыши изменяется только при опросе или ручной настройке.

0 голосов
/ 22 ноября 2010

это не работает, потому что если вы нажмете левую кнопку, то у вас не будет возможности отпустить ее, пока программа не проверит условие if (mouseState.LeftButton == ButtonState.Released).

Может ли время задержать выполнение процессором кода паузы

Задержка ввода мышью и клавиатурой незаметна.

Я бы использовал переменную для сохранения состояния левой кнопки каждого кадра:

while (1) // ininity loop
{
    if (mouseState.LeftButton == ButtonState.Pressed)
    {
         button_left_pressed = 1; // is pressed
    }
    else // Left Button is not pressed
    {
         if ( button_left_pressed ) // but was pressed (is released)
         {
             spritePos.X = mouseState.X;
             spritePos.Y = mouseState.Y;
             button_left_pressed = 0; // is not pressed
         }
    }
    // do another action        
}
...