Разработка игрового персонажа
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 90 из 91.
Задание
ЛегкоДавайте создадим систему Разработки игровых персонажей, в которой различные классы персонажей сражаются, используя уникальные способности. Вы создадите иерархию персонажей с системой опыта и уровней, демонстрируя, как наследование, интерфейсы, трейты и инкапсуляция работают вместе в игровом контексте.
Вы организуете свой код в шести файлах:
Ability.php— Определите интерфейсAbilityс двумя методами:getName(): stringиuse(Character $target): string. Этот контракт гарантирует, что все способности можно использовать единообразно, независимо от их конкретных эффектов.CombatLogger.php— Создайте трейтCombatLogger, который предоставляет методlogAction(string $action): string. Этот метод должен возвращать строку действия с префиксом"[COMBAT] ". Персонажи будут использовать этот трейт для единообразного форматирования своих боевых сообщений.Character.php— Подключите файлы Ability и CombatLogger. Создайте абстрактный классCharacter, который использует трейтCombatLogger. Используйте продвижение свойств в конструкторе (constructor promotion) дляname(string, public readonly). Добавьте приватные свойства дляhealth(int, начальное значение 100),level(int, начальное значение 1) иexperience(int, начальное значение 0). Реализуйте:getHealth(): intиgetLevel(): int— геттеры для приватных свойствtakeDamage(int $amount): void— уменьшает здоровье, но не ниже 0heal(int $amount): void— увеличивает здоровье, но не выше 100gainExperience(int $xp): string— добавляет XP; если опыт достигает 100 или более, уровень повышается (сбросьте XP до 0, увеличьте уровень, восстановите 20 HP), верните"{$this->name} leveled up to {$this->level}!"; в противном случае верните"{$this->name} gained {$xp} XP"isAlive(): bool— возвращает true, если здоровье больше 0abstract getSpecialAbility(): Ability— каждый тип персонажа предоставляет свою уникальную способностьattack(Character $target): string— наносит 10 единиц урона цели, используетlogAction()для возврата"[COMBAT] {$this->name} attacks {$target->name} for 10 damage"
Warrior.php— Подключите файл Character. Создайте классWarrior, расширяющийCharacter. РеализуйтеgetSpecialAbility(), чтобы возвращать анонимный класс, реализующийAbility:getName()возвращает"Shield Bash"use()наносит 25 единиц урона и возвращает"[COMBAT] Shield Bash hits {$target->name} for 25 damage!"(используйтеlogAction()трейта)
Mage.php— Подключите файл Character. Создайте классMage, расширяющийCharacter. РеализуйтеgetSpecialAbility(), чтобы возвращать анонимный класс, реализующийAbility:getName()возвращает"Fireball"use()наносит 35 единиц урона и возвращает"[COMBAT] Fireball engulfs {$target->name} for 35 damage!"
main.php— Подключите файлы Warrior и Mage. Вы получите два входных значения: данные персонажей (JSON) и последовательность боевых действий (JSON).Формат JSON персонажей:
[{"type": "warrior", "name": "Thorin"}, {"type": "mage", "name": "Gandalf"}]Формат JSON действий:
[{"action": "attack", "attacker": 0, "target": 1}, {"action": "special", "attacker": 1, "target": 0}, {"action": "xp", "character": 0, "amount": 100}, {"action": "status", "character": 0}]Создайте всех персонажей и сохраните их в массиве (индекс 0, 1 и т. д.). Обработайте каждое действие:
"attack"— Персонаж по индексу атакующего атакует цель; выведите результат"special"— Персонаж использует свою специальную способность на цели; выведите результат"xp"— Персонаж получает опыт; выведите результат"heal"— Персонаж лечится на указанную величину; выведите"{$character->name} healed to {$character->getHealth()} HP""status"— Выведите"{$character->name} - Level {$character->getLevel()}, HP: {$character->getHealth()}, Alive: {$alive}"(где$aliveэто'Yes'или'No')
Выводите каждый результат на новой строке.
Эта система демонстрирует, как абстрактные классы определяют общее поведение персонажей, интерфейсы гарантируют, что способности следуют единому контракту, трейты обеспечивают повторно используемую функциональность логирования, а анонимные классы создают уникальные реализации способностей, не загромождая кодовую базу одноразовыми классами.
Попробуйте сами
<?php
require_once 'Warrior.php';
require_once 'Mage.php';
// Чтение входных данных
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));
// Парсинг JSON-данных
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);
// TODO: Создать массив для хранения объектов персонажей
$characters = [];
// TODO: Пройти циклом по $charactersData и создать объекты Warrior или Mage
// на основе поля "type", сохранить их в массив $characters
// TODO: Обработать каждое действие в $actionsData
// Обработать следующие типы действий:
// - "attack": Персонаж по индексу атакующего атакует цель; вывести результат
// - "special": Персонаж использует getSpecialAbility()->use() на цель; вывести результат
// - "xp": Персонаж получает опыт; вывести результат
// - "heal": Персонаж лечится; вывести "[name] healed to [health] HP"
// - "status": Вывести "[name] - Level [level], HP: [health], Alive: [Yes/No]"
?>Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy15Финальные испытания
Платформа онлайн-обученияБанковская системаРазработка игрового персонажаСервис аренды транспорта