Плавное движение в сторону точки 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 |
めちゃくちゃちゃ
Сейчас нет на сайте
| Ахаха блин, и еще кто-то говорит что программисту не нужна математика По теме, чтобы узнать направление вектора, достаточно из точки Б вычесть точку А (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 |
|
| |
|