Пятница, 19 Апреля 2024, 03:38

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Форум игроделов » Программирование » C/C++ » Плавное движение в сторону точки B из точки A
Плавное движение в сторону точки B из точки A
SlayezДата: Воскресенье, 09 Августа 2015, 15:02 | Сообщение # 1
частый гость
Сейчас нет на сайте
Народ нужно сделать функцию которая будет возвращать направление движения точки A в точку B,
в формате (x;y) причём x и y должны быть от 0 до 1 включительно, что бы применить "Модификатор скорости" (умножить на число).
Эта формула нужна для плавного движения в сторону точки B из точки A.
C#
Код
public struct myVector
          {
              public float x, y;
          }

          public myVector GetMoveDirection(float x, float y, float needX, float needY)
          {
              // Slayez script
              myVector my;
              my.x = 0;
              my.y = 0;
              float Fx = needX - x, Fy = needY - y;

              if ((Fx == 0) & (Fy == 0))    // if need position  ==  now position send vector (0;0)
                  return my;
              else
                  if (Math.Abs(Fx) == Math.Abs(Fy))
                  {
                      my.y = 0.5f;
                      my.x = 0.5f;
                      if (Fy < 0)
                          my.y *= -1;
                      if (Fx < 0)
                          my.x *= -1;
                      return my;
                  }
                  else
                      if ((Fx == 0) & (Fy != 0))
                      {
                          my.x = 0;
                          if (Fy > 0)
                    my.y = 1;
                          else
                    my.y = -1;
                          return my;
                      }
                      else
                          if ((Fy == 0) & (Fx != 0))
                          {
                    my.y = 0;
                    if (Fx > 0)
                     my.x = 1;
                    else
                     my.x = -1;
                    return my;
                          }
                          else

                    if (Math.Abs(Fx) > Math.Abs(Fy)+roundDir)    // main function logic
                    {
                     my.y = Math.Abs(Fy) / Math.Abs(Fx);
                     my.x = 1 - (Math.Abs(Fy) / Math.Abs(Fx));
                     if (Fy < 0)
                     my.y *= -1;
                     if (Fx < 0)
                     my.x *= -1;
                     return my;
                    }
                    else
                     if (Math.Abs(Fx)+roundDir < Math.Abs(Fy))  // main function logic
                     {
                     my.y = Math.Abs(Fx) / Math.Abs(Fy);
                     my.x = 1 - (Math.Abs(Fx) / Math.Abs(Fy));
                     if (Fy < 0)
                     my.y *= -1;
                     if (Fx < 0)
                     my.x *= -1;
                     return my;
                     }
                     else
                     if (Math.Abs(Fx) > Math.Abs(Fy))    // main function logic
                     {
                     my.y = Math.Abs(Fy) / Math.Abs(Fx);
                     my.x = 1 - (Math.Abs(Fy) / Math.Abs(Fx));
                     if (Fy < 0)
                     my.y *= -1;
                     if (Fx < 0)
                     my.x *= -1;
                     return my;
                     }
                     else
                     if (Math.Abs(Fx) < Math.Abs(Fy))  // main function logic
                     {
                     my.y = Math.Abs(Fx) / Math.Abs(Fy);
                     my.x = 1 - (Math.Abs(Fx) / Math.Abs(Fy));
                     if (Fy < 0)
                     my.y *= -1;
                     if (Fx < 0)
                     my.x *= -1;
                     return my;
                     }
                     else
                     return my; // This line never do
          }

Я проверял пошагово, он выдаёт странные значения при приближении к 0 разницы между x и y.


Сообщение отредактировал Slayez - Воскресенье, 09 Августа 2015, 15:03
GudleifrДата: Воскресенье, 09 Августа 2015, 18:05 | Сообщение # 2
почти ветеран
Сейчас нет на сайте
В последний раз нарушу правила этого форума. Напишу заведомую гадость. Зато - правду.

Вас может спасти только одно - нужно нанять программиста.
Впрочем, на данный форум таковые не заходят (или их всех повывели).

А, так, для баловства, можете посмотреть "нормирование вектора", где-то в учебнике класса, этак, 6-7-го (не уверен).
Только это не поможет, т.к. Вы видимо сами не понимаете, что и зачем делаете.

Все, пошел я отседова...


Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
XakepДата: Воскресенье, 09 Августа 2015, 19:18 | Сообщение # 3
めちゃくちゃちゃ
Сейчас нет на сайте
Ахаха блин, и еще кто-то говорит что программисту не нужна математика biggrin
По теме, чтобы узнать направление вектора, достаточно из точки Б вычесть точку А (x2-x1, y2-y1) и нормировать вектор (привести к единичному), для этого раздели значения на длину вектора.
Плавное движение можно на подобие такого сделать (На хаксе, но думаю перевести на шарп не составит труда):

Код

public static function interpTo (current : Float, target : Float, deltaTime : Float, interpSpeed : Float) {

   if (interpSpeed == 0)
    return target;

   var dist : Float = target - current;

   if (dist*dist < SMALL_NUMBER)
    return target;

   var deltaMove : Float = dist*deltaTime*interpSpeed;
   return current+deltaMove;
     
}

...

x = interpTo (x, x2, dtime, 10);
y = interpTo (y, y2, dtime, 10);


SMALL_NUMBER - пороговое значение, при котором current станет target, я ставлю 1 пиксель.


Сообщение отредактировал Xakep - Воскресенье, 09 Августа 2015, 19:18
SlayezДата: Воскресенье, 09 Августа 2015, 21:34 | Сообщение # 4
частый гость
Сейчас нет на сайте
Цитата Xakep ()
Плавное движение можно на подобие такого сделать

