Einzelnes Tile verändern

0 Replies, 505 Views

Ein einzelnes Tile einer Tilemap zur Laufzeit ändern

I. Warum?
Es gibt Situationen, da möchte man während der Laufzeit seines Spiels das eine oder andere Tile seiner Tilemap in seiner Modulation, also Farbe oder Transparenz, ändern. Ganz speziell schreibe ich dies hier über folgende Situation: Mein Spieler bewegt sich durch eine kaputte und graue Welt. Überall dort wo der Spieler sich befindet, soll die Welt um ihn herum aber hell und grün sein.

II. Problem!
Wenn Du Dir die TileData eines Tiles (einer Cell) für eine bestimmte Zelle holst und die Eigenschaft "modulate" (die Eigenschaft ist vom Typ "Color") änderst, ändern sich alle Tiles in der Map die Du mit diesem Tile aus Deinem Tileset gesetzt hast. Wie man an ein einzelnes Tile der Map kommt und dessen TileData bearbeitet soll nicht Teil dieser Exkursion sein.

III. Lösungsansatz
Der erste Layer der Tilemap beinhaltet die kaputte, graue Welt und auf dem zweiten Layer liegt die grüne, helle Welt. Für den zweiten Layer habe ich in der Option "Modulate" das Alpha der Farbe auf 10 gesetzt. Setze es nicht auf 0, dann bekommst Du es nie wieder über diesen Wert hinaus. Desweiteren solltest Du wissen dass die Werte für "r", "g" und "b" zewischen 0.0 und 1.0 angesiedelt sein müssen, während "a" (Alpha, also Transparenz) einen Wert zwischen 1.0 und 255.0 erwartet. Warum das so ist? Keine Ahnung. Eventuell ein Bug.
Mit der Modulation Alpha auf 10 erreiche ich dass ich den zweiten Layer im Game nicht sehe. Die nächste Challenge ist es jetzt zur Laufzeit die Tiles auf dem zweiten Layer rund um den Spieler so zu verändern dass sie sichtbar werden. Ich möchte nun das in alle Richtungen drei Tiles von Layer 1 hell und grün werden. Also ermittle ich über welchem Tile sich mein Sprite gerade befindet, berechne dann alle Tiles in alle Richtungen die ich ändern muss und speichere diese in einem Dictionary. Als Tipp: das Tile hinter meinem Sprite ist das Zentrum. Von diesem gehe ich drei Tiles nach links, oben, rechts und unten. Mein Dictionary enthält am Ende also 49 Tiles mit ihren Koordinaten. Die Koordinate der Tiles fungiert hier als Key. Als Value könnt ihr entweder 1 angeben, oder aber eine Instanz von Color um zu definieren welche Modulation dieses eine Tile bekommen soll.

IV. Implementierung
Godot bietet diverse interne Funktionen an die wir überschreiben können. In diesem Fall sind es die Funktionen _use_tile_data_runtime_update und _tile_data_runtime_update. Diese sollten in einem Script implementiert werden welches der Tilemap zugewiesen wurde. Zudem ist es notwendig die Funktion _process zu implemetieren um in dieser einer force_update auf die Tilemap ausführen zu können.

Aber wie funktioniert das jetzt?
Beide oben genannten Funktionen werden für alle Layer der Tilemap und alle darin enthaltenen Tiles in jedem Frame ausgeführt. Die Sache kann also teuer werden wenn es viele Layer gibt und die Welt sehr groß ist!
Die Funktion _use_tile_data_runtime_update ermittelt ob es überhaupt Tiles gibt die aktualisiert werden müssen. Ihr werden von Godot der Layer übergeben der gerade angefasst wird und die Koordinate des Tiles. Wenn Euch das egal ist könnt ihr einfach ein true zurückgeben. Denkt aber daran dass in diesem Fall in jedem Frame die Map aktualisiert wird. Selbst wenn sich nichts verändert hat. In unserem Beispiel wissen wir dass sich nur Tiles auf Layer 1, also dem grünen, hellen Layer ändern. Außerdem kennen wir die Koordinate des Tiles welches aktualisiert werden muss. Somit ist es sinnvoll nur dann true zurück zu geben wenn Layer 1 als Parameter layer übergeben wurde und die Koordinate des Tiles über den Parameter coords.

Die Funktion _tile_data_runtime_update indessen führt die eigentliche Aktualisierung durch. Wie schon erwähnt wird sie in jedem Frame ausgeführt und liefert Euch den aktuell angefassten Layer, die Koordinate des gerade ermittelten Tiles und, super wichtig, die TileData des Tiles. Prüft also ob die Funktion gerade auf dem Layer aktiv ist den ihr ändern wollt und ob sie gerade bei dem Tile ist welches Euch interessiert. Wenn all das gegeben ist könnt ihr mit dem Parameter tile_data die Modulation dieses einen Tiles durchführen. Zum Beispiel mit tile_data.modulate.a = 255.0 um das Tile sichtbar zu machen.

V. Grenzen
Wenn ihr die Modulation eines Tiles halten möchtet, also für immer manifestieren, dann ist dies hier die schlechtere Lösung, denn jede Aktualisierung der TileMap bedeutet einen Einbruch der Performance. Wenn ihr aber immer nur einen kleinen Teil der Map ändern wollt funktioniert das hier hervorragend.



Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste