Menu
CoddyTech

Tworzenie postaci do gry

Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 64 z 65.

challenge icon

Wyzwanie

Średni

Zbuduj 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), level 1, max_health i health 100.0, max_mana i mana 50, strength, intelligence i agility 10, defense 5 oraz abilities, tablica typu Array[Ability]. Wartości zdrowia są typu float, a pozostałe statystyki typu int.
  • Sygnał defeated(character_name: String).
  • Metody abstrakcyjne class_title() -> String i attack_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. Zwraca NAME reached level N!.
  • attack(target): wypisuje NAME attacks TARGET, a następnie zwraca target.take_damage(attack_power()).
  • take_damage(amount) -> float: obrażenia wynoszą amount - defense * 0.5, ale co najmniej 1.0; zdrowie zmniejsza się o tę wartość i nigdy nie spada poniżej 0.0. Metoda wypisuje NAME takes D damage (HP H), każdą wartość z jednym miejscem po przecinku, emituje sygnał defeated, gdy ten cios obniży zdrowie do 0, i zwraca wartość obrażeń.
  • is_alive(): zdrowie powyżej 0. learn_ability(ability) dodaje zdolność do abilities.
  • use_ability(index, target) -> float: jeśli indeks jest poza zakresem abilities, wypisuje NAME has no ability INDEX i zwraca 0.0; w przeciwnym razie zwraca wartość zwróconą przez use() 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: zdrowie 150.0, mana 30, siła 15, inteligencja 5, obrona 8; siła ataku strength * 1.2; przy awansie dodatkowo siła +2 i maksymalne zdrowie +10 (zdrowie zostaje uzupełnione).
  • Mage: zdrowie 80.0, mana 150, siła 5, inteligencja 20, obrona 3; siła ataku intelligence * 0.4; po zwykłym ataku odzyskuje 5 many (nigdy ponad maksimum); przy awansie dodatkowo inteligencja +2 i maksymalna mana +15 (mana zostaje uzupełniona).
  • Rogue: zdrowie 100.0, mana 60, siła 12, inteligencja 8, zręczność 18, obrona 4; siła ataku strength * 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 Aragorn

wyjś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 9

Twó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

Poćwicz samodzielnie: Kompilator GDScript online