Size: a a a

2020 December 15

ДД

Дмитрий Дьячков... in Alprog I/O
Оу, меня даже мутить начало
источник

IE

Ilia Eliseev in Alprog I/O
Дмитрий Дьячков
Оу, меня даже мутить начало
+
источник

FB

Frost Bite in Alprog I/O
Я знал, что все соревнуются, кто вызовет сильнее приступ эпилепсии
источник

FB

Frost Bite in Alprog I/O
У здорового человека)
источник

FB

Frost Bite in Alprog I/O
Подсказка: если подобрать нужные звуки, непостоянный фреймрейт и добавить мерцания, то эффект сильнее
источник

Л

Лишний in Alprog I/O
Так вот он какой, сферический конь в вакууме.
источник
2020 December 18

NK

ID:0 in Alprog I/O
источник

NK

ID:0 in Alprog I/O
Логарифм и резинки
#код
Как-то в одном из чатов обронили фразу: «а когда вам последний раз был нужен логарифм?». Забавно, но мне он потребовался буквально на следующий день. Это ещё один маленький пост о том, какого рода математика нужна геймплейному программисту в повседневной жизни.

Часто нам нужно сглаживать какие-то процессы, у которых нет чёткого конца или он меняется во времени. Ну, например, у нас один объект — пусть это будет ручной дракончик — движется на воображаемой резинке за другим объектом, который тоже постоянно в движении: скажем, это будет персонаж игрока. Если игрок оказался далеко от дракончика (например, телепортировался), то дракончик сперва летит к нему очень быстро, но при приближении постепенно замедляется, чтобы это смотрелось хорошо.

Новички обычно просто домножают скорость дракончика на расстояние до игрока. Это простое решение, но ужасно плохое, поскольку время, за которое дракончик долетит до игрока, будет напрямую зависеть от FPS. При низком фпс он будет добираться до цели быстро, а при большом топтаться на месте неожиданно долго. А если FPS скачет, то и вовсе придётся лицезреть нечто рывкообразное.

Юнитологи классом повыше обычно используют небезызвестную функцию SmoothDamp. Внутри там скрывается мудрённое решение из книги Game Programming Gems 4. Вот только нам приходится где-то хранить текущую скорость для каждого процесса сглаживания, да и в целом довольно страшно выглядит. Нельзя ли как-то попроще сделать и без лишних переменных в местах вызова?

На самом деле если мы задумаемся, как будет выглядеть FPS-независимый способ приближения со сглаживанием, то быстро поймём, что нам надо проходить одинаковую долю расстояния за одинаковое время. Например, за первую секунду проходим половину пути, за вторую секунду половину от половины, то есть остаётся четверть, затем 1/8, 1/16 и так далее. И никогда мы по настоящему не достигаем цели, но нам это и не надо. При таком движении неважно в какой точке этого процесса мы оказались (на первой секунде, второй и т.п.), мы всегда знаем, как рассчитать движение дальше. От пути всегда остаётся лишь

1 / 2^t

А значит пройденное расстояние от времени вычисляется по формуле:

1 - 1 / 2^t

Двойка здесь всего лишь указатель на то, что в качестве одинаковых промежутков мы выбрали половину расстояния. Мы можем подставить туда 3, чтобы получить треть, или любое другое число больше 1. Можно думать об этом числе, как о степени агрессивности нашего In в нашем FPS-независимом сглаживании (аналог InCubic, InQuad и т.д.). Формула продолжит работать.

Но для полного счастья нам не хватает настройки времени, за которое дракончик будет визуально догонять персонажа из любой точки. Конечно, полностью он догнать не может, но нам хватит преодоления, скажем, 98% пути:

1 - 1 / base^t = 0,98
base^t = 1 / (1 - 0,98)
t = log(1 / (1 - 0,98), base)

Ну вот и всё. Теперь мы можем инициализировать этими параметрами нашу бесконечную резинку-пружинку, после чего ей можно будет скармливать deltaTime, а в ответ получать LerpK. Таким образом получилось простое FPS-независимое сглаживание для всего, что можно лерпать. Финальный класс можно видеть на скриншоте.

По-моему, симпатично получилось. А вы что думаете?
источник

