# Розробка карткової гри з відкритим кодом OpenLegends [OpenLegends](https://github.com/openlegends) - це проект реалізації вільного рушія та інтерфейсу багатокористувацької карткової гри [The Elder Scrolls Legends](https://bethesda.net/en/game/legends), в першу чергу орієнтованого на браузерний формат з використанням технологій HTML5. Початковий код реалізовано мовою PHP 8, з використанням пакетного менеджеру Composer. Причина обрання цієї мови - наявний досвід та переконання що її можливостей буде цілком достатньо для опису ігрової логіки. Також це зручно для інтеграції веб-застосунків. В процесі, можливо буде виконано адаптацію для десктопів на Rust з використанням QT, хоча більш ймовірною буде імплементація на Electron. Окремо хотілось би мати альтернативу для CLI та протоколу [Gemini](https://devzone.org.ua/post/protokol-gemini-iak-legka-alternativa-http), з підтримкою графіки ASCII. Враховуючи функціональний потенціал оригінальної гри - завдання для однієї людини не тривіальне, утім мені все ж цікаво спробувати здійснити цю давню мрію і можливо, за цей час хтось також долучитися до розробки! ## Структура Проект ділиться на три окремі гілки розробки: * `core-php` - базовий інтерфейс рушія та набір абстрактних класів ядра * `asset-php` - ігрові набори: карти, ігрові режими та інші компоненти, що реалізують `core-php` * *сервер* - багатокористувацький інтерфейс, ймовірно буде реалізований на базі фреймворку Symfony ## Ядро (core-php) Мета [core-php](https://github.com/openlegends/core-php) - відділити будь яку ігрову логіку від базової структури рушія, що дозволить робити менш часті оновлення ядра (зберігаючи сумісність як найдовше) та активніше розвивати зовнішні інтерфейси - наприклад, ігрові набори, що реалізують певну його версію. Наразі перебуває на стадії прототипу, для встановлення використовується остання версія з репозиторія: ``` composer require openlegends/core:dev-main ``` З появою першої стабільної версії, буде виконано перехід на [Семантичні версії](https://semver.org/lang/uk/) релізів. По суті, ядро складається з класів двох типів - Інтерфейси, що власне описують можливості класів карт, гравців, ігрових сесій тощо, та Абстрактні класи - що частково реалізують ці інтерфейси та використовуються ігровими наборами. Здебільшого, Абстрактні класи містять у собі такі універсальні методи як Сетери і Гетери, але можуть містити й інші - для запобігання їх дублікації в наборах (де наприклад тільки карткових класів може бути близько тисячі). Також, Абстрактні класи містять деякі абстрактні методи, які вимагають специфічної реалізації окремим класом: наприклад, дія карти, або гравця, яка в TES Legends мало чи не описує всю ігрову логіку в одному акті. ## Ігрові набори (asset-php) Ігрові набори представлені в репозиторії [asset-php](https://github.com/openlegends/asset-php) і описують ігрову логіку. Сюди входить оголошення та опис кожної карти, гравця, режиму гри та їх можливостей. Ігровий набір у своєму релізі має орієнтуватись на певну версію ядра `core-php`, що спростить розробку та супровід окремо взятого ігрового серверу, який реалізує певний набір. В розробці використовується остання версія репозиторія, яка наразі не містить стабільних релізів: ``` composer require openlegends/asset:dev-main ``` Дана версія включає тільки умовний тестовий набір класів, що складається з декількох умовних гравців (Player1, Player2), карт (Mouse, Goblin, Rat) та режиму гри з двох гравців (Arena), достатніх для тестування `core-php` та майбутнього ігрового серверу. Після появи першого стабільного релізу ядра, можна буде створити реальний набір, оскільки ядро перебуває в розробці а інтерфейс може змінюватись, у тестовому наборі не доречно обслуговувати більше трьох карт. Говорячи про реліз, ймовірно, це буде копія набору TES Legends, оскільки розрахунок нового ігрового балансу - це окреме завдання з області математики і потребує немало часу, включно з тестуванням реальними гравцями. Ігрові дані для набору можна подивитись на сайті [TES Legends Pro](https://teslegends.pro) а також запозичити звідти графіку. По зрозумілим причинам, розмістити такі дані в рамках проекту OpenLegends не є доречним, але це не заважає розгорнути альтернативний форк `asset-php`. ## Приклади роботи Завдання будь якого рушія - спрощення розробки гри. Отже, для кращого розуміння що собою являє рушій OpenLegends, розглянемо декілька найпростіших прикладів на основі тестового набору. У даному матеріалі не будуть описані інші можливості, враховуючи що вони можуть різнитися в новіших версіях. ### Взаємодія карт ``` card( $rat ); var_dump( $rat->getHealth() ); ``` ### Картковий пул Використовується здебільшого в ігрових сесіях для організації карткових наборів, наприклад колоди, стопки скиду, карт в руці, тощо: ``` addCard( new \OpenLegends\Asset\Test\Card\Goblin() ); $deck->addCard( new \OpenLegends\Asset\Test\Card\Mouse() ); $deck->addCard( new \OpenLegends\Asset\Test\Card\Rat() ); var_dump( $deck->getRandomCard()->getName() ); ``` ### Ігрова сесія На реальному сервері, гра та її учасники створюються інтерактивно через запити графічного інтерфейсу. У тестовому наборі, сесія кожного гравця ініціюється [в конструкторі його класу](https://github.com/openlegends/asset-php/blob/main/src/Test/Game/Player/Player1.php) автоматично, реалізуючи абстрактний клас ядра `\OpenLegends\Core\Abstract\Game\Player`, що включає готові набори карт, об'єкт користувача, статус здоров'я тощо. Після того, як об'єкт або клас гравця з картковими пулами було створено, ці дані передаються до об'єкту нової гри та ініціюється сценарій старту: ``` addPlayer( new OpenLegends\Asset\Test\Game\Player\Player1() ); $game->addPlayer( new OpenLegends\Asset\Test\Game\Player\Player2() ); $game->start(); ``` Інші приклади (зокрема специфіка роботи ігрового серверу через веб-сокети, взаємодія з базами даних, створення інтерактивних інтерфейсів) вартують розгляду в рамках окремої гілки серії. Сподіваюсь, на даному етапі, мені вдалось описати загальний статус та принципи розробки проекту. Кому цікава реалізація TES Legends з відкритим кодом - ласкаво просимо до OpenLegends! ## Посилання * [Сторінка на GitHub](https://github.com/openlegends)