Алгоритм для движения объекта по времени
|
|
DurianOdour | Дата: Понедельник, 23 Октября 2017, 20:27 | Сообщение # 1 |
был не раз
Сейчас нет на сайте
| Здравствуйте, я только начинающий.
Возник такой вопрос. Задача стоит в том чтобы объект двигался по времени, в зависимости от того какое время поставили. К примеру.
Есть шарик. В настройках поставили, что игровое время 40 секунд и всего шарик должен сделать 10 полных проходов пути (туда и обратно).
То есть считаем. Шарик должен пройти 1 проход (от 1 стенки к другой и обратно) за 40/10=4 секунды.
Теперь собственно как это реализовать ?
Если нельзя быть уверенным, в том что какой-то определенный фреймрейт будет.
К примеру 1 цикл игры (отрисовка и вычисление) происходит за 30мс. Соответственно можно посчитать.
4000/30 = 133 это у нас количество циклов для прохождения. Теперь допустим полное расстояние от 1 стенки к другой 1000px. Чтобы шарик сделал полный проходу нужно 2000px.
Соответственно - 2000/133 = 15, то есть каждую итерацию шарик должен проходить + 15px.
Это все хорошо, но как сделать в случае если фрейм рейт не известен + если он меняется часто и нужно коррелировать.
Желательно точно чтобы выходило время заданное в настройках. Подскажите пожалуйста алгоритм или просто идеи как это реализовать можно ?
Спасибо
|
|
| |
drcrack | Дата: Понедельник, 23 Октября 2017, 21:15 | Сообщение # 2 |
старожил
Сейчас нет на сайте
| если он должен просто тупо двигаться туда сюда, тебе подойдет функция координаты X от времени "туда-сюда" это очевидно что-то вроде синуса поэтому заходим на fooplot и ужимаем синус в удобные нам 0..1 рамки: http://fooplot.com/#W3sidH....TMiXX1d теперь реализуем это в коде (Unity):
Код void Update() {
var time = 4f; var distance = 10f; var sin = (Mathf.Sin(Time.time * Mathf.PI * 2f / time - Mathf.PI / 2f) + 1f) / 2f; transform.position = new Vector3(sin * distance, 0, 0); }
получился обьект, который 2 секунды (половина времени) двигается от 0 до 10 и затем еще 2 обратно и никак не зависит от фреймрейта
Сообщение отредактировал drcrack - Понедельник, 23 Октября 2017, 21:17 |
|
| |
AAAlex | Дата: Понедельник, 23 Октября 2017, 21:54 | Сообщение # 3 |
частый гость
Сейчас нет на сайте
| Цитата DurianOdour ( ) просто идеи как это реализовать можно ? Я как всегда, расскажу про UE4 Есть тут такая штука, Level sequence называется, или более старый matinee. Работает оно как анимация: то есть задал положения для объектов, задал время для каждого положения, а потом как плеером играешь вообще без кода. Задвать там можно не только координаты, но и растягивать, поворачивать, играть анимацию для скелетов, играть музыку и звуки, вызывать события и куча всего еще. Внешне похоже на любой видеоредактор, позволяет делать от простого движения платформ, до полноценных кат сцен. Наверняка такие штуки есть и для других движков, может быть отдельным плагином. Я не проверял, может кто подскажет, если знает такое.
|
|
| |
DurianOdour | Дата: Вторник, 24 Октября 2017, 20:13 | Сообщение # 4 |
был не раз
Сейчас нет на сайте
| Спасибо большое за ответ. Да действительно можно так. Только пожалуйста, если не трудно, объясните все эти числа что вы использовали 1f, 2f за что они отвечают в данном случае. Спасибо
|
|
| |
drcrack | Дата: Среда, 25 Октября 2017, 00:29 | Сообщение # 5 |
старожил
Сейчас нет на сайте
| Они нужны чтобы обычный синус преобразовать к виду, который будет удобен для работы, так чтобы при x от 0 до 1 это выражение возвращало результаты от 0 до 1, достигая максимума в 0.5
просто синус: http://fooplot.com/#W3sidH....SJdfV0- удобный синус: http://fooplot.com/#W3sidH....TMiXX1d
можешь на этом сайте постепенно менять формулу, добавляя разные коэфициенты из большого выражения и поймешь зачем все это нужно
Сообщение отредактировал drcrack - Среда, 25 Октября 2017, 00:30 |
|
| |
DurianOdour | Дата: Суббота, 28 Октября 2017, 00:55 | Сообщение # 6 |
был не раз
Сейчас нет на сайте
| drcrack,
Спасибо огромное, попробовал сделать, но не получилось, идея примерно понятно, но что-то я затупил где-то.
Код distance = gameUpdateStateBundle.getGameScreen().getHeight(); double timeElapsed = gameUpdateStateBundle.getTimeElapsed(); double gameTime = gameUpdateStateBundle.getGameTime(); double sin = (Math.sin((float) gameTime * Math.PI * 2f / (float) timeElapsed - Math.PI / 2f) + 1f) / 2f; Logger.error("SIN " + sin); mCenterX += (mVelocityVector.x * timeElapsed); mCenterY = (float) (distance * sin);
Подскажите в чем проблема может быть. Ваша идея с функцией для четкого определения позиции по текущему времени очень понравилась.
Спасибо
|
|
| |
drcrack | Дата: Суббота, 28 Октября 2017, 10:17 | Сообщение # 7 |
старожил
Сейчас нет на сайте
| Там где сейчас timeElapsed (полагаю это время с прошлого кадра) должна быть константа — время, которое обьект должен тратить на движение туда и обратно, 4 секунды например как у тебя в 1 посте написано.
|
|
| |