D

DOCtorActoAntohich in Alprog I/O
ID:0
Логарифм и резинки
#код
Как-то в одном из чатов обронили фразу: «а когда вам последний раз был нужен логарифм?». Забавно, но мне он потребовался буквально на следующий день. Это ещё один маленький пост о том, какого рода математика нужна геймплейному программисту в повседневной жизни.

Часто нам нужно сглаживать какие-то процессы, у которых нет чёткого конца или он меняется во времени. Ну, например, у нас один объект — пусть это будет ручной дракончик — движется на воображаемой резинке за другим объектом, который тоже постоянно в движении: скажем, это будет персонаж игрока. Если игрок оказался далеко от дракончика (например, телепортировался), то дракончик сперва летит к нему очень быстро, но при приближении постепенно замедляется, чтобы это смотрелось хорошо.

Новички обычно просто домножают скорость дракончика на расстояние до игрока. Это простое решение, но ужасно плохое, поскольку время, за которое дракончик долетит до игрока, будет напрямую зависеть от FPS. При низком фпс он будет добираться до цели быстро, а при большом топтаться на месте неожиданно долго. А если FPS скачет, то и вовсе придётся лицезреть нечто рывкообразное.

Юнитологи классом повыше обычно используют небезызвестную функцию SmoothDamp. Внутри там скрывается мудрённое решение из книги Game Programming Gems 4. Вот только нам приходится где-то хранить текущую скорость для каждого процесса сглаживания, да и в целом довольно страшно выглядит. Нельзя ли как-то попроще сделать и без лишних переменных в местах вызова?

На самом деле если мы задумаемся, как будет выглядеть FPS-независимый способ приближения со сглаживанием, то быстро поймём, что нам надо проходить одинаковую долю расстояния за одинаковое время. Например, за первую секунду проходим половину пути, за вторую секунду половину от половины, то есть остаётся четверть, затем 1/8, 1/16 и так далее. И никогда мы по настоящему не достигаем цели, но нам это и не надо. При таком движении неважно в какой точке этого процесса мы оказались (на первой секунде, второй и т.п.), мы всегда знаем, как рассчитать движение дальше. От пути всегда остаётся лишь

1 / 2^t

А значит пройденное расстояние от времени вычисляется по формуле:

1 - 1 / 2^t

Двойка здесь всего лишь указатель на то, что в качестве одинаковых промежутков мы выбрали половину расстояния. Мы можем подставить туда 3, чтобы получить треть, или любое другое число больше 1. Можно думать об этом числе, как о степени агрессивности нашего In в нашем FPS-независимом сглаживании (аналог InCubic, InQuad и т.д.). Формула продолжит работать.

Но для полного счастья нам не хватает настройки времени, за которое дракончик будет визуально догонять персонажа из любой точки. Конечно, полностью он догнать не может, но нам хватит преодоления, скажем, 98% пути:

1 - 1 / base^t = 0,98
base^t = 1 / (1 - 0,98)
t = log(1 / (1 - 0,98), base)

Ну вот и всё. Теперь мы можем инициализировать этими параметрами нашу бесконечную резинку-пружинку, после чего ей можно будет скармливать deltaTime, а в ответ получать LerpK. Таким образом получилось простое FPS-независимое сглаживание для всего, что можно лерпать. Финальный класс можно видеть на скриншоте.

По-моему, симпатично получилось. А вы что думаете?
источник

ДД

Дмитрий Дьячков... in Alprog I/O
ID:0
Логарифм и резинки
#код
Как-то в одном из чатов обронили фразу: «а когда вам последний раз был нужен логарифм?». Забавно, но мне он потребовался буквально на следующий день. Это ещё один маленький пост о том, какого рода математика нужна геймплейному программисту в повседневной жизни.

Часто нам нужно сглаживать какие-то процессы, у которых нет чёткого конца или он меняется во времени. Ну, например, у нас один объект — пусть это будет ручной дракончик — движется на воображаемой резинке за другим объектом, который тоже постоянно в движении: скажем, это будет персонаж игрока. Если игрок оказался далеко от дракончика (например, телепортировался), то дракончик сперва летит к нему очень быстро, но при приближении постепенно замедляется, чтобы это смотрелось хорошо.