я не вижу в твоём коде x1 x2 y1 y2... и причём тут deltaTime я вообще не пойму...

Добавлено (09 августа 2015, 21:34)
---------------------------------------------

Цитата Gudleifr ()
В последний раз нарушу правила этого форума. Напишу заведомую гадость. Зато - правду.

Вас может спасти только одно - нужно нанять программиста.
Впрочем, на данный форум таковые не заходят (или их всех повывели).

А, так, для баловства, можете посмотреть "нормирование вектора", где-то в учебнике класса, этак, 6-7-го (не уверен).
Только это не поможет, т.к. Вы видимо сами не понимаете, что и зачем делаете.

Все, пошел я отседова...

На словах вы все Львы Толстые...
XakepДата: Воскресенье, 09 Августа 2015, 22:03 | Сообщение # 5
めちゃくちゃちゃ
Сейчас нет на сайте
Цитата Slayez ()
я не вижу в твоём коде x1 x2 y1 y2... и причём тут deltaTime я вообще не пойму...

про дельта тайм погугли, попробуй поставить просто маленькое значение очень, к примеру 0,001, функцию которую привел делает примерно то что я описал выше, кроме нормирование, потому-что оно тут в принципе не особо то и нужно, x1, y1 - x, y в коде в самом низу, InterpTo - плавно приводит текущее значение к целевому.

Добавлено (09 августа 2015, 21:59)
---------------------------------------------
если тебе именно направление нужно, то:

dir = (needX - x, needY - y)
norm = length (dir)
dir.x /= norm
dir.y /= norm

где length (v) = sqrt (v.x^2 + v.y^2)

Добавлено (09 августа 2015, 22:03)
---------------------------------------------
Думаю тебе будет полезно: Линейная алгебра для разработчиков игр (самое главное про векторы прочитай)


Сообщение отредактировал Xakep - Воскресенье, 09 Августа 2015, 22:10
SaiteiДата: Понедельник, 10 Августа 2015, 01:05 | Сообщение # 6
старожил
Сейчас нет на сайте
Gudleifr, выдаю устное предупреждение. В следующий раз уже будет бан.

Слишком много оффтопа, равно как и непрямых оскорблений. Скоро я не смогу на это закрывать глаза.
Пожалуйста, имейте это ввиду.
AlkoshaДата: Понедельник, 10 Августа 2015, 17:57 | Сообщение # 7
участник
Сейчас нет на сайте
Постойте-ка.
А это, случаем, не смежная тема?
http://gcup.ru/forum/7-41739-2

Просто интересно, как сделать равномерное перемещение именно так, чтоб объект без погрешности оказался в точке B.
XakepДата: Понедельник, 10 Августа 2015, 20:23 | Сообщение # 8
めちゃくちゃちゃ
Сейчас нет на сайте
Alkosha, что значит без погрешности? В смысле что координаты точки А будут точно равны координатам точки Б в какой-то определенный момент без погрености? если да то я выше написал полную реализацию даже, только на нужный язык программирования перенести нужно, а т.к. тут кроме математических операция ничего нету, то с этим проблем не должно возникнуть.

Функция интерполяции:
Код

public static function interpTo (current : Float, target : Float, deltaTime : Float, interpSpeed : Float) {

    if (interpSpeed == 0)
     return target;

    var dist : Float = target - current;

    if (dist*dist < SMALL_NUMBER)
     return target;

    var deltaMove : Float = dist*deltaTime*interpSpeed;
    return current+deltaMove;
       
}


компоненты x и y - плавно перемещаются и текущего положения в (x2, y2):
Код

x = interpTo (x, x2, dtime, 10);
y = interpTo (y, y2, dtime, 10);


Чтобы без погрешностей было, тут используется простое условие, если x примерно равна x2, то приравниваем ее в x2 и дальше ничего не вычисляем.
SlayezДата: Среда, 12 Августа 2015, 12:56 | Сообщение # 9
частый гость
Сейчас нет на сайте
Спасибо за решение проблемы
AlkoshaДата: Среда, 12 Августа 2015, 13:24 | Сообщение # 10
участник
Сейчас нет на сайте
Цитата Xakep ()
если да то я выше написал полную реализацию даже


Не уверен подойдёт ли она мне, так как у меня координаты изменяются без дельта-тайма.
Чтобы каждый раз не умножать на коэффициент дельты, я воспользовался предпоследней процедуркой из этой статьи.
http://habrahabr.ru/post/136878/
XakepДата: Среда, 12 Августа 2015, 13:47 | Сообщение # 11
めちゃくちゃちゃ
Сейчас нет на сайте
Цитата Alkosha ()
Не уверен подойдёт ли она мне, так как у меня координаты изменяются без дельта-тайма.

поставь deltatime равным примерно 0.001f может меньше, может больше, тут нужно смотреть на результат.
В данном примере скорость будет меняться не линейно, если нужно чтобы линейно достигал цели, то как-то так:
Код

vec2 move2Target (vec2 current, vec2 target, float speed) {

    vec2 dir (target.x - current.x, target.y - target.x);
    float length = sqrt (dir.x*dir.x + dir.y*dir.y);
    dir = vec2 (dir.x/length, dir.y/length); // Получили направление в диапазоне [0..1]
    return vec2 (current.x+dir.x+speed, current.y+dir.y*speed);

}


Сообщение отредактировал Xakep - Среда, 12 Августа 2015, 13:48
Форум игроделов » Программирование » C/C++ » Плавное движение в сторону точки B из точки A
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг