COOKIES

This site may be using cookies to melk you with your own data. I, ben0bi, am not the owner of this web service and I also do not maintain their servers. But the EU and the owner of this service think, that the user (me) has the responsibility to inform the consumer (you), that this website uses cookies. Again: I, ben0bi, NEVER use cookies. I am not responsible for the setup of this web service. I just present some information here and do not intend to spy on you for whatever reason ever. But (also again), I do not host this website nor do I maintain any servers related to this website nor do I benefit from using the cookies maintained from this service. I hereby give the responsibility for using cookies on blogspot back to the owners of blogspot.

Dienstag, 17. Mai 2022

GODOT: HearthBar


Eine Lebensleiste aus Herzen ist in fast jedem Zelda vorhanden. Hier erkläre ich, wie ich das in Godot gelöst habe. Es hat pro Herz fünf Einstellungen: Empty, Quarter, Half, FourQuarter und Full. Im Bild siehst du Full, Half und Empties.

Erstmal solltest du das folgende Spritesheet mit all den Herzen herunterladen und in deinem Assets-Ordner einfügen. In Godot, klicke das Bild an und dann oben links neben "Szene" auf "Importieren". Deaktiviere das Filter-Flag und reimporte das Bild.

Dieses Tutorial ist eine "Erweiterung" von diesem Tutorial. (Auf Englisch)

Rechtsklick & Speichern bitte...

Nun brauchen wir ein Objekt, welches ein Herz enthält. Klicke auf "Szene"->"Neue Szene" und stelle ein "Sprite" als Root-Node ein.

Ich habe es "Sprite_Hearth" genannt.

Lade das heruntergeladene Spritesheet als Textur von Sprite_Hearth (Bild im Inspektor auf "Textur" ziehen)

Das Spritesheet hat 5 12x12Pixel Bilder.

Stelle im Inspektor unter "Region" die Werte "w" und "h" auf jeweils 12 und "Region enabled" auf true.

Speichere die Szene als "HearthContainer.tscn" ab.

In deiner Main-Szene:
(Du hast hoffentlich ein CanvasLayer für dein GUI)

Hänge eine Node ("Node") an dein CanvasLayer. Positioniere die Node oben links im Bildschirm.
Hänge daran ein Script mit folgendem Inhalt:

extends Node

# wir laden die vorher erstellte Szene in eine Variable
var hearthTile = preload("res://Assets/GUI/HearthPack/HeartContainer.tscn")

# deletes all child nodes from that node
func delete_all_child_nodes():
  for n in self.get_children():
    self.remove_child(n)
    n.queue_free()

# erstelle alle herzcontainer und fülle sie
func add_hearts(var player):
  # erstmal werden alle child-nodes gelöscht und danach neu aufgebaut
  delete_all_child_nodes()

  # damit herz nicht aus dem bildschirm herausragt gibt
  # es initial die position 6,6 statt 0,0
  var xpos=6
  var ypos=6
  # q braucht es für die y-linien
  var q=0
  # volle herzen sind multiplikanten von 4
  var healthdivided = int(player.health*0.25)

  # welchen status hat das letzte gefüllte herz?
  var healthmod= int(player.health) % 4

  for i in player.max_health*0.25:
    var hc= hearthTile.instance() # erstelle eine neue herzcontainer instanz
    self.add_child(hc) # hänge sie an die eigene node an.
    # setze die position
    hc.position.x=xpos
    hc.position.y = ypos
    # fülle die das aktuelle herz
    if i<healthdivided:
      # full hearts
      hc.region_rect.position.x=4*12.0 # letzte position
    elif i==healthdivided:
      hc.region_rect.position.x=healthmod*12 # mit mod herausgefundene position
    else:
      # empty hearts
      hc.region_rect.position.x=0

    q+=1
    xpos+=12 #setze die neue x position
    # reset a line down
    if q>=10:
      q=0
      xpos=6
      ypos+=12

Es geschieht folgendes: Jedes mal, wenn das Signal "on_stats_changed" mit dem Player als Parameter emittiert wird, werden erstmal alle Herzen in der Node (mit dem Skript) gelöscht. Danach wird auf einer Linie durchgegangen und maximal 10 (zehn) Herzen erstellt. Wenn es mehr als 10 Herzen hat, wird danach eine Linie runtergegangen.
Bei der Erstellung der Herzen wird geprüft, ob das Herz gefüllt oder leer ist. Wenn es das letzte Herz nach den Gefüllten ist, wird noch geprüft, welche Region des Spritesheets benutzt wird, ansonsten ist die Region xy = 0,0 für ein leeres Herz oder 4*12,0 für ein volles Herz.
Die Funktion add_hearts muss nun nur noch bei jeder Änderung des Health-Statuses aufgerufen werden. Das macht man am besten mit Signalen.

Dein Player Script sollte noch folgendes enthalten:
var health = 12 # 3*4 = 3 hearts
var max_health = 12 ...
signal on_stats_changed
Und in allen Funktionen des Players, welche die die health-Variable verändern am Ende noch:
emit_signal("on_stats_changed", self)

Mit self wird der Player an das Signal übergeben, so dass man die Health-Variable auslesen kann. Konnekte nun noch das Signal on_stats_changed im Inspektor mit dem Hearts-Script in der (unbenannten) Node und schreibe dazu diese eine Linie Code (der Funktionsname wird automatisch generiert):
# the player emits a signal when the stats change.
func _on_Player_player_stats_changed(var player):
  add_hearts(player)

Fertig.
Also, bei mir gehts... ;)

Keine Kommentare:

Kommentar veröffentlichen