Всем привет!
Сегодня поговорим о том как выглядит бросок кубика и как он работает.

Кубики бывают разные (СКРИН_1).
Они нужны чтобы ролевая система могла обрабатывать геймплей - бросок кубика направляет историю, делает ее непредсказуемой (или умеренно предсказуемой) и в целом является тем что оживляет характеристики персонажа, позволяет играть в игру.
Кубики бывают разные - d4, d6, d8, d10, d12, d20, d100 и более уникальные для разных ролевых систем. (d = dice, игральная кость)
Зачем их вообще столько?
Каждый куб позволяет выбирать математическую вероятность, это позволяет настраивать опыт который хочется передать.
3 примера:
d20 - самый популярный куб в DND и символ игры. Имеет линейную вероятность. Это значит что на каждое значение от 1 до 20 шанс выпадения каждого из чисел 5%. Хорошее решение для героического фэнтези - критические успехи и провалы берут всего по 5% шанса выпадения.
2d6 - то что взяли хитрецы, создавшие Дискач. Хитрость в том что количество кубов, как и их значение, влияют на вероятность. если взять 2 куба по 6, то мы получим нормальное распределение (СКРИН_2). Оно позволяет сделать так, что значения в середине выпадают чаще чем значения по краям. То есть критические успехи и провалы будет всего 2 процента, тогда как средние (в основном разные сочетания суммы 7ки) будут выпадать 17% случаев. В отличие от d20 где любое число может выпасть с вероятность 5%, в 2d6 все выпадения будут стремиться к 7. Что лучше подходит если хочется иметь больше контроля над рандомом. Его становится меньше.
d10 - то что взял я. Для крутецкого мира моды, где чудеса случаются налево и направо - люди выживают после выстрела в голову, выживают при падении из самолета, переживают взрыв гранаты - для такого подойдет d10. Вероятность тут такая же как у d20 - линейная, но при этом шанс критических успехов и провалов равен аж 10%. Другими словами для мира крайностей хочется взять то что дает больше чудес. А еще он похож на маленькую корону.

И так. Возникает 2 проблемы при добавлении этого в игру - визуальная и расчетная часть. Расчеты укажу кратко и больше расскажу как отображается куб.
1. Сам бросок тригерится через выбор реплики - так делают везде и это уместно. Сам расчет у меня выражается в четырех вариантах:
Проверка пассивного ответа в диалоге (d10 + навык >= сложность)
Проверка активного навыка (d10 + навык >= сложность)
Проверка сноски (d10 + количество улик>= сложность)
Проверка сноски + активный навык(d10 + навык + количество улик >= сложность)
Сам расчет идет через генератор рандомных чисел. Не так сложно сделать, сколько сложнее выбрать под это все дизайн и баланс - что будет если навык высокий? А низкий? Что может сломать игру? Улик будет много? А как рассчитывать? Это все отдельные вопросы требующие времени и их приходится решать. Потому что если там будет ошибка или я взял не тот куб или ну ту систему, то геймплей умрет.
2. Анимация. Вот тут сделаем акцент. Дело в том что для анимации используют 3 варианта:
Плоский 2d виджет картинкой, которую сделали в Диско
Плоский 2d анимацией, который сделали в BG3
И настоящий 3d куб с физикой, который я особо даже и не припомню где есть. Я знаю что его точно будут делать в GLASS HOUSE (будущая игра), но там они это используют для какого-то вида боевки.
Взял я конечно же 3D куб. Тут сразу вопросы - а где его кидать? Какой фон? Где границы? Что с физикой? Хочется 3D куб по нескольким причинам - когда мы кидаем куб, то мы заранее видим одну из его граней в руке и хотим выкинуть положительное значение, мы чувствуем его вес, текстуру, гладкость граней. Затем мы его кидаем. И прежде чем мы увидим значение, мы глазами следим за тем как он бьется о стенки, как скачет по столу - короче это еще одна миниигра. Затем куб замирает и проходит доля секунды после того как мы распознаем значение, еще секунду мы его складываем с бонусом и после этого двигаемся по сюжеты дальше. Или наносим удар гвоздем. Так что хочется воплотить это в игре.
Я решил что он будет кататься по диалогу. Мы все время смотрим на диалог, не переводим взгляд в другую игровую область и в итоге сами границы диалога становятся частью игрового поля. Это прикольно. (СКРИН_3)

Когда мы начинали работать с чатом, то он предложил 3 варианта как сделать.
3 варианта которые предложил чат:
1.честный бросок - куб бросается, анализируется и его значение уходит в логику игры
2.нечестный с подкруткой - мы заранее рандомим число, затем кидаем куб по физике и потом аккуратно докручиваем его анимацией в конце
3.нечестный с магнитом - рандом заранее, кидаем по физике и потом мы докручиваем его не анимацией, а через физику магнитим к правильной стороне куба.
Я всегда иду от минимального рефакторинга, так что я отбросил первый вариант - чтобы он был честным пришлось бы менять систему кнопок и тригеров - пришлось бы значительно все менять, а это того не стоит.
В итоге я сделал 2 вариант, потом понял что он не работает, потом сделал 3, он тоже не работал, потом я дебагал 2 и снова вернулся к 3 - дебагал его, а потом вернулся снова к 2му и добавил его в игру.
Подход с анимацией плохо работал потому что финальное подкручивание выглядело нелепо, резко и комично
Подход с магнитом не сработал потому что он не мог примагнитить нужное значение
В итоге. В итоге я взял анимацию и сделал финальная подкрутку в тот момент когда кубик приближается и демонстрируется игроку.
Как это выглядит в игре: Мы спавним за пределами карты маленькую комнату в которой будет болтаться наш куб. Было несколько вариантов как добавить его поверх диалогового окна. Я пришел к выводу что он будет кидаться по зеленому фону, который будет вырезаться буквально как хромакей. Границы я подогнал под размер окна 1 в 1 и имеем магию кино. Точнее зеркала и фокусы разработки игр. (СКРИН_4)

КУБ В ДИАЛОГЕ! (ВИДЕО_5)
В будущем я наложу нормальные текстуры и стиль, добавлю визуальные эффекты и музыку - будет конфетка. Сейчас я рад что оно работает хотя бы механически.
Думаю это все на счет кубов. Возможно потом сделаю часть 2. А до тех пор - ЧАО КАКАО!
GCU
Можно предварительно рассчитать анимации физически честных бросков на каждый случай, после чего просто выбрать нужную. Чтобы не были заметны повторы, можно после использования рассчитать новую.
В процессе рассчёта можно для каждого значения сохранять полученную анимацию в стек, чтобы потом просто доставать готовую по нужному значению.
Или же просто перезапускать симуляцию пока не попадётся нужная.
Если начальное состояние не важно, то можно после рассчёта анимации поменять грани так, чтобы выпало то, что надо.