Я деякий час працюю над 2d RPG, і я зрозумів, що прийняв деякі погані дизайнерські рішення. Зокрема, є декілька речей, які викликають у мене проблеми, тому мені було цікаво, які конструкції використовували інші люди для їх подолання.
За невеликого тла я почав працювати над цим у вільний час минулого літа. Я спочатку робив гру в C #, але приблизно 3 місяці тому вирішив перейти на C ++. Я хотів отримати хорошу обробку на C ++, оскільки минув деякий час, оскільки я активно використовував її, і подумав, що такий цікавий проект буде хорошим мотиватором. Я широко використовую бібліотеку підвищення та використовую SFML для графіки та FMOD для аудіо.
У мене написано неабияк коду, але я розглядаю можливість його списати і почати спочатку.
Ось основні проблемні питання, які я маю та хотів отримати деякі думки щодо належного способу вирішення їх чи вирішення інших.
1. Циклічні залежності Коли я робив гру в C #, мені не довелося переживати з цього приводу, оскільки це не проблема. Перехід на C ++, це стало досить головною проблемою, і змусило мене думати, що я, можливо, спроектував речі неправильно. Я не можу реально уявити, як роз'єднати свої заняття і все ще змусити їх робити те, що я хочу. Ось кілька прикладів ланцюга залежностей:
У мене є клас ефекту статусу. Клас має ряд методів (Apply / Unapply, Tick тощо), щоб застосувати його ефекти до символу. Наприклад,
virtual void TickCharacter(Character::BaseCharacter* character, Battles::BattleField *field, int ticks = 1);
Ця функція називатиметься кожного разу, коли персонаж, нанесений ефектом статусу, перетворюється на поворот. Це було б корисно для реалізації таких ефектів, як Regen, Poison тощо. Однак він також вводить залежності від класу BaseCharacter та класу BattleField. Природно, клас BaseCharacter повинен відслідковувати, які ефекти статусу на них зараз активні, так що це циклічна залежність. Battlefield повинен вести облік бойових сторін, і партійний клас має список базових характеристик, що вводить ще одну циклічну залежність.
2 - Події
У C # я широко використовував делегатів, щоб підключитися до подій на персонажах, полях бою тощо (наприклад, був делегат, коли змінювалося здоров'я персонажа, коли змінювалася статистика, коли додавались / видалялися ефект стану тощо) .) і графічні компоненти поля битви причепляться до цих делегатів для забезпечення їх ефектів. У C ++ я зробив щось подібне. Очевидно, що немає прямого еквівалента делегатам C #, тому натомість я створив щось подібне:
typedef boost::function<void(BaseCharacter*, int oldvalue, int newvalue)> StatChangeFunction;
і в моєму класі персонажів
std::map<std::string, StatChangeFunction> StatChangeEventHandlers;
всякий раз, коли статистика персонажа змінюється, я б повторював і закликав кожну StatChangeFunction на карті. Хоча це працює, я переживаю, що це поганий підхід до виконання справ.
3 - Графіка
Це велика річ. Це не пов’язано з графічною бібліотекою, яку я використовую, але це більше концептуальна річ. У C # я поєднав графіку з багатьма своїми класами, про які я знаю, це жахлива ідея. Бажаючи зробити це нероздільно, цього разу я спробував інший підхід.
Для того, щоб реалізувати свою графіку, я уявляв все, що стосується гри, як серія екранів. Тобто є заголовок, екран статусу символів, екран карти, екран інвентаря, бойовий екран, бойовий графічний інтерфейс, і я в основному можу скласти ці екрани один на одного, як потрібно для створення ігрової графіки. Незалежно від активного екрана є вхід гри.
Я створив диспетчер екранів, який буде натискати та з'являтися на екрані на основі введення користувача
Наприклад, якщо ви знаходилися на екрані карти (обробник вводу / візуалізатор для карти плитки) і натискали кнопку запуску, він надішле дзвінок менеджеру екрана, щоб натиснути екран головного меню через екран карти та позначити карту екран не малювати / оновлювати. Гравець буде орієнтуватися по меню, яке видасть більше команд керуючий екраном, як це підходить для натискання нових екранів на стек екрана, а потім з'являється, коли користувач змінює екрани / скасовує. Нарешті, коли гравець виходить з головного меню, я вискочу його та повернусь до екрана карти, зауважую, що його буде намальовано / оновлено та йду звідти.
Бойові екрани були б складнішими. У мене був би екран, який виступав би як фон, екран для візуалізації кожної сторони в битві та екран для візуалізації інтерфейсу користувача для битви. Користувальницький інтерфейс підключається до символьних подій і використовує ті, щоб визначити, коли потрібно оновлювати / перемальовувати компоненти інтерфейсу. Нарешті, кожна атака, яка має доступний сценарій анімації, вимагатиме додаткового шару для анімації перед тим, як вискочити з екрану. У цьому випадку кожен шар послідовно позначається як графічний і оновлений, і я отримую стек екранів, що обробляють мою бойову графіку.
Поки мені ще не вдалося змусити менеджера екранів працювати бездоганно, я думаю, що можу з певним часом. Моє запитання щодо цього, чи взагалі такий гідний підхід? Якщо це поганий дизайн, я хочу знати вже зараз, перш ніж вкладати занадто багато часу, роблячи всі екрани, які мені знадобляться. Як ви збираєте графіку для своєї гри?