Як була створена "Чарівна казка"
Створити проєкт в соло не кожному під силу, але це хороший виклик для тих, хто впевнений у своїх здібностях або хоче отримати незабутній (пекельний) досвід. Це мій другий соло-проєкт на джем, який посів 12 місце у топі! Я щиро дякую всім, хто пройшов гру, поставив оцінку та поділився своїми враженнями! У цьому девлозі я хочу розповісти, як саме створювалась “Чарівна казка” та показати рішення, які були прийняті мною під час розробки.
До джему
Перед тим, як розповідати головне, хочеться розказати про моменти, які існували та відбувалися до початку джему, але які вплинули на результат мого проєкту. Одна з головних персонажів новели, Лорем, могла декого зачепити своїм ім’ям, яке нагадує усім відомий перекручений латинський текст. І це не дарма, бо в неї є своя цікава історія, на відміну від Деяна, який був створений вже під час конкурсу. Все почалось два роки тому, коли на світ з’явився перший дизайн рудоволосої дівчини. Тоді я просто розмальовувала зображення, яке намалювала своїм тоді новеньким графічним планшетом. У неї не було імені, але мені сподобався результат малюнка, тому я малювала її ще й ще. Загалом, вона стала неабияким “плейсхолдером” в моїй творчості, її вигляд міг дещо змінюватись і зрештою я назвала її “Лорем” на честь такого ж текста-плейсхолдера. Але яке це відношення має до розробки новели? Так ось, коли я почала експериментувати в ренпаї, після мого першого джему, то в мене з’явилась необхідність мати спрайт, який і буде моїм об’єктом для досліджень. Як ви вже здогадались, ним стала Лорем, але не та версія, яку ви бачили в “Чарівній казці”. Перша версія Лорем мала інший стиль мальовки, але також вона мала й те, що перейшло потім у мій проєкт - анімація кліпання та говоріння, але про це поговоримо пізніше.
Друга річ, якою я займалась до конкурсу, була розробка інтерфейсу. Все, що ви бачите в інтерфейсі готового проєкту - плід тих самих експериментів. Розташування кнопок, блоків з налаштуваннями, швидке меню в грі… Створювати це все було цікаво, хоч допустила я чимало помилок, але отриманий досвід того вартував. На жаль, більш детального опису, як це було створено, дати не можу, бо на той час процес не документувала та в самому коді все досить заплутано.
Початок джему
Перший день найцікавіший, чи не так? Тут народжуються ідеї, персонажі та сюжети. Коли я побачила тему “Віртуальність”, то в голові спочатку виник порожній лист. Це слово, в першу чергу, асоціювалось з кіберпанком, технологіями та майбутнім, хоча це не зовсім мій улюблений жанр. Для того, щоб мати щось для роздумів, я пішла взнавати більше визначень до цього слова, де й прочитала про кіно та театр. Звісно, ця тема менше схожа на “віртуальність”, що я й взнала за результатами оцінювання, але вона імпонувала мені більше. Також за декілька днів до джему я задумувалась над тим, що хочу створити романтичну історію. Це теж не мій жанр, але я хотіла дати собі виклик у його написанні, тому мій перший концепт до історії був приблизно таким: “Пара персонажів відвідує театр, після чого отримує видіння з постановки”. В кінцевому результаті, я не сильно відійшла від цієї ідеї.
Коли в моїй голові з’явився початок казки про Принцесу місяця та Принца сонця, я обрала персонажів. Звісно ж, що першою була Лорем, бо я подумала, що її дизайн підійде до моєї оповіді і при цьому виборі я помітила цікаву закономірність: Лорем, яка має яскравий, теплий дизайн, пов’язана з Принцесою місяця, яка навпаки має лише холодні відтінки. Тому, малюючи перший концепт, я зробила другого персонажа, Деяна, в холодній палітрі, хоча Принц сонця має теплі кольори.
Ідея є, перші дизайни є, а це означає, що настав час для справжньої роботи. Далі я розподілю все по категоріях розробки, а не по днях, щоб, якщо вам цікавий конкретний етап, ви могли його легко знайти.
Сценарій
Я все ще набираюсь досвіду у написані новел та довгих текстів і ця необізнаність дає безмежний простір для пошуку свого стилю та експериментів, з чим я зіткнулась й цього разу. У сюжеті фігурують два персонажі, які однаково важливі, тому я спробувала писати текст від лиця обох, а не лише когось одного. Спочатку здавалось, що це буде складно реалізувати, але в процесі я одразу відчувала на якому моменті змінити того, хто оповідає. Думаю, що для читачів теж цікаво взнати, як персонажі бачать одне одного зі своєї перспективи. Такий прийом розповсюджений у візуальних новелах, тому варто наслідувати хороші приклади, якщо я продовжу писати щось подібне.
Для написання сценарію “Чарівної казки” я використовувала гугл документи, бо ця програма проста та зручна, її спокійно можна відкрити в браузері та завантажити на телефон, що дає змогу редагувати та писати текст з різних пристроїв. Також, якщо у вас декілька людей в команді, які займаються сценарієм або його вичиткою, то це очевидний варіант для роботи, бо в ній можлива синхронізація.
Минулого джему я робила свою першу новелу, “Няня”, і завдяки їй я зрозуміла, як краще оформлювати текст для сценарію. Для “Няні” я просто писала ім’я персонажа, який говорить та його діалог, але на етапі програмування перенесення тексту займало доволі багато часу, тому цього разу я змінила тактику та почала писати текст так, як він має виглядати в коді. Тобто, замість “Лорем: Привіт!” стало “l "Привіт!"” (l - ім’я персонажа в коді). Оскільки в “Чарівній казці” тексту значно більше, ніж в “Няні”, то цей спосіб став дуже дієвим, бо потрібно було всього лиш скопіювати текст з документа та вставити в скрипт.
ln "Тепер я не знаю чи варто щось казати, може це не так і важливо?"
ln "Я лиш зітхнула."
l "Схоже, сьогодні нещасливий день."
d "Гм? Чому ти так думаєш? І з якої ноги ти сьогодні встала?"
l "Що? Тільки не кажи що ти в таке віриш."
l "Хоча, якщо пригадати…"
Малювання
Усю графіку для своєї візуальної новели я робила самотужки, у фотошопі. За професією я живописець, а в діджитал працюю близько 5 років, тому особливого досвіду я не отримала, крім спроби дизайну UI.
В перші дні я почала малювати персонажів, бо коли вони готові, то стає легше працювати над фонами та усім іншим. На відміну від “Няні”, де спрайт персонажа відрізнявся лише конкретною емоцією, у “Чарівній казці” спрайти персонажів були схожі на конструктор, який потім треба було збирати у коді. Виглядають вони таким чином, бо, як я згадувала на початку, вони мають анімацію блимання та говоріння. Тобто спрайт персонажа побудований таким чином: тіло, основа голови, брови та їх варіації, очі та їх анімація, рот та його анімація та інші ефекти.
На жаль, не встигла зробити багато комбінацій для спрайтів, бо майже всі я кодила в останні дні. Ось як виглядає лист з різними варіантами, але тут не всі, бо потім я почала просто підписувати їх в коді.
Наступним я почала робити дизайн текстбоксів. Оскільки головних персонажів два і від кожного іде своя оповідь, то я вирішила візуально відокремити їх діалог, щоб читач точно не заплутався. В результаті вийшло три варіанти діалогових вікон: жовтий для Лорем, блакитний для Деяна та білий для Оповідача з прибиральницею. Перші два напівпрозорі, щоб краще було видно спрайт та фони, а останній зроблений непрозорим та майже одним кольором, щоб нагадувати сторінку з книги.
Фони робити було найскладніше, бо малюю я їх рідко. Цього разу я зрозуміла, що в мене може не вистачити часу на мальовку кожного, тому я вирішила спробувати один спосіб, який ще не використовувала, а саме малювати поверх фотографій. Фотографії, звісно ж, я робила сама, на свій телефон. В об’єктив потрапили вулички мого міста, які я обробляла в фотошопі, а потім малювала поверх них. Фотографії також можна використовувати в якості референсів, але, якщо композиція фотографії непогана, то чому б не скоротити час, що я й зробила.
Кімнати персонажів я малювала сама, а ось для фону з Оповідачем теж використала новий для себе спосіб - 3д моделі. Для композиції я використала Magic Poser і вже на його основі зробила фон.
Варто зазначити, що я використовувала деякі сайти, щоб зменшити розмір своїх фонів. Багато з них важили більше 1-2 мб, але після стискання вони почали важити менше 700кб. Здається, що це небагато, але насправді це дуже важливо для оптимізації гри, бо уявіть скільки можна зекономити місця, якщо стиснути 15 таких зображень, а не лише одне. Те саме стосується й інших файлів, наприклад, музики та звуку, які рекомендують зберігати у ogg форматі, а не wav чи mp3.
Останнє, про що я розповім у цій категорії - паралакс в головному меню. Для нього треба було намалювати всі потрібні об’єкти окремо. Було трохи складно розібратись з їх положенням і розміром кожного файлу, але це того вартувало. Шкода, що в мене не було часу зробити більше подібних ефектів у грі, але це й не мій останній проєкт, правда? Якщо хочете ознайомитись, як зробити такий ефект у своїй новелі, то робила свій паралакс я за цим туторіалом.
Програмування
В цьому блоці я більше розповідатиму про анімації, які я створила за допомогою коду, аніж про процес всього кодування. Зрештою, багато людей й так знають, як працює рушій Ренпай, як показати в ньому діалог, спрайт, фон тощо. Лише зазначу, що цього разу я спробувала організувати свій код, а не писати майже все в одному файлі. І так, з досвіду скажу, що навіть соло-розробникам варто все організовувати, якщо не хочете потім довго розгрібати, де яка виникла помилка. Для порівняння покажу, як виглядають файли в “Няні” (стандартні файли ренпайної новели) і як в “Чарівній казці”.
Отже, почну я з анімації спрайтів та як саме я їх ліпила.
image lorem blink: #анімація очей "lorem/eyes/eyes.png" choice: 6.5 choice: 5.5 choice: 4.5 choice: 3.5 choice: 1.5 # ↑ код, який робить рандом "lorem/eyes/eyes_a1.png" 0.15 "lorem/eyes/eyes_sad.png" 0.05 "lorem/eyes/eyes_a2.png" 0.15 repeat ### image lorem speak h: #анімація говоріння "lorem/mouth/smile.png" 0.15 "lorem/mouth/t1.png" 0.15 "lorem/mouth/t2.png" 0.15 "lorem/mouth/t3.png" 0.15 "lorem/mouth/t4.png" 0.15 "lorem/mouth/normal_t5.png" 0.15 repeat
Спочатку треба було зробити анімацію для очей, тобто створити зображення, у якому кадри анімації будуть змінюватись. Для реалістичного ефекту, я зробила заплющення очей випадковим. Анімацію рота я зробила так само, тільки її я поділила на 3 категорії: веселий, нейтральний, сумний. В них змінювались лише зображення самого рота, тобто у сумної анімації не було зображень, де рот в усмішці. Тепер, коли є анімації, можна розпочати створення самого спрайта.
image lorem h1 = LiveComposite( #стандартна весела поза (479, 1010), #тут розмір спрайта (0, 0), "lorem/base/l_hip.png", (0, 0), "lorem/base/r_hip.png", (0, 0), "lorem/base/head.png", (0, 0), "lorem blink", (0, 0), WhileSpeaking("lorem", "lorem speak h", "lorem/mouth/smile.png"), #перше - тег, друге - анімація рота, третє - рот без анімації (0, 0), "lorem/brows/normal.png", )
Вище ви можете побачити код, який показує вигляд готового спрайта. В ньому зображення йдуть у такому порядку: спочатку тіло (у Лорем тіло складається з двох частин), голова, очі, рот та брови. Рядок з ротом виглядає інакше, бо в ньому фігурують одночасно два зображення: анімація говоріння та звичайне зображення рота. Це означає, що коли персонаж говорить (з’являється текст його діалогу), то ми бачимо анімацію, але коли діалог завершується, то ми бачимо рот без анімації. Якщо ви хочете детальніше ознайомитись, як робити таку анімацію і як змусити персонажа говорити, то робила я код за цим туторіалом.
Також ви можете побачити, що в спрайта є своє ім’я, у моєму випадку це “lorem h1”. Воно зроблене не просто так, бо lorem - це тег зображення персонажа, а ось h1 - це сам спрайт. Для того, щоб дати персонажу тег, я написала image="lorem", коли створювала Лорем. Це дасть змогу легше керувати спрайтами, коли вони вже знаходяться на екрані.
define l = Character("Лорем", image="lorem") show lorem h1 d "Я раніше не чув такої казки, мабуть, це з чогось нового." l "З нової літератури? Можливо…" l h4 "Трохи сумно навіть, я думала, що в них буде щасливий кінець." l h3 "Не те щоб казки нашого дитинства були кращі, ха-ха."
На цьому прикладі емоція Лорем змінилась три рази і для цього не треба було прописувати “hide… show…”.
Для деяких фонів також була зроблена анімація. Більш помітна для всіх - дощ в одній зі сцен новели, а менш помітна - пил в кімнаті Оповідача, кімнаті Деяна та на головному меню. Тут все дуже просто, дощ та пил - це 4-5 зображень, які були анімовані в одному зображенні та просто накладені на фон.
Наступна задіяна анімація в новелі - анімація діалогових боксів. Її ви могли помітити, коли замість головних персонажів говорили Принцеса та Принц. Текстбокс спочатку ніби вистрибував, а потім просто плавав. Для ефекту вистрибування була зроблена анімація, яка накладалась на сам текстбокс, а ось для плавання я зробила анімацію зображення бокса, яке замінила, коли говорили Принцеса або Принц.
image textboxloremwarm: #анімація зображення subpixel True "loremtextbox" function WaveShader(amp=0.0, melt="horizontal", melt_params=(23.0,0.7,0.4), repeat='clamp') xalign 0.5 ### transform textboxjump: #анімація для вистрибування subpixel True ease_elastic 0.06 xoffset 20 yoffset 20 ease_elastic 0.06 xoffset -20 yoffset 20 ease_elastic 0.06 xoffset -20 yoffset -20 ease_elastic 0.06 xoffset 20 yoffset -20 ease_elastic 0.06 xoffset 0 yoffset 0 ### define lm = Character(kind=l, show_window_transform=textboxjump, window_background="textboxloremwarm")
Вище ви можете побачити, як це було зроблено. Тобто, для конкретної анімації я зробила нового персонажа, але для того, щоб не повторювати все те, що я писала для Лорем, я написала kind=l. Це означає, що персонаж такий самий, як персонаж l (в моєму випадку я так позначала Лорем), але я можу змінити моменти, які відрізняються від оригінального персонажа. Для ефекту плавання я використовувала такий шейдер. За інструкцією я створила зображення плаваючого текстбокса, яке потім вставила у визначення персонажа. P.s під час розробки я помітила, що для того, щоб анімація працювала, визначення персонажа треба робити в однаковому файлі з анімацією і лише після коду анімації.
Це, звісно ж, не все, що я робила у своєму коді, але, думаю, я описала все, що вам було б цікаво прочитати. Якщо у вас є чи будуть якісь питання до мене по моєму коду, то ви можете звернутись до мене в Діскорд! (@plyih)
Що далі?
В першу чергу, я виправлю орфографічні помилки в тексті (або вже це зробила). Але чи буде продовження проєкту\суттєві зміни? Зараз сказати важко. Поки в мене інші плани, які не стосуються розробки новел, але мені б хотілось як найскоріше повернутись до цього або навіть до конкретно цього проєкту. Якщо вам цікава подальша моя творчість, то ви можете підписатись на мій Ітч, щоб, можливо, в майбутньому отримати інформацію по моїм наступним або теперішнім проєктам. На цьому я завершую мій… девлог? Чесно, не знаю як краще це назвати, бо тут я накидала все, що спало на думку, але старалась написати цікаво та зрозуміло.
Дякую всім, хто пройшов та оцінив мою новелу і навіть просто тим, хто прочитав цей текст!
Comments
Log in with itch.io to leave a comment.
Дякую за девлог. Дуже цікаво.
Вау. З технічної точки зору ваша новела зачепила мене найбільше. Всі ці деталі, анімації, і все це створено однією людиною! Те, що розробка в соло - пекло, це чиста правда.
Дуже цікаво було прочитати так про кожен аспект гри, від ідеї до майбутніх планів. Дякую, що поділилися такими лайфгаками. Коли я дивилися на всі анміації в грі, я намагалися навіть не думати, бо це виглядало як чиста магія. Те, як створені спрайти... вау... (до речі, тепер баг зі спрайтами, котрий я вам кидали, стає зрозумілишим, я навіть не думали, що ваші персонажі зберігаються по частинами в коді : ) ).
Також ви дуже надихнули мене на створення саме девлогів. Я маю свій діскорд, де пишу довгі пости, однак більшість сфокусована саме на моїх думках, ніж на самому процесі розробки. Я точно щось винесли з цього девлогу)
Ще раз вітаю з 12 місцем, абсолютно заслужено, те, як ви розкрили тему (і її значення, котре було дано разом зі словом віртуальність. Вау).
Цей девлог наповнив мене натхненням, а "Чарівна казка" це показовий приклад того, що можливо все)
Дякую за вашу гру і девлог! Бажаю успіхів з наступними проєктами. Вже чекаю побачити, які челенджі ви візьмете на себе ще раз (і з того, що я бачу, ви можете виконати їх бездоганно). Ще раз дякую за гру і натхнення!
Також забули додати своє вау до того, як ви створювали фони. І те, що ви показали, що ховається під одягом Оповідача... Це розкриття персонажу на іншому рівні.
дякую!!🥺