Новички обычно просто домножают скорость дракончика на расстояние до игрока. Это простое решение, но ужасно плохое, поскольку время, за которое дракончик долетит до игрока, будет напрямую зависеть от FPS. При низком фпс он будет добираться до цели быстро, а при большом топтаться на месте неожиданно долго. А если FPS скачет, то и вовсе придётся лицезреть нечто рывкообразное.

Юнитологи классом повыше обычно используют небезызвестную функцию SmoothDamp. Внутри там скрывается мудрённое решение из книги Game Programming Gems 4. Вот только нам приходится где-то хранить текущую скорость для каждого процесса сглаживания, да и в целом довольно страшно выглядит. Нельзя ли как-то попроще сделать и без лишних переменных в местах вызова?

На самом деле если мы задумаемся, как будет выглядеть FPS-независимый способ приближения со сглаживанием, то быстро поймём, что нам надо проходить одинаковую долю расстояния за одинаковое время. Например, за первую секунду проходим половину пути, за вторую секунду половину от половины, то есть остаётся четверть, затем 1/8, 1/16 и так далее. И никогда мы по настоящему не достигаем цели, но нам это и не надо. При таком движении неважно в какой точке этого процесса мы оказались (на первой секунде, второй и т.п.), мы всегда знаем, как рассчитать движение дальше. От пути всегда остаётся лишь

1 / 2^t

А значит пройденное расстояние от времени вычисляется по формуле:

1 - 1 / 2^t

Двойка здесь всего лишь указатель на то, что в качестве одинаковых промежутков мы выбрали половину расстояния. Мы можем подставить туда 3, чтобы получить треть, или любое другое число больше 1. Можно думать об этом числе, как о степени агрессивности нашего In в нашем FPS-независимом сглаживании (аналог InCubic, InQuad и т.д.). Формула продолжит работать.

Но для полного счастья нам не хватает настройки времени, за которое дракончик будет визуально догонять персонажа из любой точки. Конечно, полностью он догнать не может, но нам хватит преодоления, скажем, 98% пути:

1 - 1 / base^t = 0,98
base^t = 1 / (1 - 0,98)
t = log(1 / (1 - 0,98), base)

Ну вот и всё. Теперь мы можем инициализировать этими параметрами нашу бесконечную резинку-пружинку, после чего ей можно будет скармливать deltaTime, а в ответ получать LerpK. Таким образом получилось простое FPS-независимое сглаживание для всего, что можно лерпать. Финальный класс можно видеть на скриншоте.

По-моему, симпатично получилось. А вы что думаете?
Я доволен статьей, приятно что люди не забывают для чего они все это учили.
источник

KF

Ksanf Fillum in Alprog I/O
ID:0
Логарифм и резинки
#код
Как-то в одном из чатов обронили фразу: «а когда вам последний раз был нужен логарифм?». Забавно, но мне он потребовался буквально на следующий день. Это ещё один маленький пост о том, какого рода математика нужна геймплейному программисту в повседневной жизни.

Часто нам нужно сглаживать какие-то процессы, у которых нет чёткого конца или он меняется во времени. Ну, например, у нас один объект — пусть это будет ручной дракончик — движется на воображаемой резинке за другим объектом, который тоже постоянно в движении: скажем, это будет персонаж игрока. Если игрок оказался далеко от дракончика (например, телепортировался), то дракончик сперва летит к нему очень быстро, но при приближении постепенно замедляется, чтобы это смотрелось хорошо.

Новички обычно просто домножают скорость дракончика на расстояние до игрока. Это простое решение, но ужасно плохое, поскольку время, за которое дракончик долетит до игрока, будет напрямую зависеть от FPS. При низком фпс он будет добираться до цели быстро, а при большом топтаться на месте неожиданно долго. А если FPS скачет, то и вовсе придётся лицезреть нечто рывкообразное.

Юнитологи классом повыше обычно используют небезызвестную функцию SmoothDamp. Внутри там скрывается мудрённое решение из книги Game Programming Gems 4. Вот только нам приходится где-то хранить текущую скорость для каждого процесса сглаживания, да и в целом довольно страшно выглядит. Нельзя ли как-то попроще сделать и без лишних переменных в местах вызова?

