Движение мыши: нажмите спрайт "ходит", чтобы точка щелкнула - PullRequest
4 голосов
/ 17 февраля 2011

Я довольно новичок в C # и XNA и хорошо программирую (как будто я могу следовать учебному пособию, но большая часть его создания все еще действительно очень трудна). Прямо сейчас я собираюсь по кругу, пытаясь понять, как сделать эту одну "простую" вещь.

Вот идея, это будет игра в защиту башни; сейчас я работаю над основами голой кости. У меня есть мой маленький спрайт, который будет перемещаться с помощью ввода с клавиатуры, теперь я хочу щелкнуть где-нибудь на экране и заставить его «пройтись» до этой точки. Только я заблудился от логики. Я могу нажать, и он прыгнет туда с

if (aMouse.LeftButton == ButtonState.Pressed)
{
  Position.X = aMouse.X;
  Position.Y = aMouse.Y;
} 

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

Ответы [ 4 ]

2 голосов
/ 17 февраля 2011

Люди отвечают на ваш вопрос на очень низком уровне.Иногда это помогает думать о проблеме на более высоком уровне.

Что вам нужно, это тип управления состоянием.Причудливый термин Computer Science для этого - конечный автомат.Но не надо сейчас искать это.Сначала это довольно сухо и запутанно:)

У вашего персонажа в данный момент есть одно состояние - «стоять вокруг».Вам нужно добавить и обработать состояние «ходьбы до места назначения».

Из того, что я прочитал для других вводов мышью, я думаю, что мне понадобится какой-то цикл

Вам нужен один цикл, называемый игровым циклом.Если вы используете XNA, у вас уже есть один.Но вы на правильном пути.

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

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

Когда ваш персонаж находится в состоянии «прогулки по назначению», вам необходимо обновить его положение, исходя из количества времени, прошедшего с момента последнего обновления игры,В XNA это рассчитывается для вас.Если вы не используете XNA, вам придется проверить себя.Возможно, вы сможете использовать что-то вроде класса Stopwatch и проверить поле Elapsed.

Если персонаж находится в пункте назначения, вам необходимо переключить его обратно в состояние «стояния».

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

Итак, вам понадобятся следующие переменные:

  • Таймер, чтобы узнать, сколько времени прошло с момента последнего игрового цикла (XNA дает его вам)
  • Текущее состояние игрока (может быть enum)
  • Текущая позиция игрока(вектор)
  • Скорость ходьбы игрока (возможно, с плавающей точкой), измеряется в единицах в секунду (или миллисекундах)
  • Данные для состояния «ходьба к месту назначения» - целевая позиция(другой вектор)
  • Данные, относящиеся к пользовательскому вводу (события мыши, произошедшие с момента последнего обновления, положение этих щелчков и т. д.)

Данные, характерные для персонажа, будут другими длякаждый персонаж в вашей игре, поэтому вы хотите новую копию для каждого.Вы, вероятно, захотите поместить это в класс.Все остальное носит более глобальный характер, поэтому вы можете оставить его отдельно или сделать его частью своей игры, игрового цикла, классов ввода и т. Д. (Как бы вы ни решили организовать это).

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

2 голосов
/ 17 февраля 2011

Вам нужно добавить несколько переменных экземпляра:

Point2D targetPos;

И некоторые константы:

const Point2D speed;

Когда вы выполняете цикл Update (), обновляйте текущую позицию, добавляя к ней вектор скорости (в правильном направлении курса), пока вы не окажетесь в заданном пороге от целевой позиции (обычно пороги рассчитываются из вектор скорости - если расстояние от текущей позиции до целевой позиции меньше длины вектора скорости, значит, вы находитесь на своей позиции). Использование bool в этом случае будет хорошо работать. Когда вы щелкаете мышью, установите для другой переменной экземпляра (перемещение) значение true, а после достижения целевого положения установите для перемещения значение false.

1 голос
/ 17 февраля 2011

Я предполагаю, что у вас есть три вещи:

  1. Текущая позиция
  2. Желаемая позиция
  3. Скорость перемещения каждой «игровой галочки» // незнаете, что такое игровой тик?узнай!

Ты собираешься это сделать

enter image description here

// dx, dy are delta x and delta y. It's how far in each direction
// the player must travel
// note, I fixed a typo where they were desired - desired... should be
// desired - current, as they are now
float dx = desiredX - currentX;
float dy = desiredY - currentY;

// d uses the pythagorean theorum to find the distance between current and desired
float d = sqrt(dx*dx + dy*dy);
// fac is how far along that line between desired and current will you move
float fac = d / speed;

// mx is the component of the dx line proportional to the size of fac : d
// which means it's how far in the x direction you'll move
float mx = dx * fac;
float my = dy * fac;

// the new postition is the old position plus the move value
float newPositionX = dx + mx;
float newPositionY = dy + my;
0 голосов
/ 18 декабря 2013

Я считаю этот код наиболее полезным ... кроме того, я добавил дополнительную пару строк, чтобы предотвратить возникновение определенных ситуаций.Например, будут моменты, когда направление равно 0,83, а скорость может быть изменена такими игровыми факторами, как ландшафт / погода / т.д. ... если скорость ниже 1, спрайт может вообще не двигаться или даже двигаться в неправильном направлении!

 if (Vector2.Distance(Position, TargetPosition) > 2.0f)
 {
    velocity = Vector2.Subtract(TargetPosition, Position);
    velocity.Normalize();
    /// Now no matter which direction we are going we are always moving @ sprite.Speed
    /// at velocity or speed below 1 - problems occur where the unit may not move at all!!
    if(current_Speed < 1)
    {
       Vector2 temp = (velocity * 10) * (current_Speed * 10);
       Position += temp / 10;
    }
    else
    { 
       Vector2 temp = velocity * current_Speed;
       Position += temp;
    }
    //convert to int to render sprite to pixel perfect..
    Position = new Vector2((int)Position.X, (int)Position.Y);
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...