У якийсь момент двигун ОБОВ'ЯЗКОВА спеціалізуватися та знати речі про гру. Я зійду тут по дотичній.
Візьміть ресурси в RTS. Одна гра може мати Credits
і Crystal
іншу, Metal
іPotatoes
Ви повинні правильно використовувати поняття OO і переходити до макс. повторне використання коду. Зрозуміло, що Resource
тут існує концепція .
Тож ми вирішуємо, що ресурси мають таке:
- Гачок в основній петлі для збільшення / зменшення
- Спосіб отримання поточної суми (повертає
int
)
- Спосіб віднімання / додавання довільно (гравці, що передають ресурси, покупки ....)
Зауважте, що це поняття Resource
може означати вбивства або очки в грі! Це не дуже потужно.
Тепер давайте подумаємо про гру. Ми можемо сортувати валюту, торгуючи копійками і додаючи до результату десяткові крапки. Що ми не можемо зробити - це "миттєві" ресурси. Скажімо, "генерація електромережі"
Скажімо, ви додаєте InstantResource
клас подібними методами. Ви зараз (починаєте) забруднювати двигун ресурсами.
Проблема
Давайте знову візьмемо приклад РТС. Припустимо, гравець все, що пожертвує Crystal
іншим гравцем. Ви хочете зробити щось на кшталт:
if(transfer.target == engine.getPlayerId()) {
engine.hud.addIncoming("You got "+transfer.quantity+" of "+
engine.resourceDictionary.getNameOf(transfer.resourceId)+
" from "+engine.getPlayer(transfer.source).name);
}
engine.getPlayer(transfer.target).getResourceById(transfer.resourceId).add(transfer.quantity)
engine.getPlayer(transfer.source).getResourceById(transfer.resourceId).add(-transfer.quantity)
Однак це справді досить безладно. Це загальне призначення, але безладно. Хоча це нав'язує, resourceDictionary
що означає, що тепер ваші ресурси мають мати імена! І це на кожного гравця, тому ви більше не можете мати ресурси команди.
Це "занадто багато" абстракції (не геніальний приклад, я визнаю), натомість ви повинні вдаритись до точки, коли ви приймаєте, що у вашій грі є гравці та кристал, тоді ви можете просто мати (наприклад)
engine.getPlayer(transfer.target).crystal().receiveDonation(transfer)
engine.getPlayer(transfer.source).crystal().sendDonation(transfer)
З класом Player
і класом , CurrentPlayer
де CurrentPlayer
«S crystal
об'єкт буде автоматично показувати матеріал на ІЛС для передачі / відправки пожертвувань.
Це забруднює двигун кристалом, пожертвування кристала, повідомлення на HUD для поточних гравців і все таке. Одночасно швидше і простіше читати / записувати / підтримувати (що важливіше, оскільки це не суттєво швидше)
Заключні зауваження
Справа з ресурсом не є блискучою. Я сподіваюся, що ви все ще можете побачити сенс. Якщо що-небудь я продемонстрував, що "ресурси не належать до двигуна", як те, що потрібно конкретній грі, і те, що стосується всіх понять про ресурси, це ДУЖЕ різні речі. Зазвичай ви знайдете 3 (або 4) "шари"
- "Основне" - це визначення підручника в двигуні, це графік сцени з гачками подій, він стосується шейдерів та мережевих пакетів та абстрактне поняття про гравців
- "GameCore" - Це досить загальне для типу гри, але не для всіх ігор - наприклад, ресурси в RTS або боєприпаси в FPS. Логіка гри тут починає проникати. Саме тут було б наше раніше уявлення про ресурси. Ми додали ці речі, які мають сенс для більшості ресурсів RTS.
- "GameLogic" ДУЖЕ специфічний для фактичної гри, що робиться. Ви знайдете змінні з іменами, як
creature
або ship
або squad
. Використання успадкування ви отримаєте класи , які охоплюють всі 3 шари (наприклад , Crystal
це Resource
який є GameLoopEventListener
скаже)
- "Активи" - це марно для будь-якої іншої гри. Візьмемо для прикладу комбіновані AI-скрипти в періоді напіввиведення 2, вони не збираються використовувати в RTS з тим же двигуном.
Створення нової гри зі старого двигуна
Це ДУЖЕ поширене. Етап 1 - це видобуток 3 та 4 шарів (і 2, якщо гра ВЕЛИКОБІЛЬКО іншого типу) Припустимо, ми робимо RTS зі старої RTS. У нас ще є ресурси, тільки не кришталь і інше - тому базові класи в шарах 2 і 1 все ще мають сенс, все те, про яке кристал посилається в 3 і 4, можна відкинути. Так ми і робимо. Однак ми можемо перевірити це як орієнтир того, що ми хочемо зробити.
Забруднення в шарі 1
Це може статися. Абстракція та продуктивність - вороги. Наприклад, UE4 забезпечує безліч оптимізованих випадків композиції (тому, якщо ви хочете, щоб X і Y хтось написав код, який робить X і Y разом дуже швидко - він знає, що це робить і те й інше), і як результат, дійсно досить великий. Це не погано, але це забирає багато часу. Шар 1 визначає такі речі, як "як ви передаєте дані в шейдери" та як анімувати речі. ЗРОБИТИ це найкращим чином для вашого проекту, ЗАВЖДИ добре. Просто спробуйте і плануйте майбутнє, повторно використовуючи код - ваш друг, успадкуйте там, де це має сенс.
Класифікація шарів
ОСТАННЯ (обіцяю) не бійтеся шарів. Двигун - це архаїчний термін із старих часів трубопроводів з фіксованою функцією, де двигуни в значній мірі працювали так само графічно (і в результаті мали багато спільного) програмований трубопровід повернув це на голову і як такий "шар 1" став забрудненим. будь-яких ефектів розробники хотіли досягти. AI був відмітною особливістю (через безліч підходів) двигунів, тепер це AI та графіка.
Ваш код не повинен бути поданий у цих шарах. Навіть у відомого двигуна Unreal є МНОГО різних версій, кожна специфічна для іншої гри. Мало файлів (окрім подібних структур даних), які б не змінилися. Це добре! Якщо ви хочете створити нову гру з іншої, це займе більше 30 хвилин. Ключ - спланувати, знати, які біти копіювати та вставляти, а що залишити.