На самом деле если мы задумаемся, как будет выглядеть FPS-независимый способ приближения со сглаживанием, то быстро поймём, что нам надо проходить одинаковую долю расстояния за одинаковое время. Например, за первую секунду проходим половину пути, за вторую секунду половину от половины, то есть остаётся четверть, затем 1/8, 1/16 и так далее. И никогда мы по настоящему не достигаем цели, но нам это и не надо. При таком движении неважно в какой точке этого процесса мы оказались (на первой секунде, второй и т.п.), мы всегда знаем, как рассчитать движение дальше. От пути всегда остаётся лишь

1 / 2^t

А значит пройденное расстояние от времени вычисляется по формуле:

1 - 1 / 2^t

Двойка здесь всего лишь указатель на то, что в качестве одинаковых промежутков мы выбрали половину расстояния. Мы можем подставить туда 3, чтобы получить треть, или любое другое число больше 1. Можно думать об этом числе, как о степени агрессивности нашего In в нашем FPS-независимом сглаживании (аналог InCubic, InQuad и т.д.). Формула продолжит работать.

Но для полного счастья нам не хватает настройки времени, за которое дракончик будет визуально догонять персонажа из любой точки. Конечно, полностью он догнать не может, но нам хватит преодоления, скажем, 98% пути:

1 - 1 / base^t = 0,98
base^t = 1 / (1 - 0,98)
t = log(1 / (1 - 0,98), base)

Ну вот и всё. Теперь мы можем инициализировать этими параметрами нашу бесконечную резинку-пружинку, после чего ей можно будет скармливать deltaTime, а в ответ получать LerpK. Таким образом получилось простое FPS-независимое сглаживание для всего, что можно лерпать. Финальный класс можно видеть на скриншоте.

По-моему, симпатично получилось. А вы что думаете?
У меня где-то лежит сохранённый скрин из пеинта, где я вычислял лучшую аппроксимацию сектора. Лежит под именем "математика в жизни не пригодится.bmp". Формулы вписанных в треугольник окружностей и вот это все.

Математика это весело)
источник

АТ

Александр Тужик... in Alprog I/O
ID:0
Логарифм и резинки
#код
Как-то в одном из чатов обронили фразу: «а когда вам последний раз был нужен логарифм?». Забавно, но мне он потребовался буквально на следующий день. Это ещё один маленький пост о том, какого рода математика нужна геймплейному программисту в повседневной жизни.

Часто нам нужно сглаживать какие-то процессы, у которых нет чёткого конца или он меняется во времени. Ну, например, у нас один объект — пусть это будет ручной дракончик — движется на воображаемой резинке за другим объектом, который тоже постоянно в движении: скажем, это будет персонаж игрока. Если игрок оказался далеко от дракончика (например, телепортировался), то дракончик сперва летит к нему очень быстро, но при приближении постепенно замедляется, чтобы это смотрелось хорошо.

Новички обычно просто домножают скорость дракончика на расстояние до игрока. Это простое решение, но ужасно плохое, поскольку время, за которое дракончик долетит до игрока, будет напрямую зависеть от FPS. При низком фпс он будет добираться до цели быстро, а при большом топтаться на месте неожиданно долго. А если FPS скачет, то и вовсе придётся лицезреть нечто рывкообразное.

Юнитологи классом повыше обычно используют небезызвестную функцию SmoothDamp. Внутри там скрывается мудрённое решение из книги Game Programming Gems 4. Вот только нам приходится где-то хранить текущую скорость для каждого процесса сглаживания, да и в целом довольно страшно выглядит. Нельзя ли как-то попроще сделать и без лишних переменных в местах вызова?

На самом деле если мы задумаемся, как будет выглядеть FPS-независимый способ приближения со сглаживанием, то быстро поймём, что нам надо проходить одинаковую долю расстояния за одинаковое время. Например, за первую секунду проходим половину пути, за вторую секунду половину от половины, то есть остаётся четверть, затем 1/8, 1/16 и так далее. И никогда мы по настоящему не достигаем цели, но нам это и не надо. При таком движении неважно в какой точке этого процесса мы оказались (на первой секунде, второй и т.п.), мы всегда знаем, как рассчитать движение дальше. От пути всегда остаётся лишь

