Tworzenie postaci do gry
Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 64 z 65.
Wyzwanie
ŚredniZbuduj postacie do gry fabularnej: abstrakcyjną klasę Character, trzy klasy, które ją rozszerzają, oraz zdolności, których uczą się postacie.
Character w pliku character.gd jest klasą @abstract:
- Właściwości:
character_name(z konstruktora),level1,max_healthihealth100.0,max_manaimana50,strength,intelligenceiagility10,defense5orazabilities, tablica typuArray[Ability]. Wartości zdrowia są typufloat, a pozostałe statystyki typuint. - Sygnał
defeated(character_name: String). - Metody abstrakcyjne
class_title() -> Stringiattack_power() -> float. level_up() -> String: poziom+1, maksymalne zdrowie+10, maksymalna mana+5, siła, inteligencja, zręczność i obrona+1; zdrowie i mana zostają uzupełnione do maksimum. ZwracaNAME reached level N!.attack(target): wypisujeNAME attacks TARGET, a następnie zwracatarget.take_damage(attack_power()).take_damage(amount) -> float: obrażenia wynosząamount - defense * 0.5, ale co najmniej1.0; zdrowie zmniejsza się o tę wartość i nigdy nie spada poniżej0.0. Metoda wypisujeNAME takes D damage (HP H), każdą wartość z jednym miejscem po przecinku, emituje sygnałdefeated, gdy ten cios obniży zdrowie do0, i zwraca wartość obrażeń.is_alive(): zdrowie powyżej0.learn_ability(ability)dodaje zdolność doabilities.use_ability(index, target) -> float: jeśli indeks jest poza zakresemabilities, wypisujeNAME has no ability INDEXi zwraca0.0; w przeciwnym razie zwraca wartość zwróconą przezuse()zdolności._to_string():NAME the TITLE (level L): HP H/MAX, mana M/MAX, STR S, INT I, AGI A, DEF D, zdrowie z jednym miejscem po przecinku.
Każda podklasa wywołuje konstruktor klasy nadrzędnej, a następnie ustawia własne statystyki początkowe (pozostałe zachowują wartości bazowe), zwraca nazwę klasy z class_title() i nadpisuje level_up() za pomocą super():
Warrior: zdrowie150.0, mana30, siła15, inteligencja5, obrona8; siła atakustrength * 1.2; przy awansie dodatkowo siła+2i maksymalne zdrowie+10(zdrowie zostaje uzupełnione).Mage: zdrowie80.0, mana150, siła5, inteligencja20, obrona3; siła atakuintelligence * 0.4; po zwykłym ataku odzyskuje5many (nigdy ponad maksimum); przy awansie dodatkowo inteligencja+2i maksymalna mana+15(mana zostaje uzupełniona).Rogue: zdrowie100.0, mana60, siła12, inteligencja8, zręczność18, obrona4; siła atakustrength * 0.5 + agility * 0.7; przy awansie dodatkowo zręczność+2.
Ability w pliku ability.gd: konstruktor przyjmuje ability_name, mana_cost (int) i damage (float). use(user, target) -> float wypisuje USER does not have enough mana for ABILITY i zwraca 0.0, gdy mana użytkownika jest niższa niż koszt. W przeciwnym razie pobiera manę, wypisuje USER casts ABILITY on TARGET i zwraca target.take_damage(damage + user.intelligence * 0.5).
Dostarczony kod łączy sygnał defeated każdej postaci i wypisuje NAME is defeated!. Dla tego wejścia:
hero warrior|Aragorn
hero rogue|Orc
attack Aragorn|Orc
attack Orc|Aragorn
level Aragorn
status Aragornwyjście to:
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 9Twój kod umieść w plikach character.gd, warrior.gd, mage.gd, rogue.gd i ability.gd. Plik main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
extends Node
func _ready():
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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()
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe selfMetodyWłaściwościKonstruktor (_init)Powtórka – prosty kalkulator4Polimorfizm
Ponowne omówienie przesłaniania metodDuck typingKlasy i metody abstrakcyjneProjektowanie interfejsówPowtórzenie – kalkulator kształtów7Sygnały
Czym jest sygnał?Deklarowanie i emitowanieŁączenie z sygnałamiSygnały z argumentamiPodsumowanie — system zdrowia10Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu2Właściwości klas
Zmienne instancji a zmienne statyczneFunkcje statyczneSettery właściwościGettery właściwościPrywatne z konwencjiPodsumowanie — menedżer kont bankowych5Enkapsulacja
Elementy publiczne i prywatneWalidacja za pomocą setterówUkrywanie informacjiWłaściwości tylko do odczytuPodsumowanie – system ewidencji uczniów8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieKlasy wewnętrzneWęzły jako komponentyRefCounted a NodeTypy wyliczeniowe w klasach11Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superNadpisywanie metodŁańcuchy dziedziczeniaSprawdzanie typów za pomocą isPodsumowanie – hierarchia pracowników6Metody specjalne
Wprowadzenie do metod wirtualnychMetoda _to_stringWłasne iteratoryPodsumowanie — własna lista9Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy12Wyzwania końcowe
Platforma e-learningowaSystem bankowyTworzenie postaci do gryWypożyczalnia pojazdówPoćwicz samodzielnie: Kompilator GDScript online