Разработка игрового персонажа
Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 64 из 65.
Задание
СреднеСоздай персонажей ролевой игры: абстрактный Character, три класса, которые его расширяют, и способности, которым учатся персонажи.
Character в character.gd — это класс @abstract:
- Свойства:
character_name(из конструктора),level1,max_healthиhealth100.0,max_manaиmana50,strength,intelligenceиagility10,defense5иabilities— массивArray[Ability]. Значения здоровья имеют типfloat, остальные характеристики —int. - Сигнал
defeated(character_name: String). - Абстрактные методы
class_title() -> Stringиattack_power() -> float. level_up() -> String: уровень+1, максимальное здоровье+10, максимальная мана+5, сила, интеллект, ловкость и защита+1; здоровье и мана восстанавливаются до максимума. ВозвращаетNAME reached level N!.attack(target): выводитNAME attacks TARGET, затем возвращаетtarget.take_damage(attack_power()).take_damage(amount) -> float: урон равенamount - defense * 0.5, но составляет как минимум1.0; здоровье уменьшается на это значение, но не опускается ниже0.0. ВыводитNAME takes D damage (HP H), где все значения указаны с одним десятичным знаком, испускает сигналdefeated, если этот удар снизил здоровье до0, и возвращает урон.is_alive(): здоровье выше0.learn_ability(ability)добавляет способность вabilities.use_ability(index, target) -> float: если индекс находится вне диапазонаabilities, выводитNAME has no ability INDEXи возвращает0.0; иначе возвращает результат вызоваuse()этой способности._to_string():NAME the TITLE (level L): HP H/MAX, mana M/MAX, STR S, INT I, AGI A, DEF D; здоровье выводится с одним десятичным знаком.
Каждый подкласс вызывает конструктор родительского класса, затем задаёт свои начальные характеристики (для остальных остаются базовые значения), возвращает название класса из class_title() и переопределяет level_up() с помощью super():
Warrior: здоровье150.0, мана30, сила15, интеллект5, защита8; сила атакиstrength * 1.2; при повышении уровня также получает+2к силе и+10к максимальному здоровью (здоровье восстанавливается).Mage: здоровье80.0, мана150, сила5, интеллект20, защита3; сила атакиintelligence * 0.4; после обычной атаки восстанавливает5маны (не выше максимума); при повышении уровня также получает+2к интеллекту и+15к максимальной мане (мана восстанавливается).Rogue: здоровье100.0, мана60, сила12, интеллект8, ловкость18, защита4; сила атакиstrength * 0.5 + agility * 0.7; при повышении уровня также получает+2к ловкости.
Ability в ability.gd: конструктор принимает ability_name, mana_cost (int) и damage (float). use(user, target) -> float выводит USER does not have enough mana for ABILITY и возвращает 0.0, если маны пользователя меньше стоимости способности. В противном случае списывает ману, выводит USER casts ABILITY on TARGET и возвращает target.take_damage(damage + user.intelligence * 0.5).
Предоставленный код подключается к сигналу defeated каждого персонажа и выводит NAME is defeated!. Для этого ввода:
hero warrior|Aragorn
hero rogue|Orc
attack Aragorn|Orc
attack Orc|Aragorn
level Aragorn
status Aragornвывод будет таким:
Aragorn attacks Orc
Orc takes 16.0 damage (HP 84.0)
Orc attacks Aragorn
Aragorn takes 14.6 damage (HP 135.4)
Aragorn reached level 2!
Aragorn the Warrior (level 2): HP 170.0/170.0, mana 35/35, STR 18, INT 6, AGI 11, DEF 9Твой код размести в файлах character.gd, warrior.gd, mage.gd, rogue.gd и ability.gd. В main.gd находится предоставленный код ввода/вывода, его нельзя редактировать.
Попробуйте сами
extends Node
func _ready():
# Предоставленный код ввода/вывода: оставьте его без изменений
var heroes := {}
var line := OS.read_string_from_stdin()
while line != "":
var parts := line.split(" ", true, 1)
var f: PackedStringArray = parts[1].split("|") if parts.size() > 1 else PackedStringArray()
match parts[0]:
"hero":
var hero: Character
match f[0]:
"warrior":
hero = Warrior.new(f[1])
"mage":
hero = Mage.new(f[1])
"rogue":
hero = Rogue.new(f[1])
hero.defeated.connect(func(who): print(who, " is defeated!"))
heroes[f[1]] = hero
"learn":
heroes[f[0]].learn_ability(Ability.new(f[1], int(f[2]), float(f[3])))
"attack":
heroes[f[0]].attack(heroes[f[1]])
"cast":
heroes[f[0]].use_ability(int(f[1]), heroes[f[2]])
"level":
print(heroes[f[0]].level_up())
"status":
print(heroes[f[0]])
line = OS.read_string_from_stdin()
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово selfМетодыСвойстваКонструктор (_init)Повторение: простой калькулятор4Полиморфизм
Переопределение методов: повторениеУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовПовторение — калькулятор фигур7Сигналы
Что такое сигнал?Объявление и отправкаПодключение к сигналамСигналы с аргументамиПовторение — система здоровья10Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»2Свойства классов
Переменные экземпляра и классаСтатические функцииСеттеры свойствГеттеры свойствПриватность по соглашениюПовторение — менеджер банковского счёта5Инкапсуляция
Открытые и закрытые членыПроверка данных с помощью сеттеровСокрытие информацииСвойства только для чтенияПовторение — система учета студентов8Продвинутые концепции ООП
Композиция и наследованиеВнутренние классыУзлы как компонентыRefCounted и NodeПеречисления в классах11Проект: Управление библиотекой
Обзор проектаКлассы книг и пользователей3Наследование
Основы наследованияКлючевое слово superПереопределение методовЦепочки наследованияПроверка типов с помощью isПовторение — иерархия сотрудников6Специальные методы
Введение в виртуальные методыМетод _to_stringПользовательские итераторыПовторение: пользовательский список9Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн «Одиночка»Паттерн «Фабрика»Паттерн «Наблюдатель»Паттерн «Стратегия»12Итоговые задания
Платформа электронного обученияБанковская системаРазработка игрового персонажаСервис аренды автомобилейПотренируйтесь самостоятельно: Онлайн-компилятор GDScript