1 / 2^t

А значит пройденное расстояние от времени вычисляется по формуле:

1 - 1 / 2^t

Двойка здесь всего лишь указатель на то, что в качестве одинаковых промежутков мы выбрали половину расстояния. Мы можем подставить туда 3, чтобы получить треть, или любое другое число больше 1. Можно думать об этом числе, как о степени агрессивности нашего In в нашем FPS-независимом сглаживании (аналог InCubic, InQuad и т.д.). Формула продолжит работать.

Но для полного счастья нам не хватает настройки времени, за которое дракончик будет визуально догонять персонажа из любой точки. Конечно, полностью он догнать не может, но нам хватит преодоления, скажем, 98% пути:

1 - 1 / base^t = 0,98
base^t = 1 / (1 - 0,98)
t = log(1 / (1 - 0,98), base)

Ну вот и всё. Теперь мы можем инициализировать этими параметрами нашу бесконечную резинку-пружинку, после чего ей можно будет скармливать deltaTime, а в ответ получать LerpK. Таким образом получилось простое FPS-независимое сглаживание для всего, что можно лерпать. Финальный класс можно видеть на скриншоте.

По-моему, симпатично получилось. А вы что думаете?
Да, в геймдеве из математики в основном геома. Это понятно. Просто моя мини-рубрика "математика в геймплее" посвящена больше алгебре, так как менее очевидные места :)
источник

🇬⠀

🇬 🇪 🇿 🇪 🇱 🇱 🇮 🇬 ⠀... in Alprog I/O
Ну можно знания из алгебры всякие применять иногда. Теория категорий хорошо помогает понимать функциональщину
источник

ET

Evgenij Tsvetkov in Alprog I/O
Спасибо за статью!
источник

NK

ID:0 in Alprog I/O
Поправочка!
#код
Ох, что-то я написал этот пост и тут же понял, что лишнего наворотил. Движение, при котором мы за равные промежутки проходим половину, затем половину от остатка и так далее — это фактически тоже самое движение, когда мы за равные промежутки проходим треть, затем треть от остатка и так далее. Это просто свойство перевёрнутой экспоненты самой по себе. И неважно какое основание. А чтобы управлять агрессивностью In-прыжка, достаточно слегка менять threshold-порог. Чем выше выставить процент порога, тем агрессивнее будет прыжок в начале.

Правду говорят, что если хочешь в чём-то разобраться сам, то расскажи это другому. Вот и здесь так получилось.

public struct EndlessSpring
{
   private float TimeScale;

   // time is amount of time that needeed to pass
   // threshold-share of the distance (never pass 100%)
   public EndlessSpring(float time, float threashold = 0.98f)
   {
       var expectedValue = 1 / (1 - threashold);
       this.TimeScale = Mathf.Log(expectedValue, 2) / time;
   }

   public float GetLerpK(float deltaTime)
   {
       return 1 - 1 / Mathf.Pow(2, deltaTime * TimeScale);
   }
}
источник

W

WallK in Alprog I/O
ID:0
Поправочка!
#код
Ох, что-то я написал этот пост и тут же понял, что лишнего наворотил. Движение, при котором мы за равные промежутки проходим половину, затем половину от остатка и так далее — это фактически тоже самое движение, когда мы за равные промежутки проходим треть, затем треть от остатка и так далее. Это просто свойство перевёрнутой экспоненты самой по себе. И неважно какое основание. А чтобы управлять агрессивностью In-прыжка, достаточно слегка менять threshold-порог. Чем выше выставить процент порога, тем агрессивнее будет прыжок в начале.

Правду говорят, что если хочешь в чём-то разобраться сам, то расскажи это другому. Вот и здесь так получилось.

public struct EndlessSpring
{
   private float TimeScale;

   // time is amount of time that needeed to pass
   // threshold-share of the distance (never pass 100%)
   public EndlessSpring(float time, float threashold = 0.98f)
   {
       var expectedValue = 1 / (1 - threashold);
       this.TimeScale = Mathf.Log(expectedValue, 2) / time;
   }

