Menu
CoddyTech

פיתוח דמות במשחק

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 64 מתוך 65.

challenge icon

אתגר

בינוני

בנו את הדמויות של משחק תפקידים: Character מופשטת, שלוש מחלקות שיורשות ממנה, ויכולות שהדמויות לומדות.

Character בקובץ character.gd היא מחלקה מסוג @abstract:

  • מאפיינים: character_name (מהבנאי), level 1, max_health ו-health 100.0, max_mana ו-mana 50, strength, intelligence ו-agility 10, defense 5, ו-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()

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר GDScript אונליין