Степенная функция
Одной из самых часто возникающих задач при моделировании игры и составлении баланса является задача выбора функции для определенных зависимостей, которая бы удовлетворяла задумкам геймдизайнера.
Чаще всего нужна функция, которая бы постоянно росла или постоянно убывала, но делала бы это не линейно, а с какой-то закономерностью. Причем часто нужно, чтобы эта функция имела одну или две определенные точки, в которых результат был бы строго определен.
В свою очередь, геймдизайнер хочет иметь возможность контролировать характер такой функции, при этом сохраняя значения в ключевых точках.
Пример задачи
Нужно вывести формулу, которая бы определяла количество необходимого опыта для достижения определенного уровня героя.
При этом мы бы хотели точно зафиксировать стартовое значение такой функции: Первый уровень должен даваться за 100 единиц опыта. А в формуле должны быть коэффициенты, которые бы позволяли бы легко управлять характером кривой на графике, делать ее растущей быстрее или медленнее.
Степенная функция
В большинстве случаев нам подойдет степенная функция. Частные случаи графиков такой функции нам хорошо знакомы еще со школы. Это графики в виде параболы и гиперболы.
Просто теперь мы дополняем эти функции коэффициентами, которые позволяют нам:
— «Сжимать» и «растягивать» графики по оси Y. За это отвечает коэффициент k.
— Перемещать график горизонтально. За это отвечает коэффициент a.
— Перемещать график вертикально. За это отвечает коэффициент b.
— Делать график выпуклым или вогнутым. За это отвечает коэффициент power.
Этих трансформаций достаточно, чтобы построить необходимую функцию для какой-либо зависимости в балансе.
Гипербола, парабола и линия
Как мы уже видели выше, степень функции (power) сильно влияет на ее характер. Для каждой конкретной задачи мы можем выбрать тот диапазон значений степени, который нам будет нужен. Рассмотрим все варианты:
Power < 0. График функции будет представлен в виде гиперболы. У графика будут две асимптоты. Причем они будут определяться коэффициентами a и b.
Power = 0. Функцию можно свести к виду y = const. График будет выглядеть как параллельная оси x линия.
0 < Power < 1. График функции будет представлен в виде «замедляющейся» параболы.
Power = 1. Функцию можно свести к виду y = kx+b. График функции будет в виде наклонной линии.
Power > 1. График функции будет представлен в виде «ускоряющейся» параболы.
В зависимости от нужного характера графика, мы должны будем наложить соответствующее ограничение на параметр power. В частности, если этот параметр будет добавлен в настройки игры, то должна быть введена дополнительная проверка на соответствие параметра нужному диапазону.
Ключевые точки
Итак, в начале мы решаем какой характер функции нам нужен для нашей конкретной задачи и накладываем ограничение на power.
Далее, как правило, нам нужно наложить ограничения на функцию и сделать ее вид более удобным для работы. Это делается с помощью ключевых точек. Мы определяем какие значения должна принимать функция в ключевых точках (x1, y1), (x2, y2) и получаем систему уравнений вида:
Мы можем выразить коэффициенты функции через значения ключевых точек и переписать формулу, так чтобы вместо начальных коэффициентов были выражения, которые бы использовали координаты ключевых точек. Зачастую это делает формулу более удобной для настройки. Рассмотрим это на двух разных примерах с разным характером функции.
Пример с параболой
Вышеначатый пример с опытом и уровнями. Нужно вывести формулу, которая бы определяла количество необходимого опыта для достижения некого уровня героя.
Нам нужна бесконечно растущая функция. Возможно замедляющая или ускоряющая свой рост, мы пока этого не решили (для формулы это будет не важно).
Примем за условие, что power > 0.
Нам было бы удобно работать с формулой, указывая ключевые точки:
— Сколько опыта нужно для первого уровня
— Сколько опыта нужно для N уровня. (N может быть, например, максимальный текущий уровень в игре)
Обозначим эти ключевые точки, как: (1; XpStart) и (LvlFin; XpFin).
Теперь мы можем выразить k следующим образом:
Да, выглядит страшновато, но зато теперь настраивать значения будет гораздо проще.
Протестировать параметры можно здесь (меняйте значения ключевых точек и/или коэффициент power):
https://docs.google.com/spreadsheets/d/1N-6gO6cxl8oEnwlr_NpRJvomA3DSTqnkrh5mzACCYms/edit?usp=sharing
Пример с гиперболой
Главный герой бежит по полосе препятствий. Иногда он может встретить на дороге аптечки. Чем дальше расстояние, которое пробежал герой, тем ниже вероятность встретить аптечку на каких-то определенных чекпоинтах. Допустим чекпоинты встречаются каждые 100 метров. Но эта вероятность хоть и падает, она всегда выше определенного значения.
Нужна функция вероятности, зависящая от пройденных метров. Очевидно, что нам нужна убывающая функция, которая асимптотически стремится к какому-то предельному значению. То есть нам нужна гипербола.
Возьмем за ключевую точку первый чекпоинт на 100 метрах. Пусть вероятность на нем будет равна ProbStart.
Вместо второй ключевой точки возьмем предельное значение, к которому стремится вероятность. Пусть она будет равна ProbInf. Кстати, это и есть коэффициент b.
Подставим ключевую точку в уравнение:
Обратим внимание, что a не должно быть равно -100.
Протестировать параметры можно здесь:
https://docs.google.com/spreadsheets/d/1N-6gO6cxl8oEnwlr_NpRJvomA3DSTqnkrh5mzACCYms/edit?usp=sharing
Заключение
— Если вам нужно выразить какую-то зависимость в игре через формулу, попробуйте использовать степенную функцию.
— Определите ключевые точки на графике, которые вы хотите контролировать и выразите коэффициенты функции через значения этих точек.
— Проследите, чтобы конфиг для этой функции не мог принять значения для коэффициентов, которые ломают логику функции. Например, чтобы не случилось деления на ноль или взятие корня из отрицательного числа. В случае некорректных данных можно выдавать ошибку при изменения конфига.
Если материал показался полезным, подписывайтесь на телеграмм-канал: https://t.me/SecretRoom_Gamedesign
Если возникли вопросы или заметили ошибку, то оставьте, пожалуйста, комментарий в этом посте: https://t.me/SecretRoom_Gamedesign/15