   public float GetLerpK(float deltaTime)
   {
       return 1 - 1 / Mathf.Pow(2, deltaTime * TimeScale);
   }
}
threshold*
источник
2020 December 19

R

Roman in Alprog I/O
Александр Тужик
Да, в геймдеве из математики в основном геома. Это понятно. Просто моя мини-рубрика "математика в геймплее" посвящена больше алгебре, так как менее очевидные места :)
Что такое геома?
источник

АТ

Александр Тужик... in Alprog I/O
Roman
Что такое геома?
Геометрия
источник

R

Roman in Alprog I/O
Ааа
источник

VD

Valentin Drazdov in Alprog I/O
ID:0
Логарифм и резинки
#код
Как-то в одном из чатов обронили фразу: «а когда вам последний раз был нужен логарифм?». Забавно, но мне он потребовался буквально на следующий день. Это ещё один маленький пост о том, какого рода математика нужна геймплейному программисту в повседневной жизни.

Часто нам нужно сглаживать какие-то процессы, у которых нет чёткого конца или он меняется во времени. Ну, например, у нас один объект — пусть это будет ручной дракончик — движется на воображаемой резинке за другим объектом, который тоже постоянно в движении: скажем, это будет персонаж игрока. Если игрок оказался далеко от дракончика (например, телепортировался), то дракончик сперва летит к нему очень быстро, но при приближении постепенно замедляется, чтобы это смотрелось хорошо.

Новички обычно просто домножают скорость дракончика на расстояние до игрока. Это простое решение, но ужасно плохое, поскольку время, за которое дракончик долетит до игрока, будет напрямую зависеть от FPS. При низком фпс он будет добираться до цели быстро, а при большом топтаться на месте неожиданно долго. А если FPS скачет, то и вовсе придётся лицезреть нечто рывкообразное.

Юнитологи классом повыше обычно используют небезызвестную функцию SmoothDamp. Внутри там скрывается мудрённое решение из книги Game Programming Gems 4. Вот только нам приходится где-то хранить текущую скорость для каждого процесса сглаживания, да и в целом довольно страшно выглядит. Нельзя ли как-то попроще сделать и без лишних переменных в местах вызова?

На самом деле если мы задумаемся, как будет выглядеть FPS-независимый способ приближения со сглаживанием, то быстро поймём, что нам надо проходить одинаковую долю расстояния за одинаковое время. Например, за первую секунду проходим половину пути, за вторую секунду половину от половины, то есть остаётся четверть, затем 1/8, 1/16 и так далее. И никогда мы по настоящему не достигаем цели, но нам это и не надо. При таком движении неважно в какой точке этого процесса мы оказались (на первой секунде, второй и т.п.), мы всегда знаем, как рассчитать движение дальше. От пути всегда остаётся лишь

1 / 2^t

А значит пройденное расстояние от времени вычисляется по формуле:

1 - 1 / 2^t

Двойка здесь всего лишь указатель на то, что в качестве одинаковых промежутков мы выбрали половину расстояния. Мы можем подставить туда 3, чтобы получить треть, или любое другое число больше 1. Можно думать об этом числе, как о степени агрессивности нашего In в нашем FPS-независимом сглаживании (аналог InCubic, InQuad и т.д.). Формула продолжит работать.

Но для полного счастья нам не хватает настройки времени, за которое дракончик будет визуально догонять персонажа из любой точки. Конечно, полностью он догнать не может, но нам хватит преодоления, скажем, 98% пути:

1 - 1 / base^t = 0,98
base^t = 1 / (1 - 0,98)
t = log(1 / (1 - 0,98), base)

Ну вот и всё. Теперь мы можем инициализировать этими параметрами нашу бесконечную резинку-пружинку, после чего ей можно будет скармливать deltaTime, а в ответ получать LerpK. Таким образом получилось простое FPS-независимое сглаживание для всего, что можно лерпать. Финальный класс можно видеть на скриншоте.

По-моему, симпатично получилось. А вы что думаете?
Вспомнил старую математическую задачу про ахилеса/геракла и черепаху
источник