Transkripte
1. 0-0 Trailer: Willkommen zu meinem Kurs
zum Erstellen Ametrovinien in der
Gadot-Game-Engine Mein Name ist Thomas Ionizlo
und ich werde dein Lehrer sein. Ich habe einen Bachelor-Abschluss
in Informatik und unterrichte seit über fünf Jahren
Spieleentwicklung auf mehreren Plattformen Ich habe einen
kompletten Satz von Inhalten beigefügt, darunter Sprites,
Soundeffekte
und Musik, mit denen Sie
mitverfolgen
können , oder Sie können Ihre
eigenen Ressourcen verwenden, wenn Sie möchten Dieser Kurs wird dir helfen, dich mit der
GDOGame-Engine
vertraut zu machen Es ist ein sehr effizienter Arbeitsablauf für die Erstellung von Spielen und die native
Skriptsprache Du lernst, wie du Szenen mithilfe der verschiedenen Knoten von
Gado erstellen
und bearbeiten und ihr Verhalten
mithilfe von Skripten ändern Beim Schreiben dieser Skripte lernst
du, wie du
objektorientierte
Programmierprinzipien anwendest objektorientierte
Programmierprinzipien um deinen Code präzise,
skalierbar und
für andere Projekte wiederverwendbar zu halten ,
skalierbar und
für andere Projekte wiederverwendbar Am wichtigsten ist, dass
Sie lernen, ein komplexes Projekt
dieser Größenordnung zu strukturieren , indem Sie es in seine
einzelnen Komponenten
zerlegen in seine
einzelnen Komponenten
zerlegen Wir beginnen damit, einen
2D-Plattformcharakter zu erstellen und zu
animieren Erstellen Sie dann eine Umgebung
, in der der Charakter
die Kamera
des Spiels erkunden und bewegen Als Nächstes ermöglichen wir dem Charakter, zwischen
verschiedenen Räumen
zu wechseln und die Welt auf
eine Karte zu
zeichnen , damit der Spieler deine Welt
erkunden kann. Nachdem wir den Fortschritt
des Spielers gespeichert und geladen
haben, zeichnen wir ein Head-up-Display. Füge dann unsere
freischaltbaren Fähigkeiten hinzu, darunter einen Doppelsprung, einen Wandsprung, einen Sprung
und das Abfeuern eines Projektils Schließlich werden wir
einige Gegner für den Kampf und
einen Bosskampf hinzufügen und den
Fortschritt des Spielers im Spiel
verfolgen . ob du neu
in der Spieleentwicklung bist, die Gadot-Game-Engine noch nicht kennst
oder Metroid Venias noch nicht kennst, diesem Kurs lernst du
alles, was du
wissen musst, um ein komplettes
Spiel von Grund auf zu entwickeln Wenn du Hilfe benötigst, ist unser
Discord-Server voller anderer Studenten und
angehender Spieleentwickler , die alle deine Fragen beantworten können Klicke auf den Link in
meinem Profil, um Mitglied zu werden. Sie können sich die ersten beiden Abschnitte des Kurses kostenlos ansehen, und ich habe einen weiteren Kurs
, der die Grundlagen
der GD-Script-Programmierung ebenfalls
völlig kostenlos behandelt . Sobald Sie bereit sind, können
wir anfangen lernen, wie man
eine Metrovnia in Cado baut
2. 0-1 Herunterladen: Hallo Freunde. Um an diesem
Kurs teilnehmen zu können, benötigen Sie die Godot-Engine Öffnen Sie einen beliebigen Webbrowser
, gehen Sie zu godot.org und laden Sie
die neueste Version herunter, die zum Zeitpunkt
der Aufnahme dieses Videos Die Nutzung der Engine ist kostenlos, Sie können
jedoch optional
spenden, um die
Entwicklung zu unterstützen, wenn Sie möchten Nachdem der Download abgeschlossen ist, müssen
Sie die
Dateien aus dem komprimierten Ordner extrahieren sie
dann an einem sicheren
Ort auf Ihrem Computer speichern Um den Editor auszuführen, müssen Sie
lediglich die größere Datei
ausführen, die
nicht in der Konsole endet Sie müssen sich keine Gedanken über Installer oder
Launcher machen. Sie Godot zum ersten Mal öffnen, Ihre Projektliste leer
und Sie werden gefragt, ob
Sie
einige der verfügbaren Beispielprojekte
erkunden möchten einige der verfügbaren Beispielprojekte Wir werden das ignorieren
und unser erstes Projekt erstellen, das ein neues Fenster öffnet Hier können wir entscheiden, wo
das Projekt gespeichert werden soll. Der Standardspeicherort befindet sich
im Dokumentenordner, aber es ist eine gute Idee,
einen separaten Unterordner für Ihre
Godot-Projekte zu erstellen einen separaten Unterordner für Ihre
Godot-Projekte zu Als Nächstes können wir
unserem Projekt einen Namen geben. Mach dir darüber jetzt nicht
zu viele Gedanken. Sie können es später jederzeit ändern. Außerdem wird ein neuer Unterordner mit demselben Namen erstellt ,
der alle Dateien enthält ,
die sich
auf dieses Projekt beziehen können drei verschiedene Renderer ausgewählt werden, jeweils für
unterschiedliche Zwecke optimiert Ich empfehle, alle Ihre Projekte zunächst mit
dem Kompatibilitätsrenderer
zu starten, da
dieser am besten
für Web-Builds geeignet ist .
Wechseln Sie Ihren Renderer erst später wenn Sie eine bessere Unterstützung
für qualitativ bessere visuelle Effekte benötigen für qualitativ bessere visuelle Effekte Die Versionskontrolle mit Gi
Hub wird automatisch unterstützt und ich empfehle dringend, zu
lernen, wie man sie benutzt dieses
Projekt erstellen, wird es automatisch
geöffnet,
damit wir es bearbeiten können. Ich werde den
Editor jedoch schließen und erneut öffnen. Unser Projekt ist jetzt
in der Projektliste enthalten, und wir können es öffnen,
indem wir entweder darauf doppelklicken
oder es aus der Liste auswählen und auf die Schaltfläche Bearbeiten klicken Wir haben jetzt Zugriff auf den Godot und können mit der
Bearbeitung unseres ersten Projekts beginnen Im nächsten Video werden wir das Layout des
Editorfensters
untersuchen Wir sehen uns im nächsten Video.
3. 0-2 Redakteur: Hallo Freunde. Bevor wir
mit der Bearbeitung unseres Projekts beginnen, müssen
wir uns
mit dem Layout des
Godot Editor-Fensters
vertraut machen mit dem Layout des
Godot Editor-Fensters Der Großteil des
Fensters ist mit
einer Drei-D-Ansicht
der aktuellen Szene gefüllt einer Drei-D-Ansicht
der aktuellen Szene Dieses Projekt wird in zwei D nicht in drei D angezeigt.
Mit den Schaltflächen oben im
Fenster können wir die Ansicht
zwischen drei D und zwei D
umschalten zwischen drei D und zwei D . In zwei D haben wir die
X-Achse rot, die Y-Achse grün
und ein blaues Rechteck, das den Viewport zeigt, oder was tatsächlich auf dem Bildschirm
gezeichnet wird , wenn das Spiel
ausgeführt Beachten Sie, dass sich das Darstellungsfenster unterhalb der X-Achse
befindet wobei Y gleich Null ist, was
dem oberen Bildschirmrand entspricht Die Y-Achse ist invertiert, sodass positive Y-Werte Y-Achse nach unten und nicht nach oben verschoben
werden Links oben befindet sich
eine Registerkarte für die Struktur der aktuellen
Szene, die derzeit leer ist und uns
auffordert, einen
Wurzelknoten für diese Szene zu erstellen Da unser Spiel aus zwei D bestehen wird, lassen Sie uns eine Szene mit zwei D erstellen. Der Szenen-Tab zeigt jetzt
unseren Szenen-Stammknoten, einen Knoten zwei D. Wir werden im nächsten Video mehr über Szenen
und Knoten
erfahren. Dieses Dock enthält auch
den Tab Import, dem wir
die Importeinstellungen für
importierte Dateien wie
Grafiken und Audio ändern können , die wir in
unserem Projekt verwenden werden . Diese Dateien werden im
Projektdateisystem gespeichert und organisiert, das wir unten links sehen
können. Derzeit
enthält unser Projekt nur eine Datei, nämlich das Gadot-Symbol Auf der Registerkarte Dateisystem können
wir unsere
Projektdateien organisieren, indem wir
Ordner erstellen und
sie mithilfe des Filters durchsuchen zur Registerkarte Szene zurückkehren Wenn wir zur Registerkarte Szene zurückkehren und eine Notiz ausgewählt haben, werden
ihre Eigenschaften Registerkarte Inspektor auf der rechten Seite angezeigt. Wir können die Kategorien
dieser Eigenschaften erweitern und ihre Werte hier
bearbeiten. Dieses Dock
enthält auch die Registerkarte „Knoten“, die eine Liste der
Signale enthält, die dieser Knoten aussenden kann, sowie die Gruppen, zu denen
er gehört. Die Registerkarte Verlauf enthält eine
Liste aller Änderungen, die wir in der aktuellen Szene
oder für das gesamte Projekt
vorgenommen haben . Sie können alle Änderungen sehen,
die wir vorgenommen haben.
Außerdem habe ich
den Editor Fontie bearbeitet Das untere Dock ist
derzeit ausgeblendet, aber wir können auf die
Ausgabeschaltfläche klicken, um es zu erweitern Die Ausgabe zeigt
uns auch die Änderungen, die wir am Projekt vorgenommen haben, und zeigt auch
die
Textausgabe aus unserem Spiel an, was
für das Debuggen sehr nützlich ist Wir können hier manuell Nachrichten
ausgeben, aber der Editor gibt auch hier
Warnungen und Fehler Der Debugger verfügt über eine Vielzahl
nützlicher Tools, denen wir herausfinden können, was unser Spiel verlangsamt oder zum
Absturz bringt Es gibt auch Tabs
speziell für Audio, Animation und Shader. Weitere Tabs werden hier bei Bedarf hinzugefügt. Wir können dieses Dock zusammenklappen indem wir auf die
aktuell ausgewählte Registerkarte Wenn Sie auf die drei Punkte klicken, können
diese Docks Ihren Bedürfnissen entsprechend neu angeordnet werden,
je nachdem, wie Sie denken
, dass dies für Ihren Arbeitsablauf am besten für Ihren Die einzelnen Tabs können auch zwischen den
Dokumenten gezogen werden. Wenn Sie ein Layout gefunden haben
, das für Sie gut geeignet ist, können
Sie es
im Editor-Menü speichern Sie können auch eine Vielzahl von
Editor-Einstellungen ändern , um
den Editor an Ihre Bedürfnisse anzupassen Wenn wir irgendwann
ein Spiel zum Laufen haben, können
wir das über die Schaltflächen
in der oberen rechten Ecke tun Entweder das Spiel von
Anfang an spielen oder nur die aktuelle Szene
ausführen, das Spiel
pausieren oder beenden Im nächsten Video
lernen wir, wie man eine Szene erstellt. Wir sehen uns im nächsten Video.
4. 0-3 Szenen: Hallo Freunde. Nun, da
wir mit dem
Layout des Editors vertraut sind, fangen wir an,
unsere erste Szene zu bearbeiten. Wir beginnen mit einem
Klick auf zwei
D-Szenen und machen den Wurzelknoten
unserer Szene zu einem Knoten zwei D. Ein Knoten zwei D
steht eigentlich für nichts in unserem Spiel. Es ist nur eine
zweidimensionale Transformation. Eine Transformation ist eine Kombination aus Position, Drehung und Maßstab. Godot enthält auch eine
Schrägkomponente in zwei D-Transformationen. Wenn wir tatsächlich etwas zeichnen
wollen, müssen
wir unserer Szene einen weiteren
Knoten hinzufügen Entweder klicken
wir mit
der rechten Maustaste auf den Wurzelknoten und wählen Kind
hinzufügen oder klicken Sie
auf die Plus-Schaltfläche, Kind
hinzufügen oder klicken Sie
auf die Plus-Schaltfläche, um unserer Szene einen untergeordneten
Knoten hinzuzufügen. Es gibt viele
verschiedene Arten von Knoten, die alle
unterschiedlichen Zwecken dienen. Die gebräuchlichste
Art, etwas
in zwei D-Spielen zu zeichnen , ist die
Verwendung eines Sprites Also fügen wir unserer Szene einen
Sprite-Zwei-D-Knoten hinzu. Knotentypen erben
von anderen Knotentypen. Ein Sprite-2-D-Node ist also auch ein Node-2-D-Node und ein Canvas-Element und ein Basisknoten. Er hat
dieselben Eigenschaften, die von diesen Typen
geerbt wurden
, und dieselben Eigenschaften, die von diesen Typen
geerbt wurden
, einige weitere eigene Der Sprite-Two-D-Knoten wird als untergeordnetes Element
des Wurzelknotens
hinzugefügt, was durch den
Einzug gekennzeichnet Die Szenen sind
in einer Hierarchie organisiert beginnen mit einem
einzelnen Wurzelknoten verzweigen sich
dann in eine beliebige
Anzahl Diese untergeordneten Knoten können auch
ihre eigenen untergeordneten Knoten haben , die den Szenenbaum
bilden Wir können
Zweige des Baums oder
den gesamten Baum zusammenklappen , indem wir
auf den Pfeil neben ihnen klicken, und sie erneut erweitern. Der Sprite-Knoten zeichnet
immer noch nichts, weil ihm nicht gesagt
wurde, was er zeichnen soll ihn auswählen, können wir seine Eigenschaften
im Inspektor
sehen,
wo er tatsächlich Eigenschaften hat, die von Node,
Canvas-Element und Knoten D
übernommen wurden . Unter dem Abschnitt Sprite Two D hat
er auch eine Textureigenschaft, die derzeit leer ist Wir können eine
Texturdatei laden oder das GAD-Symbol aus
dem Dateisystem-Tab
in
das Texturfeld ziehen GAD-Symbol aus
dem Dateisystem-Tab in ,
um es zu füllen Und jetzt zeichnet der Sprite
Two D-Knoten Textur
des GADO-Symbols
als Sprite Lassen Sie uns diesen
Sprite-2-D-Node im Szenenbaum duplizieren , indem wir mit
der rechten Maustaste klicken und Duplizieren
auswählen oder den Knoten auswählen und Strg oder Command
D
drücken . Das Duplikat hat dieselben Eigenschaften
wie
der ursprüngliche Knoten und wird umbenannt, indem eine
steigende Zahl an seinen Namen angehängt Geschwister im Szenenbaum dürfen nicht denselben
Namen haben Wir können
eines unserer Sprites
in der Szenenansicht verschieben ,
indem wir es einfach ziehen Dadurch wird
ihre
Eigenschaft für transformierte zwei D-Positionen im Inspektor automatisch aktualisiert ihre
Eigenschaft für transformierte zwei D-Positionen im Wir können das Sprite auch drehen, skalieren und neigen,
wenn wir wollen Als Nächstes ziehen wir diesen Sprite Tu Di-Knoten
auf den anderen und
weisen ihn als untergeordneten Knoten
des anderen Sprite Tu Di-Knotens zu, was durch eine weitere Einrückungsebene weisen ihn als untergeordneten Knoten
des anderen Sprite Tu Di-Knotens zu, was durch eine weitere Einrückungsebene gekennzeichnet ist Wenn wir nun den übergeordneten
Sprite Tu Di-Knoten auswählen und
seine Transformationseigenschaften bearbeiten, werden
diese Änderungen Die eigenen
Transformationseigenschaften des Kindes werden in Bezug
auf die Eigenschaften des Elternteils definiert Diese hierarchische Struktur
der Szenen und die Vererbung von Eigenschaften ermöglichen es uns,
komplexe Szenen mit mehreren
verschiedenen Komponenten zu erstellen komplexe Szenen mit mehreren
verschiedenen Komponenten Wir können der
Szene eine beliebige Anzahl
verschiedener Knoten verschiedener Typen hinzufügen , z. B. einen
Audio-Stream-Player mit zwei D-Knoten und einen GPU-Partikel mit zwei D-Knoten Nun kann diese Szene mit zwei D-Szenen etwas
zeichnen, Geräusche
und Partikel aussenden , und all
diese Komponenten erben ihre
Transformationsposition vom Wurzelknoten Um die Sache zu vereinfachen, sollte
die Transformation eines
Wurzelknotens immer
alle Standardwerte haben und nur untergeordnete Knoten enthalten,
deren Transformationen bearbeitet Wir können Knoten umbenennen, was besonders nützlich ist der Wurzelknoten einer Szene beschreibt
, worum es sich handelt Nennen wir es so
etwas wie Roboter. Dann können wir diese Szene
als Szenendatei in unserem Projekt speichern Szene
als Szenendatei in unserem Projekt und sie erhält automatisch den gleichen
Namen wie der Stammknoten. Erstellen Sie dann eine neue
Zwei-D-Szene und stellen Sie sich vor, dass dies einen
Raum darstellt, in dem sich der Roboter befindet. Unsere Roboterszene kann der Szene
als einzelner Knoten
hinzugefügt werden . Wir können sogar mehrere
Roboter haben, wenn wir wollen. Im Kontext
dieser größeren Szene können
wir nun die
Transformationseigenschaften
eines Roboters bearbeiten , um ihn zu bewegen, drehen, zu skalieren, zu neigen usw. Lassen Sie uns diese Szene in
Room umbenennen und speichern. Wenn wir zur Roboterszene zurückkehren und die
untergeordneten Knoten des Roboters bearbeiten, werden
diese Änderungen auf
alle Instanzen des
Roboters in anderen Szenen angewendet . der Raumszene muss es
nicht Bei der Raumszene muss es
nicht
darum gehen, wie der
Roboter gebaut ist, sondern nur darum, wo er sich
im Raum befindet. Konstruktion von Szenen aus einzelnen Komponenten
ermöglicht es uns,
die Details
einzelner Objekte geheim zu
halten die Details
einzelner Objekte geheim und vor größeren
Bereichen zu verbergen Außerdem können wir auf einfache Weise mehrere
Kopien derselben Sache
erstellen, aber mit nur einer Quelle für das Objekt, das bearbeitet werden
muss Der Aufbau eines kompletten Spiels
besteht darin viele kleinere Szenen zu erstellen, die einzelne
Spielobjekte,
Charaktere und Orte
darstellen , und
dann mehrere
dieser Szenen
miteinander zu kombinieren , um
eine größere Szene zu erstellen , während
das Spiel läuft. Im nächsten Video werden wir
untersuchen, wie die Engine nützliche integrierte
Knotentypen für die
Simulation von Physik
bereitstellt Knotentypen für die
Simulation von Physik Wir sehen uns im nächsten Video.
5. 0-4 Physik: Hallo Freunde. Nachdem wir nun verstanden haben, wie
Szenen konstruiert werden, werden
wir uns ansehen, wie
Game-Engines integrierte
Funktionen bereitstellen , um die
Spieleentwicklung erheblich zu vereinfachen. Wir können die Roboter loswerden und diese Szene
aus dem Projekt löschen. Beginnen wir damit, unserer Szene einen
starren Körper hinzuzufügen. Im Kontext der Physik ist
ein Körper jedes Objekt, das mit anderen
Objekten
kollidieren kann und Masse besitzt Ein starrer Körper steht für
ein festes Objekt. Er wird durch
äußere Kräfte wie die Schwerkraft beeinflusst, kollidiert mit anderen
festen Objekten, verformt sich
aber nicht oder Es wird seine Form behalten. Dieser starre Körper benötigt eine Form
, bei der es sich um einen weiteren
Knoten handelt, der als direktes Kind
des starren Körpers
hinzugefügt werden muss . Dieser Formknoten
weiß nicht, welche Form er bis wir ihm im Inspektor eine
Formressource geben. Aus der Drop-down-Liste können wir einige verschiedene Optionen
auswählen. Ich mache eine rechteckige Form. Jetzt hat dieser starre Körper eine Form, aber es wird
eigentlich nichts gezeichnet. Also fügen wir ihm einen
Sprite-Zwei-D-Knoten hinzu und lassen ihn die
Godot-Symboltextur zeichnen Das Sprite und die
Kollisionsform stimmen nicht überein. also den
Kollisionsformknoten auswählen, können
wir ihn so anpassen, dass er besser
zum Sprite passt, indem wir auf die roten Punkte klicken und sie
ziehen oder indem wir seine Eigenschaften
im Inspektor bearbeiten Halten Sie die Alt-Taste gedrückt während der
Knoten für den starren Körper ausgewählt ist
, und positionieren Sie ihn so
, dass er
sich irgendwo in der oberen Bildschirmmitte befindet Drücken Sie dann die Taste „
Aktuelle Szene ausführen“ oder drücken Sie F sechs als Tastenkombination. Die Spiel-Engine
wendet automatisch Kräfte auf den starren Körper an, um
reale Physik wie die Schwerkraft zu simulieren . Die Masse- und Gravitationsskala
können
im Inspektor schnell angepasst werden, um das
Verhalten des starren Körpers zu optimieren Wir können ihm sogar
ein physikalisches Material geben , um ihm Reibung oder Sprungkraft hinzuzufügen, seinen Massenschwerpunkt anzupassen und viele andere Optionen Lassen wir zunächst diese einfache
Box mit einem Boden kollidieren. Sehr robuste Objekte, die
wir nicht bewegen möchten, bestehen normalerweise
aus einem statischen Körper statt aus einem starren Körper Ein statischer Körper kann immer noch mit anderen Körpern
kollidieren, aber er bewegt sich durch
diese Kollision nicht und wird nicht durch Kräfte wie die Schwerkraft
beeinflusst Ein statischer Körper benötigt auch
eine Kollisionsform. Aus dem Drop-down-Menü
wähle ich Weltgrenze aus. Im Gegensatz zu anderen Formen erstreckt sich
eine Weltgrenze bis ins Unendliche. In zwei D wird dies als Linie
dargestellt. Der Pfeil in den beiden D-Ansichten zeigt von der Grenze weg. Standardmäßig wird eine Geschossdecke
erstellt. die Position
des statischen Körperknotens
an den unteren Rand
des Viewports verschieben des statischen Körperknotens
an den unteren Rand
des , wird verhindert der starre Körper
über diese Weltgrenze fällt Lassen Sie uns den
starren Körper duplizieren und sehen, wie er sich verhält, wenn er
mit einem anderen starren Körper kollidiert Wir können auf einen Knoten klicken
und seinen Typ ändern. Lassen Sie uns also diesen starren
Körper in einen statischen Körper umwandeln. Positionieren und
drehen Sie ihn dann so, dass der starre Körper in der
Luft mit ihm kollidiert. Denken Sie daran, Knoten umzubenennen, nachdem Sie ihren Typ geändert haben, damit Sie
wissen, um welchen Typ es sich Sie können es aber auch an dem
Symbol neben ihrem Namen erkennen. Wenn wir das
alles selbst manuell programmieren würden, würde
es eine Menge Arbeit erfordern, diese Sprites
zu zeichnen, zu
berechnen, wie sie von Kräften
beeinflusst werden,
herauszufinden, wann sie miteinander
kollidieren,
und festzustellen, wie
sich das auf ihr Verhalten auswirkt Neben der Physik
helfen uns Game-Engines dabei, einen Großteil der Funktionen zu automatisieren , die in
den meisten Spielen
üblich sind drastisch
zu beschleunigen
und zu vereinfachen Im nächsten Video erfahren
wir, wie man Skripte
an Knoten anhängt, um ihr Verhalten
zu bearbeiten Wir sehen uns im nächsten Video.
6. 0-5 Skripte: Hallo Freunde.
Die Game-Engine bietet uns zwar viele integrierte
Funktionen, wir können aber auch unsere eigenen hinzufügen, indem wir Skripte an Knoten
anhängen Wenn ich einen beliebigen Knoten
im Szenenbaum auswähle, verwende
ich den statischen Körper
, der eine schwebende Box ist Wir können entweder mit der rechten
Maustaste klicken und das
angehängte Skript auswählen oder die Schaltfläche für
das angehängte Skript drücken. Dies öffnet ein neues Fenster. Das Skript erbt
automatisch den Knotentyp, an den es angehängt
ist, und wir können unser Skript bei Bedarf
von einer Vorlage aus starten. Wir werden auch einen
Namen für das Skript angeben
, der
seinen Zweck widerspiegeln sollte Ich nenne mein Script Spin und den Ordner, in dem
es gespeichert ist. Wenn Sie auf die Schaltfläche Erstellen klicken, wechselt die
Ansicht
automatisch zur Skriptansicht, sodass wir mit der
Bearbeitung des Skripts beginnen können. Die Vorlage beginnt mit zwei Funktionen:
Bereit und Bearbeitung. Jeder Text, der dem
Octothorp-Symbol folgt, ist ein Kommentar. Es wird nicht von der
Engine verwendet und dient nur zu unserem Vorteil, um uns zu helfen, das Skript
besser zu verstehen Wie in diesen Kommentaren beschrieben, wird
die Ready-Funktion
automatisch aufgerufen wenn dieser Knoten den
Szenenbaum zum ersten Mal betritt, was ein
bisschen irreführend ist Aber vorerst wird es bedeuten,
wann das Spiel zum ersten Mal startet. Der Prozess
wird dagegen bei jedem Frame aufgerufen, während das Spiel läuft Bei den
Standardprojekteinstellungen
ist
das 60 Mal pro Sekunde. Eine Funktionsdeklaration beginnt
mit dem Schlüsselwort funk, gefolgt vom Namen
der Funktion. Diese Funktionsnamen
beginnen mit einem Unterstrich Weise
kennzeichnet Gudo Funktionen als privat,
was bedeutet, dass sie
nur im Kontext dieses
Skripts verwendet werden dürfen den Funktionsnamen
folgen Klammern, die Parameter
für die Funktion enthalten ,
falls vorhanden Die Prozessfunktion
hat einen Parameter,
Delta, der die Anzahl der Sekunden angibt, die
seit dem vorherigen Frame vergangen sind den meisten
Fällen handelt es sich also um ein Sechzigstel, nimmt
aber manchmal zu, wenn die Verarbeitung eines Frames
länger dauert als erwartet Auf die Parameter folgt ein Bindestrich, der größer als ein Pfeil ist, dann der Rückgabetyp
der Funktion, die in beiden Fällen ungültig sind, was bedeutet, dass sie
keinen Wert zurückgeben Die Angabe von
Rückgabetypen ist optional, und diese können
entfernt werden, wenn Sie dies bevorzugen Der Inhalt einer Funktion ist um einen Tabulator
eingerückt,
ohne dass geschweifte Klammern erforderlich sind einen Tabulator
eingerückt,
ohne dass geschweifte Klammern erforderlich Beide Funktionen
enthalten nur das Schlüsselwort pass, was im Grunde nichts tun
bedeutet Aber wir können diese
Anweisung durch
etwas anderes ersetzen . Um zu sehen, wie das
funktioniert, ändern wir Hauptteil
der
Ready-Funktion so, dass sie etwas tut. Die Druckfunktion gibt alles, was wir wollen, im Ausgabefeld aus
, wenn das Spiel läuft. Wir können Funktionen aufrufen,
indem wir
ihren Namen
gefolgt von Klammern angeben ihren Namen
gefolgt von Klammern Dann können
wir innerhalb der Klammern Argumente angeben, können
wir innerhalb der Klammern Argumente angeben der
Funktionen entsprechen In Anführungszeichen
können wir alles schreiben, was wir wollen, Beispiel Ready to Spin Alles, was wir in
Anführungszeichen setzen , wird als Zeichenfolge
bezeichnet, kurz für Zeichenfolge. in der Prozessfunktion Lassen Sie uns in der Prozessfunktion
dasselbe tun, aber dieses Mal den Wert von Delta ausgeben. Lassen Sie uns auch das tun, wofür dieses
Skript gedacht war, und den Wert der Rotation
dieses Knotens ändern, indem wir ihn mithilfe
des Plus-Gleichheits-Operators um Delta
erhöhen Der Plus-Gleichheitsoperator
nimmt den Wert von Delta und addiert ihn zum Wert
der Rotation Weisen Sie das
Ergebnis dann auch der Rotation zu. Wenn wir die Szene ausführen, können wir sehen
, dass sich die Kiste dreht. das Spiel beenden, können wir in
der Ausgabe sehen , dass die
Bereitschaftsnachricht zuerst gedruckt wurde, nur einmal,
gefolgt von vielen Zahlen, von denen die
meisten eine 60. sind Wie funktioniert das? Sowohl Ready als auch Process sind
Funktionen von Node,
was bedeutet, dass jeder Knoten in unserem Szenenbaum diese Funktionen bereits
hat, aber sie tun nichts. Unser Skript überschreibt
die Definitionen
dieser Funktionen für
einen bestimmten Knoten , an den dieses Skript angehängt ist Wir können in unserem Skript sehen, wenn
eine Funktion
eine Funktionsdefinition überschreibt , wenn ein blauer Pfeil
davor steht Wenn wir das Spiel starten,
rekonstruiert
die Engine den
Szenenbaum für diese Szene, beginnend mit der Wurzel, und fügt jeweils einen Knoten
von oben nach Die Ready-Funktion
für jeden Knoten wird
aufgerufen , nachdem er
zum Szenenbaum hinzugefügt wurde, aber auch, nachdem alle
seine untergeordneten Knoten hinzugefügt
wurden und ihre Ready-Funktionen zuerst aufgerufen
wurden Das bedeutet, dass Eltern sich
darauf verlassen können, dass ihre Kinder zum Szenenbaum
hinzugefügt werden, bevor
sie als bereit betrachtet werden. Wenn der gesamte
Szenenbaum fertig ist, beginnen die
Prozessframes. Der Prozess wird
auf jedem Knoten
im Szenenbaum von oben nach
unten in sequentieller Reihenfolge aufgerufen im Szenenbaum von oben nach
unten in sequentieller Reihenfolge Im Gegensatz zu Ready lassen Eltern ihre Kinder
nicht zuerst
verarbeiten wir nun
ein grundlegendes Verständnis
davon haben , wie Godot funktioniert, werden wir
im nächsten Video damit beginnen, das Projekt für
die Entwicklung unseres Spiels
einzurichten Wir sehen uns im nächsten Video.
7. 0-6 Spiel: Hallo Freunde. Bevor wir
mit unserem Spielprojekt beginnen, müssen
wir
ein paar Dinge vorbereiten. Zuerst können wir entweder alles
löschen oder ein neues Projekt starten, damit
wir einen Neuanfang haben. Ich werde alles
außer der Bodenkollision entfernen. Benennen Sie dann diese Szene und
ihren Stammknoten in Game um. Die Spielszene wird
eine zentrale Szene sein , in der das
gesamte
Hauptspiel stattfindet. Der Stammknoten des Spiels wird
zwei untergeordnete Hauptzweige haben, einen Knoten für die Weltumgebung
und einen Knoten auf der Canvas-Ebene. Diese stellen eine
klare Unterscheidung dar zwischen dem, was
in der Spielwelt existiert, wie dem Level, in dem der Spieler gerade
spielt, allen Charakteren,
Gegenständen usw.,
und dem, was außerhalb
dieser Welt ausschließlich zum Vorteil des Spielers existiert , d. h.
Informationen,
die auf einem
Head-up-Display oder einer Benutzeroberfläche angezeigt werden Head-up-Display oder einer Benutzeroberfläche Der Weltumgebungsknoten
wird mehrere Kinder haben. Ein oder mehrere Knoten für die
aktuellen Levels,
die geladen sind Im Moment stellen wir
das einfach als statisches Body-Tutti dar Ein Tutti-Knoten für den Körper eines Charakters
wird am häufigsten für
den Spielercharakter verwendet und ein Kamera-Tutti-Knoten,
der normalerweise dem Spieler folgt Ich setze die Position
der Bodenkollision wieder
auf den Ursprung der Szene
zurück Wenn sich in der Szene ein Kameraknoten befindet, das blaue Rechteck nicht mehr dar, welcher Teil der
Welt auf dem Bildschirm dargestellt wird.
Stattdessen wird das
Sichtfenster der Kamera in Magenta angezeigt, derzeit
am Ursprung zentriert ist. Der Boden wird sich also in der
Mitte der Kameraansicht befinden. der Leinwandebene werden Kinder für Dinge
wie
die Anzeige der Spielerinformationen auf dem
Bildschirm, in Menüs usw. vorhanden sein. Diese werden alle
mit Kontrollknoten dargestellt. Der Canvas- und der
Kontrollknoten werden weiterhin
das blaue Rechteck
als Viewport verwenden das blaue Rechteck
als Viewport um
ihre Positionen auf dem Bildschirm zu ordnen Das funktioniert, während der Spieler das Spiel
spielt, so, dass die Kamera die
Welt betrachtet und zeichnet, was sie sieht, alle Kinder des
Weltenumgebungsknotens Nachdem die Kamera
ein rechteckiges
Toti-Bild der Welt gerendert hat , zeichnet
die Canvas-Ebene ihre
Kinder darüber, sodass der typische
Gameplay-Bildschirm
entsteht , den wir
gewohnt sind Diese beiden Branchen weisen
noch einen weiteren klaren Unterschied auf. Die Welt
muss angehalten werden, die Canvas-Ebene
jedoch nicht Wenn Sie also den Spielknoten
im Inspektor unter Knoten,
Erweiterung Prozess auswählen, wird der zugehörige
Prozessmodus auf „Immer“ geändert Der
Node World Environment wird auf
Pausble gesetzt und die Canvas-Ebene wird als
Standard-Inherit-Ebene beibehalten Er erbt den
Prozessmodus seines übergeordneten Knotens
,
also des Spielknotens, und wird es auch immer Da der voreingestellte
Prozessmodus „Vererben“ ist, alle untergeordneten Elemente der
Welt-Umgebung, was
pausibel ist, wohingegen untergeordnete Elemente der Canvas-Ebene
die Always-Verarbeitung Wenn wir
in einem neuen Projekt zum ersten Mal auf
die Schaltfläche „Projekt ausführen“ klicken, werden
wir aufgefordert, die Hauptszene
festzulegen Wir können die aktuelle Szene oder eine andere Szene
aus dem Projekt auswählen. die Spielszene
gerade geöffnet ist, können
wir sie
vorerst als
Hauptszene festlegen und sie später ändern,
wenn wir eine Titelszene haben. Dies kann
in den
Projekteinstellungen unter den Ausführungseinstellungen geändert werden. Es ist auch eine gute Idee,
Ihre Anzeigeeinstellungen festzulegen ,
bevor Sie beginnen. Wählen Sie also Fenster aus. Hier können wir
die Breite
und Höhe des Viewports in Pixeln einstellen und Höhe des Viewports in Pixeln Ich finde, dass 12 × 80 × 720 eine
gute Größe für die meisten Spiele sind, und sie ist
mit den meisten Plattformen kompatibel unter
Stretch den Stretch-Modus von deaktiviert auf
Canvas-Elemente ändern , wird sichergestellt, dass zwei D-Knoten entsprechend
dem Spielfenster dehnen oder verkleinern Da ich Pixelkunst verwenden werde, ändere ich den Skalierungsmodus
von Fractional auf Pixel werden also nur
doppelt oder halb so groß, wodurch Pixel mit gemischter Größe vermieden werden Unter „
Texturen rendern“
ändere ich außerdem den
Standard-Texturfilter von „linear“ auf „Am ähnlichsten“. Dadurch werden meine Pixelgrafiken genau so
dargestellt, wie sie sind, und
verhindert, dass sie
verschwommen Nachdem Sie die
Projekteinstellungen geschlossen
haben, müssen Sie möglicherweise
eine Aktualisierung auslösen , indem Sie einfach das Ansichtsfenster
zoomen oder schwenken , um
das blaue Rechteck
oder
die Kamera zu erzwingen , ihre Größe selbst oder Jetzt können wir damit beginnen, das Projekt
in seine einzelnen Komponenten zu
zerlegen in seine einzelnen Komponenten und sie nacheinander anzugehen. Im nächsten Abschnitt werden
wir einen grundlegenden
Tutti-Plattform-Charakter erstellen , den der Spieler kontrollieren kann Wir sehen uns im nächsten Video.
8. 1-1 CharakterKörper: Hallo Freunde. In diesem Abschnitt werden
wir einen
2D-Plattform-Charakter bauen , den der Spieler kontrollieren kann Falls deine Spielszene
noch nicht über einen Charakterkörper mit zwei Dnode verfügt, solltest
du jetzt einen hinzufügen Der Charakterkörper zwei D ist kein Körper im
Sinne einer Person,
sondern ein physischer Körper, wie der
starre Körper oder der statische Körper Im Gegensatz zu starren Körpern wird auf einen
Charakterkörper nicht automatisch die
Schwerkraft ausgeübt automatisch die
Schwerkraft ausgeübt, sondern
er reagiert
im Gegensatz zu einem statischen Körper auf Kollisionen im Gegensatz zu einem statischen Körper Der Körperknoten der Figur benötigt also auch eine Kollisionsform als untergeordnetes Objekt mit einer Formressource, die
ihm mitteilt, welche Form er hat Die meisten Spiele verwenden eine Kapsel,
um einen Charakter darzustellen, aber es werden auch Rechtecke und
Kreise verwendet Vorerst verwende ich
ein Rechteck mit Abmessungen 128 mal 128 Wir können jederzeit die Kollisionsform ändern oder die
Größe nachdem wir eine Zeichnung
des Charakters erstellt haben , auf der
er später basieren soll Zusätzlich zur
Kollisionsform benötigen
wir auch einen
Sprite-Knoten, um den Charakter zu zeichnen Es ist wichtig, keinen
animierten Sprite-Knoten zu verwenden animierten Sprite-Knoten da dies nicht der
beabsichtigte Zweck ist Animierte Sprite-Knoten dienen nur zum Zeichnen einfacher
animierter Sobald Sie
andere Knoten mit Ihren
Animationen wie Sounds,
Partikeln oder
Funktionen synchronisieren müssen , benötigen Sie
mehr Flexibilität, als der Animated
Sprite-Node Im Moment verwende ich einfach das Godot-Symbol als Textur des
Charakters, das 128 mal
128 Pixel groß ist und
der Kollisionsform entspricht Lassen Sie uns den
Toti-Knoten des Charakters in den Namen
des Charakters umbenennen Toti-Knoten des Charakters in den Namen
des Charakters Wir
haben zwar nicht die Absicht mehrere Kopien
dieses Charakters zu
haben, aber
es ist trotzdem eine gute Idee seine Struktur
in einer separaten, von der Spielszene
isolierten Szene
zusammenzustellen von der Spielszene
isolierten Szene Das können wir erreichen, indem wir mit der
rechten Maustaste auf den Knoten dann
Zweig als Szene speichern auswählen. Lassen Sie uns einen neuen
Unterordner für Szenen erstellen, einen weiteren darin
für Charaktere, speichern wir ihn
dann unter dem
Namen dieses Charakters In der Spielszene wird
dieser Charakter jetzt als ein
einziger Knoten
mit einem Klapperbrettsymbol
dargestellt , was uns darauf hinweist, dass es sich
um Alle untergeordneten
Knoten sind versteckt und befinden sich jetzt in
der Wir können die Charakterszene öffnen indem wir auf das
Schindelsymbol klicken. In der Szene des Charakters empfiehlt
es sich, den Ursprung des
Charakters so zu betrachten , dass er sich
im Mittelpunkt zwischen seinen Füßen befindet, als ob die
X-Achse der Boden Dadurch wird sichergestellt, dass alle
Charaktere
unabhängig von
ihrer Größe ihren Ausgangspunkt gemeinsam haben . Lassen Sie uns also die Sprite- und
Kollisionsformknoten entlang der Y-Achse
nach oben verschieben Kollisionsformknoten entlang der Y-Achse
nach oben Zusätzlich zur
Kollisionsform und den Sprite-Knoten benötigt
unser Charakter
einen Animationsspieler, um die Sprite-Animationen abzuspielen Außerdem gibt es einen
Animationsbaum, mit dem Sie steuern können , welche Animation zu
einem bestimmten Zeitpunkt abgespielt wird einem
Audio-Stream-Player mit zwei D-Knoten können
wir auch
Soundeffekte abspielen. Möglicherweise möchten wir auch einen
GPU-Partikelemitter verwenden, um Partikeleffekte für
Dinge wie Schritte und Sprünge zu erzeugen Dinge wie Schritte und Jeder dieser Knoten
wird in einem
eigenen Video behandelt , um
sie genauer zu erklären Vorerst ist es wichtig zu
verstehen, wie eine Szene alles
im Spiel darstellen
kann ,
wobei ihre eigene Szene über viele untergeordnete Knoten verfügt
, die zu ihrer Erstellung verwendet werden. den Wurzelknoten dieser Szene wird normalerweise ein Skript
angehängt. Je nachdem, wie Sie Ihre Dateien organisieren
möchten, möchten
Sie dieses Skript möglicherweise in demselben Ordner wie
die Szene
speichern , an
die es
angehängt ist , oder in einem separaten Ordner
speziell für Drehbücher. Sie sollten
Ihre Skripte nach
ihrem Verwendungszweck benennen und dabei einen möglichst
vagen Namen angeben Dieses Skript wird nicht spezifisch
für meinen Kindercharakter sein, sondern sollte
so geschrieben sein, dass es für jeden Charakter
gelten kann ,
zumindest vorerst Der Zweck des
Skripts wird darin bestehen, nicht nur den
Körperknoten des Charakters selbst zu kontrollieren, sondern auch die
Operationen aller untergeordneten
Knoten so durchzuführen, dass sie
so harmonisch funktionieren, wie es für die Knoten so durchzuführen, dass sie
so harmonisch funktionieren, Erstellung
unseres Charakters erforderlich Dieses Skript,
das an den Stammknoten unserer
Charakterszene angehängt ist, ist auch
von der Spielszene aus zugänglich und dient zwei
weiteren Zwecken. Es verschleiert die Verarbeitung der einzelnen Komponenten
der Charakterszene und bietet
gleichzeitig eine übersichtliche
und übersichtliche Oberfläche für Interaktion mit anderen Skripten und Objekten in der Darauf wird im
weiteren Verlauf dieses
Abschnitts näher eingegangen Nachdem wir nun eine grundlegende
Charakterstruktur erstellt haben, müssen
wir
vom Spieler Feedback erhalten, um sie kontrollieren zu können. Wir sehen uns im nächsten Video.
9. 1-2 Eingabekarte: Hallo Freunde. In diesem Video werden
wir Eingaben vom
Spieler
entgegennehmen und
sie an den Charakter senden. Da ich das Skript für den Tu
Di-Knoten
meines Charakters anhand einer Vorlage erstellt habe , es bereits
Code, der Eingaben
entgegennimmt und den
Charakter nach links oder rechts bewegt. Wenn wir die Spielszene ausführen, der Charakter
durch Drücken der linken und rechten wird der Charakter
durch Drücken der linken und rechten
Pfeiltasten
bewegt, aber das fühlt sich nicht sehr gut und ist nicht sehr gut implementiert. Der Kommentar
sagt uns sogar , dass wir
zumindest
die linken und rechten Benutzeroberflächenaktionen
durch unsere eigenen benutzerdefinierten
Gameplay-Aktionen ersetzen sollten die linken und rechten Benutzeroberflächenaktionen . Dazu öffnen wir
die Projekteinstellungen und wechseln
dann zur
Eingabekarte. In das Feld „Neue Aktion hinzufügen
“ geben wir den Namen
unserer Aktion ein, beginnend mit „Nach links bewegen“. Dies darf keine Leerzeichen enthalten und wird normalerweise
in kleinen Schlangenbuchstaben geschrieben, wobei
alle Kleinbuchstaben durch Unterstriche getrennt sind Drücken Sie die Eingabetaste oder klicken Sie auf die Schaltfläche Hinzufügen, um
die Eingabeaktion hinzuzufügen, und machen Sie
dann
eine weitere Aktion, um nach rechts zu gehen Und wir werden später auch
einen für Jump benötigen. rechts neben jeder
dieser Aktionen auf die Plus-Schaltfläche, Klicken Sie rechts neben jeder
dieser Aktionen auf die Plus-Schaltfläche, um dieser Eingabeaktion ein Ereignis
hinzuzufügen. Dies ist die Taste, die gedrückt
wird, um sie auszulösen. Das Listen-Feld erkennt
automatisch Eingabeereignisse, oder Sie können
die verfügbaren Eingabeereignisse durchsuchen. Um mich nach links zu bewegen, verwende ich
die linke Pfeiltaste, bewege ich mich mit
der rechten Pfeiltaste nach rechts und springe mit der Z-Taste. Wir können jeder Aktion mehrere verschiedene
Ereignisse hinzufügen,
was bedeutet, dass wir
Controller-Unterstützung
einfach hinzufügen können , indem wir zusätzliche
Ereignisse für den Controller hinzufügen. Ich verwende das Steuerkreuz nach links und rechts, um den Charakter zu
bewegen, sowie den
linken Stick nach links
und rechts und auch die untere
Taste zum Springen. Wenn Sie fertig sind, schließen Sie
die Projekteinstellungen. In diesem Video werden wir
nur
diese eine Zeile ändern, in der
wir Eingaben abrufen,
und, was noch wichtiger ist,
sie in ein separates Skript verschieben Es empfiehlt sich, dass alle Ihre Skripte
nur einem einzigen Zweck dienen Dieses Skript wird nur
verwendet, um einen Charakter zu steuern, nicht um Eingaben
vom Spieler zu erhalten. dem Szenenbaum einen neuen Knoten
hinzufügen, kann
dieser einfach ein
normaler Knoten sein, da er nichts anderes tut,
als unser Skript auszuführen. Nennen wir es Player. Hängen Sie dann ein neues Skript an. Es gibt mehrere
Möglichkeiten, Eingaben zu empfangen. Am gebräuchlichsten ist es, die Eingabefunktion zu
überschreiben. Funktionsüberschreibungen müssen exakt mit der überschriebenen
Funktion übereinstimmen Der Name muss also exakt
dieselbe Schreibweise, dieselben Parametertypen
und
denselben Rückgabetyp Die Eingabefunktion
hat einen Parameter, ein Eingabeereignis, dem wir einen beliebigen Namen geben
können. Aber ich bevorzuge es,
ihre Standardnamen zu verwenden, und es gibt nichts zurück. Die Eingabefunktion
wird in
jedem Frame aufgerufen , wenn ein
Eingabeaktionsereignis eingetreten ist, egal ob es sich dabei um das
Drücken einer Taste, Neigen eines Analogsticks
oder das Bewegen der Maus Innerhalb dieser Eingabefunktion können
wir über
seinen Namen auf das Eingabeereignis zugreifen und auf seinen
Inhalt mit einem Punkt Wir wollen eine Funktion des
Eingabeereignisses namens
Is action pressed aufrufen . Beim Aufrufen einer Funktion müssen auf
den Funktionsnamen Klammern
folgen In den Klammern geben
wir
Argumente für die Funktion
an, die ihren Parametern entsprechen In diesem Fall eine Zeichenfolge, der Name der
Eingabeaktion, die wir überprüfen Also schreiben wir Sprünge
in Anführungszeichen und achten
darauf, dass Groß- und
Kleinschreibung der Eingabeaktion, die
wir in den
Projekteinstellungen erstellt haben, exakt übereinstimmen Kleinschreibung der Eingabeaktion, die . Diese Funktion gibt einen booleschen Wert zurück, entweder true, wenn die Taste gedrückt
wurde, oder
false, wenn sie nicht Indem wir diese Funktion
hinter das Schlüsselwort if setzen, gefolgt von einem Doppelpunkt, können
wir eine neue
Einrückungsebene für unser Skript erstellen Alles, was wir
hier eingeben, wird nur ausgeführt, wenn das Ergebnis der
I-Anweisung wahr ist, also nur, wenn die
Taste gedrückt wurde Vorerst
drucken wir einfach das Wort Jump aus. Wenn wir das Spiel ausführen und eines der Eingabeereignisse drücken, die wir
als Sprungeingabeaktion angegeben
haben, werden wir sehen, dass der Sprung im Ausgabefenster
gedruckt wird. Wir brauchen die
Ready-Funktion nicht, also entfernen wir sie. Für Dinge wie Bewegung, insbesondere bei der Verwendung von
Controllern mit Analogsticks, kann
es nützlich sein, innerhalb der
Prozessfunktion nach
dieser Eingabe zu suchen . Genau wie beim
Zeichenskript müssen
wir
den Eingabe-Singleton verwenden Diese Singleton-Klasse hat eine
Funktion namens get axis. Die G-Achsenfunktion
erfordert zwei Parameter, eine negative und
eine positive Aktion Links wird immer als negativ und rechts als positiv betrachtet , was der X-Achse
in unseren beiden D-Welten
entspricht. Also schreiben wir die Namen
unserer Eingabeaktionen wir in den
Projekteinstellungen erstellt haben, in Anführungszeichen, bewegen uns nach links und nach rechts. Diese Funktion gibt
eine Dezimalzahl zwischen
minus eins und positiv zurück , die
angibt, wie
weit der linke Stick in eine angibt, wie
weit der linke Stick der beiden Richtungen geneigt
ist, oder einfach eine negative oder positive Zahl, wenn Sie
Tasten oder Knöpfe verwenden Da der Wert Null,
was bedeutet, dass
keine Eingabe erfolgt, immer noch eine gültige Eingabe ist, möchten
wir
diese Information immer bei jedem Frame an den
Spieler senden diese Information immer bei jedem Frame an den
Spieler Hier ist also keine
If-Aussage erforderlich. Lassen Sie uns einfach den Wert ausdrucken hier zurückgegeben
wird
, damit wir ihn sehen können. Beim Ausführen des Spiels wird die Zahl Null wiederholt
gedruckt. Wenn ich die linke oder
rechte Pfeiltaste, die Richtungstasten auf
meinem Controller drücke oder
den linken Analogstick neige, ändert sich der Wert zwischen negativ
und positiv Falls Sie jemals
weitere Informationen einer dieser
Klassen oder Funktionen benötigen, können
Sie
auf deren
Dokumentation zugreifen, indem die Strg- oder
Befehlstaste
gedrückt halten und auf sie klicken das
Zeichenskript von zuvor öffnen, haben
wir eine Variable
namens direction die in der Prozessfunktion
deklariert wird. Lassen Sie uns das auskommentieren und diese Variable in
den globalen Bereich
unseres Skripts
verschieben , indem sie stattdessen oben
im Skript
deklarieren Wenn wir zum
Spielerskript zurückkehren, in dem wir
Bewegungseingaben erhalten haben , um
diese Informationen von
einem Skript an ein anderes weiterzugeben , benötigen
wir einen Verweis
auf das andere Skript Im Spielerskript werden
wir eine
Variable erstellen, die
einen Verweis auf den Körper eines
Charakters enthält . Indem wir vor der
Variablendeklaration ein Export-Tag hinzufügen, die Variable vom Inspektor aus
zugänglich und wir können ihren
Wert als unseren Charakter zuweisen. Anstatt
den Wert von input dot get axis auszudrucken , senden
wir ihn an
das Zeichen, indem ihn der
Richtungsvariablen des Zeichens zuweisen Wenn wir das Spiel starten, überprüft der
Player-Node jedem Frame den Status unserer Eingaben „Zug nach links“ und „
Zug nach rechts Weisen Sie das dann der Richtungsvariablen des
Charakters zu. Die Funktion zur
Verarbeitung von Zeichenskripten überprüft die
Richtungsvariable jedem Frame und verwendet diese, um das
Zeichen nach links und rechts zu bewegen. Unser Spieler gibt jetzt
Eingaben , um unseren Charakter zu bewegen. Wir sehen uns im nächsten Video.
10. 1-3 Bewegung: Hallo Freunde. In diesem Video werden
wir die
Bewegung der Charaktere
verbessern , indem wir Physik anwenden. Im Zeichenskript können
wir sehen, dass die
Standardvorlage prüft, ob der Wert
von direction Null ist. Null wird als falsch behandelt und
jeder andere Wert ist wahr. Wenn also ein
Richtungswert angegeben wird, der nicht Null ist, die
X-Geschwindigkeit des Charakters auf Richtung
multipliziert mit Geschwindigkeit
gesetzt Oder wenn die Richtung Null ist, dann bewegt sich der Wert der X-Geschwindigkeit
des Charakters mit der Geschwindigkeit
gegen Null Das Ergebnis ist, dass die Geschwindigkeit der Figur entweder Null oder Geschwindigkeit
ist, außer wenn der Analogstick
geneigt Das ist nicht sehr realistisch
und fühlt sich nicht sehr gut an. Diese Werte für Geschwindigkeit und
Sprunggeschwindigkeit sind ebenfalls als Konstanten definiert, die sich im Gegensatz zu Variablen
niemals ändern dürfen Das ist problematisch, und wir
sollten das ändern, wenn wir
wollen, dass sich die Charaktere in unserem Spiel jemals mit unterschiedlichen
Geschwindigkeiten bewegen mit unterschiedlichen
Geschwindigkeiten Wir werden uns später mit dem Springen befassen. Beachten Sie auch, dass diese Werte in Pixeln
gemessen werden, sodass sie je nach Größe Ihres Charakters variieren. Lassen Sie uns zunächst
unsere Geschwindigkeitskonstante
durch eine
Bewegungsgeschwindigkeitsvariable vom Typ Float ersetzen . Ich stelle meins auf 256
Pixel pro Sekunde ein. Es ist eine gute Idee,
Variablen und Funktionen
in Bereiche zu unterteilen, die öffentlich und privat
sein sollen , indem privaten Namen
ein Unterstrich
vorangestellt alles Private
soll nur innerhalb
dieses Skripts selbst zugegriffen
werden, im
Gegensatz zur Richtungsvariablen, auf
die vom Gegensatz zur Richtungsvariablen, Player-Skript
aus
zugegriffen und sie geändert wird ,
also öffentlich ist Im physikalischen Prozess werden
wir die
Geschwindigkeitskonstante durch unsere
Bewegungsgeschwindigkeitsvariable ersetzen . Und jetzt funktioniert alles
genauso wie zuvor, außer dass die Geschwindigkeit etwas langsamer
ist. Wenn wir vor dieser
Variablendeklaration ein Export-Tag
hinzufügen , können
wir dessen
Wert im Inspektor ändern. Dies ist eine großartige
Möglichkeit, den Wert zu testen und zu
optimieren, damit
er sich genau richtig anfühlt Da können wir unser Spiel ausführen,
schauen, ob es sich gut anfühlt, es dann
ändern und erneut testen Ein weiterer Vorteil ist, dass, wenn wir
mehrere Charaktere haben , die dasselbe Skript
verwenden, jeder seinen eigenen
Wert für diese Variable haben kann. Normalerweise
bewegen sich Charaktere jedoch nicht sofort mit maximaler
Geschwindigkeit vom Stillstand zur Bewegung. Stattdessen wird bei ihnen im Laufe der Zeit eine
gewisse Beschleunigung angewendet, bevor sie ihre Höchstgeschwindigkeit
erreichen Dies kann erreicht werden,
indem
eine weitere Variable
namens Beschleunigung deklariert wird, ebenfalls schwimmend ist und in Pixeln
pro
Quadratsekunde gemessen wird in Pixeln
pro
Quadratsekunde gemessen Wenn das einfacher ist, können
Sie davon ausgehen, dass der Wert ein Vielfaches Ihrer Wenn meine Beschleunigung doppelt so hoch
ist wie meine Geschwindigkeit, dann erreiche ich die
Höchstgeschwindigkeit in einer halben Sekunde. Oder wenn es die Hälfte meiner Geschwindigkeit ist, dauert es 2 Sekunden,
bis ich die Höchstgeschwindigkeit erreicht habe. Um die Beschleunigung
in den physikalischen Prozess einzubeziehen, müssen wir
lediglich
den Wert unserer
aktuellen X-Geschwindigkeit in
Richtung Geschwindigkeit multipliziert mit der
Richtung bei einer
Beschleunigungsrate verschieben den Wert unserer
aktuellen X-Geschwindigkeit in
Richtung Geschwindigkeit multipliziert mit Richtung bei einer
Beschleunigungsrate Aber das wird alles
auf einmal in einem einzigen Frame passieren. Um die Geschwindigkeit im Laufe der Zeit anzupassen, müssen
wir das tun, was die
Vorlage
hier tut , indem sie die Schwerkraft anwendet
und mit Delta multipliziert. Da Delta die
Anzahl der Sekunden ist , die seit
dem vorherigen Frame vergangen sind, normalerweise eine 60stel-Sekunde, führt
dies dazu, dass die
Beschleunigungsrate über die Zeit und nicht
auf einmal
angewendet wird über die Zeit und nicht
auf einmal
angewendet Die Funktion move toward nimmt den Inhalt des
ersten Parameters,
bewegt ihn um den Betrag
des
dritten Parameters in Richtung
des Werts des zweiten Parameters und gibt das Ergebnis zurück Sie ändert den Wert
des ersten Parameters nicht, also müssen wir
ihn so zuweisen, dass er
den vorherigen Wert
unserer X-Geschwindigkeit überschreibt den vorherigen Wert
unserer X-Geschwindigkeit Die Funktion „Verschieben und Verschieben ist in der Klasse D für Charakterkörper
2 definiert und
führt alle schwierigen
Berechnungen für uns durch. Dabei werden die Geschwindigkeit der
Figur, äußere Kräfte wie die Schwerkraft und
Kollisionen mit anderen
physikalischen Körpern
berücksichtigt äußere Kräfte wie die Schwerkraft und dann entschieden, wo sich die
Figur in den einzelnen Bildern befinden soll wir das Spiel jetzt ausführen, schrittweise beschleunigt,
bevor wir
unsere Höchstgeschwindigkeit erreichen Außerdem können wir den Wert
unserer Beschleunigung
im Inspektor
anpassen unserer Beschleunigung
im Inspektor es
sich so anfühlt
, wie wir es möchten Wir können diese Kommentare entfernen. Dieselbe Logik kann auf die
Verzögerung angewendet werden, indem einfach eine weitere Variable
hinzugefügt Dieser Wert ist normalerweise viel
höher als die Beschleunigung. Der Code im Physikprozess
verwendet bereits Move Toward. Wir müssen nur Geschwindigkeit
durch Verzögerungszeiten Delta ersetzen Verzögerungszeiten Es gibt jedoch einen anderen Zeitpunkt
, an dem wir vielleicht die
Verzögerung anwenden möchten , außer wenn der Spieler keine
Eingabe macht, wenn er sich
umdrehen und in
die andere Richtung gehen möchte umdrehen und in
die andere Richtung gehen Wir können unsere I-Erklärung erweitern, um diesen
Fall zu berücksichtigen. Nachdem wir überprüft haben, ob die
Richtung nicht Null ist, wenn unsere X-Geschwindigkeit Null ist, steht
der Charakter still, dann
wollen wir trotzdem beschleunigen. Aber wenn die
Richtungssünde der gleiche
ist wie der
Sinus der X-Geschwindigkeit, dann versucht der Spieler, sich in die
gleiche Richtung zu bewegen, in die er
sich bereits bewegt, und wir wollen weiter beschleunigen,
bis die Geschwindigkeit steigt Die Sinusfunktion wandelt
jede Zahl in negative Eins, Null oder positive Eins um, was den Vergleich, ob
diese beiden Werte beide positiv oder
beide negativ
sind, einfacher Wir können Bedingungen
mit oder kombinieren. Wenn also einer dieser
Werte wahr ist, dann ist die gesamte
Aussage wahr. Wenn beide falsch sind, wollen wir
umkehren, was bedeutet, dass wir eine
Verzögerung
anstelle von Beschleunigung anwenden , was zu einer viel schnelleren
Wende
führt, als dies bei einer Beschleunigung der Fall wäre ,
wenn der Wert
der Verzögerung Wenn wir das ausprobieren, sollte es sich jetzt
viel realistischer anfühlen,
unseren Charakter nach links
und rechts zu bewegen , und wir können
die Werte für unsere Geschwindigkeit,
Beschleunigung und Verzögerung einfach im Inspektor anpassen Beschleunigung und Wir sehen uns im nächsten Video.
11. 1-4 Springen: Hallo Freunde. In diesem Video werden
wir die Implementierung
des Sprungs verbessern. Bevor wir
mit dem Springen beginnen, bewege
ich die Kamera entlang der Y-Achse nach
oben sodass sich der Boden am unteren Bildschirmrand befindet, nicht in der Mitte. Das Vorlagenskript
für unseren Charakter hat
bereits eine
Sprungtaste in der Benutzeroberfläche
, mit Ausnahme der Leertaste, die die
Y-Geschwindigkeit des Charakters auf Sprunggeschwindigkeit
setzt. Aber
in einem früheren Video haben wir bereits
unsere eigene Sprungtaste hinzugefügt . Im Gegensatz zu Schwerkraft oder Beschleunigung, die mit Delta
multipliziert und über mehrere Frames
auf den Charakter angewendet werden, wird
diese Sprunggeschwindigkeit
sofort auf den Charakter Beim Ausführen des Spiels können wir die
Leertaste drücken, um zu springen, aber es gibt mehrere Probleme Der Sprung ist immer
gleich hoch und das
Zeichenskript sucht nach Eingaben. Lassen Sie uns dies zunächst
aus dem physikalischen Prozess
des Charakters entfernen und
es stattdessen einer öffentlichen Funktion zuweisen. Wir nennen es Sprung. dann im Spielerskript Wenn wir dann im Spielerskript die Sprungtaste drücken, anstatt Jump zu drucken, können
wir dem Charakter sagen, dass er stattdessen springen
soll. Zugriff auf den
Inhalt des Charakters mit einem Punkt, gefolgt vom
Namen der Funktion, und die Funktion
hat keine Parameter, also nichts
in Klammern Aber jetzt
erlauben wir dem Charakter , jederzeit zu springen, wenn die
Taste gedrückt wird, auch wenn er sich nicht
auf dem Boden Wir müssen zuerst überprüfen, ob
der Charakter auf
dem Boden ist , bevor wir ihn springen
lassen. Diese Funktion auf dem Boden ist in der Klasse D des Charakters
Body Two definiert. Jetzt kann der Charakter nur
springen, wenn er sich auf dem Boden befindet, aber der Sprung hat immer
dieselbe Höhe. In den meisten Spielen springt der
Charakter höher, die Taste gedrückt
hält,
als wenn er einfach gedrückt würde. Manchmal können wir
messen, wie lange die Sprungtaste gedrückt gehalten wird,
bevor wir sie loslassen, diese
Information
dann über
den Sprungfunktionsaufruf weiterleiten , um die Sprungkraft
anzupassen. Aber vor allem bei zwei
D-Plattformspielen erwarten
wir normalerweise, dass Sprünge sofort
passieren, wenn
wir die Taste drücken,
was bedeutet, dass wir nicht warten können bis
die Taste
gedrückt gehalten oder losgelassen wird Stattdessen ist es
üblicher, davon auszugehen, dass
der Sprung
die volle Sprunghöhe erreicht,
und ihn dann abzubrechen wenn der Spieler die Taste
vorzeitig
loslässt So wie wir
im Skript des Spielers auf das Drücken
einer Taste reagiert haben, können wir auch darauf reagieren,
dass sie losgelassen wird. Mit dem Schlüsselwort if wird
dies nur überprüft, wenn die vorherigen Bedingungen falsch
waren. Dadurch
entfällt die Notwendigkeit
, zu überprüfen, ob die Taste gleichzeitig gedrückt
und losgelassen wurde gleichzeitig gedrückt
und losgelassen Wenn die Sprungtaste losgelassen wird, können
wir eine
andere Funktion aufrufen, um den Sprung
abzubrechen und ihn zu
verkürzen Zurück im Zeichenskript müssen
wir die
abgebrochene Sprungfunktion deklarieren, die keine Parameter benötigt
und keinen Wert zurückgibt. Eine einfache Möglichkeit,
dies zu tun, wäre, Y-Geschwindigkeit des Charakters auf Null zu
setzen, aber das kann sich ziemlich
unnatürlich anfühlen , wenn es mitten in der Luft
zum Stillstand kommt Also teile ich stattdessen
die Y-Geschwindigkeit durch zwei. Aber wir wollen, dass
das nur passiert, wenn die Geschwindigkeit des Charakters
derzeit kleiner als Null ist, das
heißt, er
bewegt sich nach oben und nur, wenn seine Geschwindigkeit kleiner als
Null ist, weil er gesprungen Wenn es einen anderen Grund gäbe warum sich der Charakter nach oben bewegt, aber nicht gesprungen ist, würden
wir nicht
zulassen wollen , dass er einen Sprung abbricht und seine Geschwindigkeit
verringert Wir können das kontrollieren, indem wir eine neue Variable
deklarieren. Wir nennen es
Is Jumping vom Typ Boolean, was natürlich
standardmäßig auf False Wenn wir diese Variable auf
true setzen, wenn der Charakter springt, können wir überprüfen, ob der Charakter
springt, bevor wir
ihm erlauben, den Sprung abzubrechen Falls sie den Sprung
nicht abbrechen, müssen
wir die
Variable is jump automatisch wieder auf
false setzen automatisch wieder auf
false Im physikalischen Prozess können wir also
überprüfen, ob die Figur
springt und ob ihre Y-Geschwindigkeit
größer oder gleich Null ist,
was bedeutet, dass die Figur
fällt oder sich zumindest
nicht nach was bedeutet, dass die Figur oben bewegt, dann können wir auf Falsch springen
setzen, weil es für die Figur
zu spät ist , die Taste
loszulassen,
um diesen Sprung abzubrechen. Das funktioniert hervorragend, aber
jetzt möchten wir vielleicht
anpassen, wie hoch die
Figur springen kann. Das Vorlagenskript deklariert die
Sprunggeschwindigkeit als Konstante. Genau wie bei
der Bewegungsgeschwindigkeit können
wir sie in eine Variable umwandeln Aber zu wissen, wie viel
Geschwindigkeit erforderlich ist um eine bestimmte Höhe zu erreichen,
ist nicht sehr intuitiv, und aus gestalterischer Sicht ist
es oft besser, genau
kontrollieren zu können , wie hoch
ein Charakter springen kann. Lassen Sie uns also
eine weitere Variable
namens Sprunghöhe
als Ganzzahl deklarieren . Dies wird in Pixeln gemessen. Ich setze meins auf 256, was der doppelten
Höhe des Charakters entspricht. Mit dem Tag on ready können
wir mit etwas
Mathematik
die Sprungkraft berechnen, die erforderlich ist, um genau diese Höhe zu
erreichen. Das Tag on ready führt diese Zeile des Skripts aus, wenn
der Knoten
bereit ist, bevor die Ready-Funktion
ausgeführt Skripts aus, wenn
der Knoten
bereit ist wird. Ich bin kein Physiker,
daher könnte ich nicht erklären
, warum diese
Gleichung funktioniert, aber sie funktioniert Nimm einfach die Quadratwurzel der Schwerkraft multipliziert mit der
Sprungkraft mal zwei Dann multipliziere das alles
auch mit minus eins, da das Minus
entlang der Y-Achse nach oben zeigt Um dies zu tun, müssen
wir die Schwerkraft, die auf
das Zeichen ausgeübt
wird,
als dezimale Zahl im Wasser kennen das Zeichen ausgeübt
wird,
als . also eine weitere Variable
mit dem Tag on ready deklariert wird, muss sich
diese über
der Jump-Force-Variablen befinden, also wird sie zuerst gesetzt Wir können die
Schwerkraft aus den
Projekteinstellungen ermitteln Wir müssen nur
den Pfad zu der gewünschten Einstellung
in einer Zeichenfolge angeben. Wenn der
Charakter springt, setzen
wir schließlich seine Y-Geschwindigkeit auf
diese berechnete Sprungkraft Jetzt kann der Spieler kontrollieren,
wie hoch er springen möchte. Und wir können die maximale
Sprunghöhe
eines Charakters ganz einfach im Inspektor bearbeiten . Wir sehen uns im nächsten Video.
12. 1-5 Sturz: Hallo Freunde. In diesem Video passen
wir an, wie sich der Charakter in der Luft
fühlt und steuert Unser Charakter kann jetzt höher
springen, fühlt sich
aber sehr schwebend und der Charakter kann seine Bewegung in
der Luft genauso einfach
kontrollieren wie
am Vielleicht möchtest du das für dein Spiel, aber oft hat der Spieler in der Luft
weniger Kontrolle über den
Charakter Im Charakterskript können
wir diese
alten Konstanten entfernen, können
wir diese
alten Konstanten entfernen da sie nirgends mehr verwendet
werden Da unser Skript mehrere Dinge
tut, den Charakter nach links
und rechts
bewegt und springt, wäre
es eine gute Idee, es
zu organisieren Ich lasse meine Variablen für
Bewegungsgeschwindigkeit, Beschleunigung, Verzögerung und Richtung
gruppieren und mache
dasselbe mit
Variablen , die sich auf das Springen
beziehen Wir können sogar Kategorien
für unsere Variablen erstellen, indem das Export-Kategorie-Tag und den Namen
der Kategorie als Zeichenfolge angeben Lassen Sie uns eine separate
Kategorie für Variablen haben auf die Fortbewegung
beziehen,
und eine weitere für das Springen Dadurch werden dem Inspektor Header
hinzugefügt, sodass unsere exportierten Variablen in
diese Kategorien unterteilt
werden Unsere Kategorie „Springen“
hat nur eine Variable, aber wir werden
weitere hinzufügen, angefangen mit einem Gravitationsmultiplikator Dies wird ein Float sein und ich gebe ihm den
Standardwert eins Multiplizieren Sie dann unsere
Schwerkraft mit dem
Schwerkraftmultiplikator , nachdem
Sie ihn aus den Projekteinstellungen abgerufen Da diese Zahl zur Berechnung
der Sprungkraft
verwendet wird , die erforderlich ist, um unsere gewünschte Sprunghöhe zu
erreichen, ändert sich
die
Sprunghöhe des Charakters nicht
und die Kraft
wird automatisch erhöht, und die Kraft
wird automatisch um dies zu kompensieren die Projekteinstellungen öffnen und unter Physik zwei D
nachschauen, unter Physik zwei D
nachschauen, ist die
Standardgravitation auf 980
Pixel pro Quadratsekunde eingestellt Wir können hier die Schwerkraft für
das gesamte Projekt ändern , was sich auf alle unsere
physikalischen Körper auswirkt Wir möchten vielleicht, dass sich einige Dinge schwerer oder
leichter
anfühlen als andere, und eine einfache Möglichkeit,
dies zu tun, besteht darin,
ihre eigene individuelle Schwerkraft
mit einer anderen Zahl zu multiplizieren . Gravitationsmultiplikator unseres Charakters erhöhen springt er schneller und
der Charakter fühlt sich schwerer den Schwerkraftmultiplikator verringern ,
fühlen sie sich
leichter und Als Nächstes können wir
die Kontrolle des Spielers über
den Charakter verringern , indem wir mehr Multiplikatoren
verwenden, allgemein als
Luftsteuerung und Luftbremsen bezeichnet Luftregelung wird verwendet, wenn der Spieler in der Luft
Bewegungseingaben gibt und
Luftbremsen wenn er in der Luft keinen
Bewegungseinfluss gibt. Ich setze beide Werte auf 0,5,
was bedeutet, dass die
Beschleunigung
und Verzögerung des Charakters halbiert werden Im weiteren Verlauf des physikalischen Prozesses können
wir
alles, was
passiert, besser organisieren, indem wir es
in verschiedene Funktionen unterteilen:
eine Funktion, die nur aufgerufen wird, wenn der Charakter auf dem Boden befindet,
und eine, wenn sie nicht auf dem Boden ist Wir werden den Wert
von Delta an beide Funktionen weitergeben. eine separate
Bodenphysik-Funktion definieren, können
wir uns jetzt
darauf konzentrieren, nur
die entsprechende Physik anzuwenden die entsprechende Physik , wenn sich der Charakter am Boden
befindet. Erstellen Sie dann eine weitere Funktion
für die Luftphysik und verwenden Sie diese Funktion, um den Charakter
anders zu
steuern , als
wenn er sich am Boden befindet. Hier werden wir
die Schwerkraft anwenden. Kopiere dann auch die
Steuerung für den Charakter sich bewegt und nicht bewegt,
aus der Bodenphysik. Umdrehen ist in der Luft weniger
wichtig da es keinen Boden
gibt, der für Reibung sorgt Es wäre
also nicht sinnvoll, sich schneller
umzudrehen Wir müssen lediglich die natürliche
Beschleunigung des Charakters mit
dem Multiplikator für
die Luftregelung und
seine Verzögerung mit dem Multiplikator für die
Druckluftbremsen multiplizieren Eine andere Methode besteht darin, dass Sie die
Luftregelung
und die Druckluftbremsen als
alternative Werte betrachten könnten , die Beschleunigung und
Verzögerung
ersetzen, anstatt sie als Multiplikatoren zu , die Beschleunigung und
Verzögerung
ersetzen, anstatt Vielleicht möchtest du auch erwägen, eine Endgeschwindigkeit
hinzuzufügen,
je nachdem, wie stark
der Charakter auf
langen Strecken fallen wird und
ob der Spieler in solchen Situationen eine bessere
Kontrolle haben
muss Eine Endgeschwindigkeit ist die maximale Geschwindigkeit, mit der
sich ein Objekt durch die Luft bewegen kann, da die
Luftwiderstandskraft
irgendwann der Schwerkraft entspricht und sich
gegenseitig ausgleicht. Da wir noch keine richtige Umgebung haben ,
um das zu testen, können wir
nur die Sprunghöhe
des Charakters auf
einen sehr hohen Wert einstellen , vielleicht sogar die Kamera
herauszoomen, damit wir weiter oben sehen können. Aber wir können sehen, dass sich
der Charakter sehr schnell
bewegt, wenn er großen Entfernungen
folgt, und es ist für
den Spieler sehr schwierig , es
mit Genauigkeit zu kontrollieren. Lassen Sie uns also eine weitere Variable
für unsere Endgeschwindigkeit exportieren . In der Erdatmosphäre
erreicht
ein Mensch beim Fallschirmspringen eine Endgeschwindigkeit von
etwa 54 Metern/Sekunde Wenn 100 Pixel 1 Meter sind, dann sind das 5.400
Pixel pro Um diesen Grenzwert in
der Luftphysik-Funktion anzuwenden, können
wir einfach die
Min-Funktion verwenden, um
entweder die
aktuelle Y-Geschwindigkeit des Zeichens
oder die Endgeschwindigkeit zurückzugeben entweder die
aktuelle Y-Geschwindigkeit des Zeichens
oder die Endgeschwindigkeit ,
je nachdem, welcher Wert niedriger ist Weisen Sie dann den zurückgegebenen Wert der Y-Geschwindigkeit des Zeichens
zu Jetzt können wir einfach einschränken, wie schnell der Charakter im Inspektor fallen darf
, sodass der Spieler mehr Kontrolle wenn er
langen Strecken folgt. Ich setze meinen vorerst auf 4.096. Ich sehe dich im nächsten Video.
13. 1-6 Laufen: Hallo Freunde. In diesem Video fügen
wir eine Run-Taste hinzu
, die der Spieler gedrückt halten
kann, um
seine Bewegungsgeschwindigkeit zu ändern. Zuerst setze ich den Zoom
der Kamera und positioniere sie
dort, wo sie vorher war. Die
Bewegungsgeschwindigkeit des Charakters beim Spielen mit der Tastatur
ist immer gleich, aber wir können
die Bewegungsgeschwindigkeit anpassen indem wir
den Analogstick nur teilweise neigen In manchen Spielen reicht das aus,
damit der Spieler
entweder laufen oder rennen In anderen gibt es jedoch
eine spezielle Run-Taste die der Spieler
gedrückt halten kann, um schneller voranzukommen. die Projekteinstellungen öffnen, können
wir unserer Eingabe-Map eine Run-Schaltfläche
hinzufügen. Ich verwende die Umschalttaste oder die rechte Taste
auf meinem Controller. Im Player-Skript
verwenden wir dieselben Funktionen wie beim Sprung, um zu überprüfen, ob
die Run-Taste
gedrückt oder losgelassen wurde. Wenn die Run-Taste gedrückt wird, können
wir dem
Charakter sagen, dass er rennen soll, und wenn wir ihn loslassen, können wir ihm
sagen, dass er laufen soll. Wenn wir schon hier sind, können wir mit der Warnung
umgehen, dass die Prozessfunktion den
Wert von Delta nicht wirklich verwendet. Um
eine bestehende Funktion zu überschreiben, müssen
die Parameter exakt
übereinstimmen, sodass wir
Delta nicht vollständig entfernen können. Stattdessen
würde es die Godot-Engine vorziehen, dass wir
diesen Parameter als unbenutzt markieren diesen Parameter als unbenutzt indem wir seinem Namen
einen Unterstrich voranstellen Alternativ können wir
das Warnfenster öffnen und auf Ignorieren
klicken, um
der Engine mitzuteilen, dass sie
diese Warnung ignorieren soll Jetzt benötigt das
Zeichenskript
diese öffentlichen Funktionen:
Run und Walk. Wir beginnen damit,
zwei weitere exportierte Variablen
in der Kategorie Fortbewegung hinzuzufügen , eine Gehgeschwindigkeit und eine Laufgeschwindigkeit Anschließend kann der Tag der Bewegungsgeschwindigkeit von Export
auf Bereit geändert und der
Wert standardmäßig der
Gehgeschwindigkeit zugewiesen den Funktionen Gehen
und Laufen
eine Deklaration geben ,
keine Parameter akzeptieren und keine Werte zurückgeben, müssen
wir nur den Wert der
Bewegungsgeschwindigkeit auf
Laufgeschwindigkeit oder Gehgeschwindigkeit setzen . Dann
erledigt der physikalische Prozess den Rest indem er den aktuellen
Wert der Bewegungsgeschwindigkeit verwendet. Das ist alles, was Sie brauchen, um die
Bewegungsgeschwindigkeit
unseres Charakters zu ändern , während Sie eine Taste gedrückt halten. Wir könnten dies
leicht rückgängig machen sodass der Charakter standardmäßig
läuft, aber
beim Gehen eine Taste gedrückt halten,
indem wir einfach den
Standardwert für die
Bewegungsgeschwindigkeit auf Laufgeschwindigkeit ändern und das Spielerskript die entgegengesetzten Funktionen
aufrufen lassen. Da diese Lektion so kurz war, bereite
ich mich auch auf das nächste Video vor, indem ich einen Block hinzufüge dem der Charakter
mithilfe eines statischen Körperknotens abspringen kann. A Wir sehen uns im nächsten Video.
14. 1-7 Kojote: Hallo Freunde. In diesem Video helfen
wir dem
Spieler, indem wir Funktionen zur
Barrierefreiheit hinzufügen , die es
unserem Charakter leichter machen ,
ihn zu kontrollieren Ich setze zunächst die Sprunghöhe des Charakters wieder auf einen vernünftigen
Wert zurück In den meisten D-Plattformspielen ermöglicht
das Spiel dem Spieler, für kurze Zeit
die Sprungtaste zu drücken , nachdem
sein Charakter von
einem Felsvorsprung
gegangen ist und
auch, wenn er fällt
und fast landet In beiden Fällen die Funktion
ist auf dem Boden den Wert false zurück, aber es würde
dem
Spieler ein besseres Gefühl geben, wenn er trotzdem einen Sprung ausführen
darf Um diese Funktionen hinzuzufügen, ändern
wir zunächst
den Rückgabetyp
der Sprungfunktion von „
Nichts“ in einen booleschen Wir geben also true zurück, wenn der Sprung erfolgreich war,
oder false, wenn er es nicht war Auf diese Weise kann das Spielerskript
darauf reagieren, dass die
Sprungtaste
zu früh gedrückt wird , und
den Sprung erneut versuchen , nachdem der Charakter auf dem Boden
gelandet zum Spielerskript wechseln, des
Charakters reagieren,
anstatt nur die Punktsprungfunktion
des Charakters aufzurufen können
wir auf den Rückgabewert des
Charakters reagieren,
anstatt nur die Punktsprungfunktion
des Charakters aufzurufen,
indem wir ihn in eine if-Anweisung einfügen Wenn Jump den Wert true zurückgibt, müssen
wir nichts tun, aber wenn es falsch zurückgibt, können
wir davon ausgehen, dass der
Spieler springen möchte, wenn es möglich
wird, falls das relativ bald
passiert. Wenn also nicht jump, wenn jump falsch zurückgegeben hat, dann werden wir
diese Sprungeingabe
für ein kurzes Zeitfenster zwischenspeichern . Der einfachste Weg, die Zeit im Auge zu behalten , ist die Verwendung eines Timer-Knotens. Wir können ihn als
untergeordnetes Element des Player-Knotens hinzufügen, oder da der Player-Knoten keinen bestimmten Typ hat, für den wir ihn verwenden, können
wir seinen Typ
so ändern,
dass er der Timer selbst ist. Wenn wir uns seine Eigenschaften
im Inspektor ansehen, können
wir festlegen, wie
lang der Timer sein soll, also das
Zeitfenster dem die Eingabe
zwischengespeichert wird , und seine
One-Shot-Eigenschaft auf true setzen Das bedeutet, dass
der Timer, wenn er einmal gestartet ist, nur bis zum 01 Mal
herunterzählt Das Standardverhalten wäre, wiederholt bis Null
herunterzuzählen. Als Nächstes deklarieren wir
eine neue Variable. Wir nennen sie gepufferte
Eingabe vom Typ Callable. Callable ist eine Klasse, die
einen Funktionsaufruf mit Argumenten enthält . Wenn unser Sprung also fehlschlägt, möchten
wir unsere
gepufferte Eingabe auf einen
Zeichen-Punktsprung
ohne Klammern setzen , da wir
die Funktion jetzt nicht aufrufen, sondern sie in einer Variablen speichern Und starte auch den Timer. Da wir den Typ
dieses Knotens in einen Timer geändert haben, müssen
wir den Typ des
Knotens, den dieses Skript am Anfang
des
Skripts erweitert, ändern Knotens, den dieses Skript am Anfang
des
Skripts erweitert , um
auf Funktionen
der Timer-Klasse zugreifen zu können . dann in der Prozessfunktion Wenn dann in der Prozessfunktion dieser Timer läuft nicht gestoppt ist, rufen
Sie die gepufferte Eingabe Wenn die gepufferte
Eingabe den Wert true zurückgibt, war sie erfolgreich und
wir können die Zeit anhalten Wenn die gepufferte Eingabe falsch
zurückgegeben hat, kann
dies in diesem Frame
noch nicht geschehen, und wir werden es im nächsten Frame erneut
versuchen bis der Timer
abgelaufen ist oder der Vorgang erfolgreich ist Zu Testzwecken verwenden
wir auch
einige Print-Anweisungen, um
auszudrucken wann der
Sprung gepuffert ist,
wann die gepufferte Eingabe fehlschlägt und Wenn wir das Spiel starten und die Sprungtaste früh
drücken,
wird die Sprungeingabe zwischengespeichert Es schlägt ein paar Mal dann erfolgreich, wenn der
Charakter auf den Boden Wenn wir die Sprungtaste drücken während sich der Charakter
weit oben in der Luft befindet,
wird die Eingabe gepuffert,
aber sie schlägt fehl, bis der Timer
abgelaufen ist , und ist nie Sobald wir mit
der Leistung
unserer Eingabepufferung zufrieden sind , können
wir diese Druckanweisungen entfernen oder
auskommentieren Als Nächstes wollen wir
dem Charakter ermöglichen, zu springen, wenn er kürzlich von einem Felsvorsprung
heruntergelaufen wird allgemein als Coyote Time bezeichnet
und
bezieht sich dabei auf Wiley Coyote bezieht sich dabei auf In der
Charakterszene können wir
einen Timer-Knoten hinzufügen und ihn in Coyote umbenennen Wie beim Eingangspuffer-Timer wird
es sich um einen One-Shot-Timer handeln, und wir können die
Dauer des Timers anpassen die Charakterszene
im Charakterskript geöffnet ist, können
wir einen Verweis auf
einen beliebigen untergeordneten Knoten abrufen indem wir die
Strg- oder Befehlstaste gedrückt halten, dann auf
den Knoten klicken und ihn in das Skript ziehen Dadurch wird automatisch eine Variable
mit demselben Namen erstellt und ihr Wert
mithilfe des Tags
on ready festgelegt . Dabei wird die Notation des Knotenpfads verwendet, die mit dem 1$-Zeichen
beginnen Verwendung dieser Notation im Dollarzeichen setzt voraus, dass dieser Knoten mit dem exakten Knotenpfad
relativ zu dem Knoten
existieren muss mit dem exakten Knotenpfad
relativ zu dem Knoten
existieren , an den
dieses Skript angehängt ist. Andernfalls wird ein Fehler
verursacht. Diese
Kojotenzeit ist jedoch eine Funktion, die im Allgemeinen nur für den
Spielercharakter gilt Möglicherweise
möchten wir diesen Knoten nicht
in jeder Charakterszene haben in jeder Charakterszene Wir können also die
Funktion get node or
null verwenden , die denselben
Knotenpfad als String-Argument weitergibt. Diese Funktion
gibt entweder einen Verweis auf
den Knoten zurück, der
diesem Knotenpfad folgt , oder null, wenn er nicht
existiert, ohne Fehler zu
verursachen. In der Sprungfunktion überprüfen
wir nun, ob
ein Sprung möglich
ist , entweder ob sich
der Charakter auf dem Boden befindet oder ob
der Charakter
einen Kojoten-Timer hat und der
Kojoten-Timer nicht gestoppt ist Boden befindet oder ob
der Charakter
einen Kojoten-Timer hat und der
Kojoten-Timer Bei Logikoperationen und wird vor oder sofern
du keine Klammern verwendest ,
ausgewertet In Bezug auf die A-Anweisung wird
die linke Seite
vor der rechten Seite geprüft. Wenn also der
Coyote-Timer nicht existiert, wird
die A-Aussage als
falsch angesehen Es wird also nicht geprüft, ob
der Coyote-Timer auf
der rechten Seite
läuft oder nicht Coyote-Timer auf
der rechten Seite
läuft Jetzt müssen wir nur noch den
Coyote-Timer starten. Dazu müssen wir wissen, wann der Charakter einen
Felsvorsprung verlässt Ich betrachte das als Teil der Kategorie
Springen, und wir werden
zwei neue Variablen deklarieren Ist auf Floor, um
den Rückgabewert
der Funktion I on floor
für diesen Frame zu speichern den Rückgabewert
der . diese Weise können wir diese Prüfung einmal pro
Frame
durchführen und die Ergebnisse
speichern ,
sodass wir sie mehrmals verwenden können ,
sodass wir sie mehrmals verwenden können. Dadurch müssen wir die
Funktion nicht mehrmals pro
Frame aufrufen und war auf Floor, was den Wert von is on floor aus
dem vorherigen Frame enthält. Während des physikalischen Prozesses setzen
wir den Wert von was
on floor auf is on floor dann is on floor auf den von
der Funktion is on floor zurückgegebenen Wert. Alle anderen Aufrufe der Funktion
is on floor können stattdessen unsere Variable verwenden
, um effizienter zu sein. Wenn die Figur dann
im vorherigen
Bild auf dem Boden
war und sich nicht auf
dem Boden dieses Frames befindet und ihre Y-Geschwindigkeit
größer oder gleich Null ist,
was bedeutet, dass sie nicht gesprungen ist,
ist
die einzig logische Schlussfolgerung, dass diese
Figur von einem Felsvorsprung die einzig logische Schlussfolgerung gegangen ist oder Boden,
auf dem sie stand, verschwunden ist, und das ist genau der Moment wann der
Coyote-Timer starten sollte. Zu Testzwecken
fügen wir Print-Anweisungen hinzu, damit wir wissen, wann der Coyote-Timer startet und wann
ein Coyote-Sprung ein Coyote-Sprung Dazu ist eine
redundante if-Anweisung erforderlich, wir
jedoch später entfernen werden Okay. Ich lasse das Spiel laufen, um es zu testen. Wir können von einem Felsvorsprung heruntergehen und sehen, dass der
Coyote-Timer Wenn wir die Sprungtaste drücken während der
Coyote-Timer läuft, darf der Charakter trotzdem einen Sprung Wir haben jetzt eine solide
Toti-Plattform und Im nächsten Abschnitt werden wir den Charakter zeichnen und animieren Wir sehen uns im
nächsten Abschnitt.
15. 2-1 Sprite: Hallo Freunde. In diesem Abschnitt nehmen
wir
unser einfaches Gadot-Symbol und polieren es zu einem
vollständig animierten Charakter Dafür benötigen wir
Assets, Bilder und Audiodateien Die Dateien, die ich verwende sind enthalten, wenn du sie verwenden
möchtest, aber ich empfehle
fortgeschrittenen Schülern deine eigenen oder
andere kostenlose Dateien
zu verwenden. Bevor wir mit dem
Import von Assets beginnen, ist
es eine gute Idee,
einen separaten Ordner für sie zu erstellen . Wir können auch
verschiedene Unterordner für
verschiedene Arten von Assets wie
Spritesheets und Soundeffekte erstellen verschiedene Arten von Assets wie Spritesheets und Soundeffekte Klicken Sie auf den Ordner in dem sich
Ihre importierten Assets befinden sollen, klicken Sie
dann einfach auf
die Assets und ziehen Sie sie in
das Gadot-Fenster Der Importvorgang
erfolgt automatisch und sie werden
in den ausgewählten Ordner sortiert Wenn sie sich nicht
im richtigen Ordner befinden, können
Sie sie jederzeit in
die Registerkarte Dateisystem ziehen , um sie ebenfalls
neu zu organisieren Dadurch wird jedoch ein erneuter Import
ausgelöst.
Daher ist es besser, sie zunächst
in den richtigen
Ordner zu importieren , insbesondere bei größeren Dateien Öffne deine Charakterszene
, falls sie nicht schon geöffnet ist. Diese Elemente zum Zeichnen
der Figur zu verwenden , könnte
so einfach sein wie das Ersetzen des Gadot-Symbols durch Ihre
importierte Bilddatei wenn Ihre Assets nur
ein Sprite pro Datei haben Die von mir verwendeten Elemente sind in einem Spritesheet
organisiert, sodass es mehrere
Sprites in einer einzigen Textur gibt, was ich nicht zeichnen Mithilfe der Dropdownliste können wir andere Arten von Texturen
auswählen, und die für die
Verwendung eines Spritesheets wird Atlas-Textur genannt auf die
Atlas-Textur klicken, um sie zu erweitern können
wir sie direkt
hier im Inspektor bearbeiten Das
Spritesheet als Atlas zuweisen. Wir können dann die
Region des Atlas bearbeiten,
die anhand der Atlas-Textur gezeichnet wird Wenn wir einen Bereich des Spritesheets auswählen,
den wir verwenden möchten, können
wir die
Auto-Slice-Funktion verwenden, um
ein einzelnes Sprite oder ein
einzelnes Pixel auszuwählen ein einzelnes Sprite oder ein
einzelnes Pixel , um auf einen bestimmten Bereich zu klicken und
ihn zu ziehen Da diese Sprites alle
gleichmäßig groß und gleichmäßig verteilt sind, verwende
ich diesen Bereich mit 32 mal 36 Pixeln Wenn Sie das Sprite ändern, sich Breite und Höhe Nur die X- und Y-Position werden um
einheitliche Werte erhöht Das macht es viel einfacher
, den Charakter zu animieren. Bevor Sie sich dazu entscheiden,
eine Reihe von Elementen zum
Animieren einer Figur zu verwenden , kann
es sich lohnen, Ihr Spritesheet so zu
bearbeiten,
dass dieser gleichmäßige Abstand eingehalten wird, um Zeit und Mühe zu
sparen Ich bewege das Sprite nach unten,
sodass es auf der X-Achse liegt. Seine Y-Position entspricht jetzt der Hälfte der
Höhe der Sprite-Region. Da wir nun eine genaue
visuelle Darstellung
unseres Charakters haben , können
wir
die Kollisionsform besser anpassen Wir können die
untergeordneten Knoten neu anordnen, um
die Kollisionsform über dem
Charakter-Sprite zu zeichnen die Kollisionsform über dem , um die Sache zu
vereinfachen Ich verwende eine Kapselform
und mache sie groß genug um den Kopf, aber
nicht die Ohren und den Körper einzuschließen, aber nicht unbedingt die
Arme, den Schwanz oder Dies wird verwendet, um
mit der Umgebung zu kollidieren,
sodass alles, was sich außerhalb
der Kollisionsform mit den
Wänden, der Decke oder dem Boden überlappt Achte darauf, dass deine
Kollisionsform und dein Sprite um
die Y-Achse zentriert bleiben und
bequem auf der X-Achse sitzen ,
als wäre es der Boden Wenn sich die Größe deines Charakters erheblich
ändert, wirst
du
wahrscheinlich die Werte
seiner Variablen für Dinge wie
Bewegungsgeschwindigkeit und Sprunghöhe ändern seiner Variablen für Dinge wie Bewegungsgeschwindigkeit und Sprunghöhe Wir können auch mathematische
Gleichungen in diese Felder eingeben , und die Engine
bestimmt das Ergebnis für uns. Aber ich ordne die Kollisionsform so
an, dass sie sich
wieder hinter dem Sprite Wenn das Zeichen auf der Y-Achse
zentriert ist, links oder rechts müssen wir
lediglich den Wert der Variablen „Horizontal umkehren“
im Sprite-Two-D-Knoten
ändern, damit
der
Charakter nach Variablen „Horizontal umkehren“
im Sprite-Two-D-Knoten
ändern, damit
der zum
Zeichenskript wechseln, nehmen
wir einen Verweis auf den
Sprite-Two-D-Knoten und speichern ihn in einer Variablen, indem wir die Strg- oder
Befehlstaste
gedrückt halten und
ihn in das Skript ziehen Dann deklarieren wir eine öffentliche
Funktion namens face left, keine Parameter
akzeptiert
und keinen Wert zurückgibt Die aktuelle
Absicht besteht zwar darin, diese Funktion nur privat
in diesem Skript zu verwenden, Sie können sich wahrscheinlich vorstellen,
dass es in einem öffentlichen Kontext
nützlich sein könnte
, einem Charakter zu sagen , dass er in eine Richtung schauen soll. Um nach links zu schauen,
müssen wir lediglich
den Wert der Eigenschaft Flip H des Sprites auf true Wir könnten auch eine andere
Funktion namens face right schreiben, aber die Funktion
würde nur
den Wert dieser
Variablen wieder auf False setzen den Wert dieser
Variablen wieder auf False Manchmal ist es einfacher,
unsere Funktionen zu schreiben , um flexibler zu
sein. Anstatt sowohl die Funktionen „Gesicht
links“ als auch „Gesicht nach rechts“ zu verwenden, können
wir der
Funktion „Gesicht links“ einen Parameter geben , mit dem sie beide Funktionen ausführen kann. Ich nenne sie einfach left und gebe ihr den Standardwert true. Wenn Sie einem Parameter einen
Standardwert geben, ist er optional. Diese Funktion
mit dem Namen face left
kann also ohne
Angabe von Argumenten aufgerufen werden, und wir gehen davon aus, dass
sie nach links zeigen wollen. Wir können dann den Wert von
flip H auf den Wert von left setzen. Damit das Zeichen
nach rechts zeigt, müssen wir nur
face left aufrufen, aber
false als Argument angeben ,
anstatt eine völlig
andere Funktion aufzurufen. die
Richtung eines Charakters in der Physik Wenn die
Richtung eines Charakters in der Physik negativ ist, möchte er nach links schauen. Und wenn es positiv ist, dann wollen sie nach links schauen,
nicht nach links, sondern nach rechts. Wenn die Richtung Null ist, sie weiterhin in
dieselbe Richtung wie im vorherigen Bild. Um meinen kleinen Charakter besser sehen
zu können, zoome ich die Kamera
um den Faktor vier und positioniere sie neu, sodass sich der Boden am unteren Bildschirmrand
befindet O. Wenn wir auf „Abspielen“ klicken, wird
der Charakter gezeichnet und
sein Sprite wird umgedreht, sodass er in
die richtige Richtung zeigt, aber er wird immer noch nicht
animiert Ich möchte, dass mein
Charakter schneller ist, also werde ich seine
Werte in der Charakterszene erhöhen Werte in der Charakterszene Wir sehen uns im nächsten Video.
16. 2-2 Animations-Player: Hallo Freunde. In diesem Video werden
wir unserem Charakter
Animationen hinzufügen. Wenn dein Charakter keinen Animations-Player-Knoten hat, solltest
du jetzt einen hinzufügen. Wenn der
Animations-Player-Knoten ausgewählt ist, sollte
der Animations-Tab automatisch
erweitert werden. Wenn sie nicht geöffnet ist, können Sie
sie öffnen , indem Sie auf die
Animationsschaltfläche klicken. Das Animationsfenster ist derzeit leer, da noch
keine Animationen vorhanden sind. auf die Schaltfläche
Animation klicken, wählen
wir Neu aus, um
eine neue Animation zu erstellen und sie als inaktiv zu bezeichnen. Wenn eine Animation ausgewählt ist, gibt es jetzt eine Zeitleiste, die in Sekunden
gemessen wird. Wenn Sie möchten, können Sie
die Sekunden in
Bilder pro Sekunde ändern die Sekunden in
Bilder pro Sekunde Die Zeitleiste wird dann stattdessen in Bildern
angezeigt. die Frames sehr
nahe beieinander liegen, Da die Frames sehr
nahe beieinander liegen, zoome ich heran, um die
Frames weiter voneinander
entfernt anzuzeigen . Wir können auch die
Bildrate ändern. Ich stelle meins auf 12
Bilder pro Sekunde ein. Es ist auch hilfreich, mit diesem Schalter
das Einrasten auf den
Timeline-Cursor anzuwenden mit diesem Schalter
das Einrasten auf den
Timeline-Cursor Wenn wir jetzt durch
die Animationszeitleiste blättern, wird
sie automatisch auf das nächste Bild ausgerichtet In diesem Bereich
können wir
der Animation Spuren hinzufügen, indem wir
auf die Plus-Schaltfläche klicken Am gebräuchlichsten ist
ein Eigenschaften-Track, mit
dem wir
jede Eigenschaft eines beliebigen Knotens im Szenenbaum im Laufe
der Zeit bearbeiten können . Der Knoten, den wir animieren wollen,
ist der Sprite-Ti-Knoten, genauer gesagt seine
Textureigenschaft Dadurch wird
der Animations-Timeline eine Spur hinzugefügt ,
und auf dieser Spur können
wir Keyframes hinzufügen, um
der Eigenschaft zu diesem Zeitpunkt einen neuen
Wert zuzuweisen der rechten Maustaste auf die Spur klicken, können
wir Key einfügen auswählen, um dieser Spur einen Keyframe
hinzuzufügen Standardmäßig entspricht der Wert dieses Keyframes dem aktuellen Wert. Dies ist dieselbe Textur, auf die wir ihn im
vorherigen Video eingestellt haben Das ist gut genug für
einzelne Sprite-Dateien, da wir hier einfach
die Textur ändern können Aber da ich
ein Spritesheet verwende, möchte
ich die Textur eigentlich nicht ändern Ich möchte nur den Bereich
der Textur ändern , der verwendet
wird Es gibt mehrere
Möglichkeiten, dies zu tun. Eine Möglichkeit besteht darin, auf
die Eigenschaftenspur zu klicken und ihren Eigenschaftsnamen zu
bearbeiten, indem Sie einen Doppelpunkt und das
Wort Region nach der Textur hinzufügen. Dadurch wird der Animation mitgeteilt
, dass ich die Bereichseigenschaft
der Textur
bearbeiten möchte , nicht die Textur selbst. Ich setze die Animation
zurück, sodass sie vorerst leer ist. Stellen Sie sicher, dass der
Animation-Player-Knoten in der Szenenstruktur
ausgewählt ist, und wählen Sie
dann den
Sprite Two D-Knoten die
Atlas-Textureigenschaft erweitern, können
wir ihre Eigenschaften
in einem verschachtelten Fenster sehen mit der Maus über den Eigenschaftsnamen
der
Region fahren, wird im Popup-Fenster
der Name der Immobilie angezeigt Dies ist hilfreich, um
sicherzustellen, dass Sie die genaue Groß- und Kleinschreibung und Schreibweise kennen
, wenn Sie versuchen, über den Code oder
den
Namen des Animationstracks
darauf zuzugreifen, wie wir es gerade getan haben Die zweite Methode zum Hinzufügen von
Eigenschaftstracks zu einer Animation,
die viel einfacher ist, besteht jedoch Eigenschaftstracks zu einer Animation, darin die Tastentaste
rechts neben der Eigenschaft zu
verwenden. Diese Schaltfläche ist nur verfügbar, wenn
der Animation-Player-Knoten
zuvor
in der Szenenstruktur ausgewählt wurde . Eine Animation ist gerade geöffnet, und dann wird ein anderer Knoten in
der Szenenstruktur ausgewählt. Wenn Sie auf diese Schaltfläche klicken,
wird
der aktuellen Animation an der Position des
Timeline-Cursors ein Keyframe hinzugefügt der aktuellen Animation an der Position des
Timeline-Cursors wir zum ersten Mal einen Keyframe für
eine Eigenschaft
hinzufügen , für die es
derzeit keine Spur
in der Animation gibt, fragt uns
Godot, ob wir dafür eine Spur erstellen
möchten Und wenn wir
diesen Track zur
Reset-Animation hinzufügen wollen , werden
wir zu beiden Ja sagen Dadurch wird der Track
zur Animation hinzugefügt und gleichzeitig der erste
Keyframe Wenn Sie auf den
Namen der inaktiven Animation klicken ,
um das Drop-down-Menü zu erweitern, wird auch die
Reset-Animation erstellt Weise speichert GoDo die Standardwerte
der Eigenschaften Auf diese Weise können Probleme
beim Ausführen von Animationen
im Editor
und beim dauerhaften
unbeabsichtigten Ändern
der Eigenschaftswerte vermieden beim Ausführen von Animationen
im Editor
und beim dauerhaften
unbeabsichtigten Ändern der Eigenschaftswerte Godot setzt alle
Eigenschaften auf
die
in dieser Reset-Animation angegebenen Standardwerte zurück die
in dieser Reset-Animation angegebenen Standardwerte Um dies reibungsloser zu gestalten,
versuchen Sie, Animationen immer
Eigenschaftenspuren hinzuzufügen , wenn sie sich in
ihrem Standardstatus befinden Jetzt sind wir bereit, den
eigentlichen Animationsprozess zu starten. Sie sollten entweder eine
Texturspur zum Ändern einzelner Sprites oder
eine Texturbereichsspur zum Ändern von Sprites
innerhalb eines Spritesheets Ihre Assets können auch
unterschiedliche Spritesheets
für unterschiedliche Animationen verwenden unterschiedliche Spritesheets
für unterschiedliche diesem Fall
benötigen Sie außerdem einen Track
sowohl für die Atlas-Textur als auch für den
Texturbereich Alles, was wir tun müssen, ist, in der
Timeline einen Frame
vorwärts zu scrubben , dann
entweder den Wert der Textur oder des Texturbereichs zu bearbeiten und auf
die Tastentaste zu klicken , um
einen weiteren Keyframe hinzuzufügen und Da ich weiß, dass alle
meine Sprites dieselbe Größe und gleichmäßige Abstände haben, kann
ich
das noch einfacher machen, indem ich einfach
neue Keyframes einfüge, als die X-Eigenschaft manuell zu
bearbeiten und sie für jedes Bild zu erhöhen Wenn wir diese Animation testen, die Engine davon aus,
dass wir die Werte dieser Eigenschaften zwischen
den Keyframes verknüpfen möchten Werte dieser Eigenschaften zwischen
den Keyframes verknüpfen Da die Bildrate
des gesamten Spiels
60 Bilder pro Sekunde beträgt, beträgt diese Animation
jedoch
12 Bilder pro Sekunde Die Engine erzeugt
vier zusätzliche Frames zwischen jedem Keyframe, um einen reibungsloseren Übergang zu
erzielen Offensichtlich ist das nicht das, was wir bei einer Sprite-Animation wollen, also müssen wir
den Aktualisierungsmodus für
diesen Track von
kontinuierlich auf diskret umstellen diesen Track von
kontinuierlich Jetzt
ändert sich die Eigenschaft nur, wenn die Animation ein Keyframe
trifft, und der Wert wird sofort
geändert Die Animation ist zu lang, daher müssen wir
die Anzahl der Frames der
Animation so einstellen , dass sie
nach dem letzten Keyframe endet Diese Animation muss
ebenfalls wiederholt werden. Klicken Sie
also auf die
Schaltfläche für die Animationsschleife Klicken Sie
also auf die
Schaltfläche für die Animationsschleife , sodass das
Looping-Symbol blau ist Wenn du noch einmal darauf klickst, wird
es auf Ping Pong gesetzt, was eine andere
Art von Looping ist Bei Charakteranimationen wollen wir generell Vorwärtsschleifen Es ist eine gute Idee, die
zurückgesetzten
Animationsspuren auch auf
diskret zu setzen, falls
Sie
damit einen Charakter
per Skript zurücksetzen möchten damit einen Charakter
per Skript zurücksetzen Diese inaktive Animation
ist jetzt abgeschlossen, und wir können mit der Erstellung der restlichen Animationen fortfahren ,
die wir für
unsere Plattform und unseren Charakter benötigen. auf die
Animationsschaltfläche klicken, können
wir eine neue Animation hinzufügen
und von vorne beginnen, oder wir können
diese inaktive Animation duplizieren und als Vorlage
verwenden. Da ich weiß, dass meine
Sprites gleichmäßig verteilt sind, muss
ich nur
die Y-Eigenschaften
meiner Keyframes bearbeiten, um
von Idle- zu Walk-Frames zu wechseln Wir können Schlüssel kopieren und einfügen,
um die Arbeit zu vereinfachen. Eine Linie, die zwei Schlüssel verbindet ,
bedeutet, dass sich die Werte zwischen ihnen nicht
ändern. Wenn ich die
laufende Animation mache, verdoppele ich einfach
die Bildrate. Wir können
Tasten anklicken und ziehen , um sie
entlang der Timeline zu bewegen. Ich muss auch springende
und fallende Animationen erstellen. Je nachdem, welche
Elemente Sie verwenden, müssen
Sie möglicherweise
unterschiedliche Animationen erstellen. Möglicherweise
benötigen Sie beispielsweise Animationen für Starthilfen,
Idle-Jump, Fall-Idle-Animationen oder Landing-Animationen. Stellen Sie sicher, dass Sie wissen
, welche Animationen wiederholt werden
müssen und welche nicht. Jetzt hat der Charakter
alle Animationen, aber sie stecken in
der inaktiven Animation fest. Also müssen wir dem Charakter
sagen, wann er zu
anderen Animationen wechseln soll. Wir sehen uns im nächsten Video.
17. 2-3 Animationsbaum: Hallo Freunde. In diesem Video steuern
wir
mithilfe eines Animationsbaums, welche
Animation
im Animation-Player abgespielt wird . Wenn deine
Charakterszene keinen Animationsbaumknoten hat, solltest
du jetzt einen hinzufügen. Der
Animationsbaum
dient dazu, den
Animations-Player zu steuern und zu
entscheiden, welche Animation zu einem bestimmten Zeitpunkt
abgespielt werden soll. also der Animationsbaumknoten Wenn also der Animationsbaumknoten im Szenenbaum im Inspektor
ausgewählt ist, setzen
wir seine
Animations-Player-Eigenschaft
auf unseren Animations-Player-Knoten . Die Eigenschaft tree root ist eine
Ressource, die verwendet wird, um zu bestimmen, welche
Animation vom Animations-Player-Knoten
abgespielt wird . auf das Drop-down-Menü klicken, wir auf das Drop-down-Menü klicken, stehen uns hierfür verschiedene
Optionen zur Verfügung, von denen die
meisten
besser geeignet sind wenn Sie drei D
- oder Bone-Animationen verwenden, denen häufig mehrere
Animationen miteinander kombiniert werden. Da es sich um ein
einfaches Zwei-D-Sprite handelt, verwenden
wir eine Zustandsmaschine auf unsere neue
Zustandsmaschine klicken, öffnen wir den Animationsbaum
am unteren Rand
des Editorfensters mit einer
Zustandsmaschine, die zur Bearbeitung geöffnet Unsere Zustandsmaschine hat derzeit einen Startknoten und einen Endknoten. Diese sind nicht identisch mit
den Knoten im Szenenbaum, sondern sind Knoten im
Kontext eines Knotengraphen. Wir können in einen leeren
Bereich klicken, um weitere Knoten hinzuzufügen. Fügen wir die inaktive
Animation als Knoten hinzu. Wir können auf diese Knoten klicken und sie
verschieben ,
um
sie nach Belieben zu organisieren. Ihre Positionen in
diesem Raum sind irrelevant. Wenn wir unseren Bearbeitungsmodus von auswählen und verschieben,
um Knoten miteinander zu verbinden, können
wir durch Klicken und Ziehen
von einem Knoten zum anderen wechseln, wodurch ein Pfeil entsteht, der sie in einer Richtung
verbindet. Dies ist ein Übergang
vom Startknoten zum inaktiven Knoten. Wenn also die
Zustandsmaschine gestartet wird, wechselt
sie
sofort zum inaktiven Knoten, wodurch der Animationsspieler
angewiesen die inaktive Animation abzuspielen. den Bearbeitungsmodus zurückschalten,
um Knoten auszuwählen und zu verschieben, fügen
wir nun auch die Walk- und
Run-Animationen hinzu. Und wenn Sie wieder zum
Verbinden von Knoten zurückkehren, schaffen Sie einen Übergang von Idle
zu Walking und Walking to Run. Wenn diese Zustandsmaschine gestartet wird, geht sie sofort vom
Startknoten zum Run-Knoten über. Deshalb möchten wir
diesen Übergängen Bedingungen hinzufügen , um einzuschränken , wann dieser Übergang
stattfinden darf. Wenn Sie den Übergang
von Idle zu Walk auswählen, erweitern Sie den Bereich „Weiter“. Unter dem erweiterten
Ausdruck befindet sich ein Textbereich. Hier können wir einen beliebigen
logischen Ausdruck angeben, mit dem wir steuern
möchten, wann dieser
Übergang stattfinden darf,
solange das Ergebnis ein boolescher Wert, wahr oder falsch ist solange das Ergebnis ein boolescher Wert, wahr oder falsch In diesem Fall wollen wir die Walk-Animation
abspielen, wenn die X-Geschwindigkeit der Figur etwas anderes als Null
ist Das ermöglicht also das
Gehen sowohl nach links als auch nach rechts. Dieser Ausdruck wird auf dem Knoten
geprüft, den wir in den Eigenschaften
des Animationsbaumknotens,
dem Basisknoten für erweiterte
Ausdrücke,
angeben . diesen Knoten als
Wurzelknoten der Szene festlegen, also D-Node für
den Körper der Figur, können
wir die
Animationszustandsmaschine
automatisch auf die Geschwindigkeit der
Figur reagieren automatisch auf die Geschwindigkeit der
Figur , um die Animation zu ändern. zur Zustandsmaschine zurückkehren vom Gehen zum Laufen
wechseln, wollen
wir überprüfen, ob
der absolute Wert
der X-Geschwindigkeit der Figur größer
ist als die Gehgeschwindigkeit der
Figur Möglicherweise möchten Sie
einen anderen Schwellenwert angeben, indem beispielsweise festlegen, dass
der Absolutwert der X-Geschwindigkeit gleich der
Laufgeschwindigkeit oder höher als
der Durchschnitt der Geh- und
Laufgeschwindigkeit usw. sein muss Laufgeschwindigkeit oder höher als . Jetzt müssen wir einen Übergang vom Gehen
zurück zum Leerlauf hinzufügen. Beim Erstellen von Übergangsschleifen zwischen zwei oder mehr Knoten in
einer solchen Zustandsmaschine die Bedingungen
aller Übergänge dürfen
die Bedingungen
aller Übergänge nicht alle
gleichzeitig zutreffen. Dies würde
es
der Zustandsmaschine unmöglich machen , zu entscheiden , welcher Status gerade aktiv
sein soll, da sie einfach auf unbestimmte Zeit zwischen
den Zuständen hin- und herschalten wird Da die Bedingung für den
Übergang von Idle zu Walking darin besteht, dass die X-Geschwindigkeit
etwas anderes als Null ist, sollte der Übergang
von Walk zu Idle der Fall sein, wenn die
X-Geschwindigkeit gleich Null ist Diese beiden Bedingungen können nicht gleichzeitig erfüllt
sein,
sodass die Zustandsmaschine nicht in einer Schleife zwischen
diesen beiden Zuständen
stecken bleiben kann Schleife zwischen
diesen beiden Zuständen
stecken bleiben dieselbe Logik auf den
Übergang von Laufen zu Laufen angewendet wird, müssen
die Bedingungen für diesen
Übergang
logisch inkompatibel mit
dem Übergang von Gehen zu Laufen Wenn also der absolute Wert
der X-Geschwindigkeit des Charakters kleiner oder gleich der Gehgeschwindigkeit des
Charakters ist, wird
dies niemals
gleichzeitig zutreffen wie größer als Wenn wir das Spiel starten, beginnt die
Zustandsmaschine
am Startknoten und bewegt sich
entlang von am Startknoten und bewegt sich Übergängen zwischen
verschiedenen Zuständen, jeder Zustand
eine oder mehrere Animationen darstellt. In einigen Fällen
kann die Zustandsmaschine zum Endknoten übergehen. In diesem Fall
funktioniert es nicht mehr. Wenn wir unseren Charakter animieren, wollen
wir nie, dass diese
Zustandsmaschine den Endknoten erreicht, also gibt es keinen Übergang, der dorthin
führt Das funktioniert so, dass
die Figur im Leerlauf,
beim Gehen und Laufen
nach links oder rechts animiert wird, aber wir müssen auch
Animationen für das Springen hinzufügen Wenn wir hier die
Sprunganimation hinzufügen würden, müssten
wir der Sprunganimation
Übergänge aus all unseren bestehenden Zuständen hinzufügen
, da die Figur
aus jedem dieser Zustände springen kann Das wird sich verheddern,
chaotisch und schwierig zu handhaben sein,
vor allem, wenn dein Charakter mehrere verschiedene
Sprunganimationen
hat Stattdessen können wir eine verschachtelte Zustandsmaschine
erstellen. Wir beginnen damit,
unseren aktuellen Zustandsmaschine
als Projektressource zu speichern unseren aktuellen Zustandsmaschine
als Projektressource Nennen wir es Fortbewegung. Dann ersetze diese
Zustandsmaschine durch eine neue. in unserer neuen leeren Zustandsmaschine rechten Maustaste in einen leeren
Bereich und wählen Sie Laden aus. Suchen Sie die
Locomotion-Zustandsmaschine und fügen Sie sie der neuen
Zustandsmaschine als einzelnen Knoten hinzu. Benennen Sie sie um, sodass Sie wissen
, dass es die
Locomotion-Zustandsmaschine handelt Fügen Sie dann einen Übergang
vom Start zur Fortbewegung hinzu. Die gesamte
Locomotion-Zustandsmaschine besteht nun einem einzigen Knoten, den
wir öffnen können indem wir auf die
Schaltfläche Bearbeiten mit einem Bleistiftsymbol Die Idle-Animationen „Walk“ und „
Ausführen“
wechseln immer noch wie zuvor, aber jetzt sind sie in
einer größeren Zustandsmaschine verschachtelt Wir können zur
anderen Zustandsmaschine zurückkehren, indem wir auf die Semmelbrösel klicken In dieser Zustandsmaschine fügen
wir alle
Animationen hinzu, die sich auf das
Springen beziehen, und verbinden
sie mit Übergängen So sieht eine Endlosschleife in einer Zustandsmaschine aus. Wir möchten, dass der Charakter
aus einem beliebigen Bewegungszustand wechselt um zu springen, wenn seine Y-Geschwindigkeit kleiner als Null
ist,
was bedeutet, dass er sich aufwärts bewegt Wenn ihre Y-Geschwindigkeit
größer oder gleich Null ist, hat
sie den
Höhepunkt ihres Sprungs erreicht, und ich wechsle
zur Fallanimation Gehen Sie dann
vom Fallback zur Fortbewegung über, wenn sich der
Charakter auf dem Boden befindet Wir können die Funktion aufrufen oder
unsere private Variable verwenden , die wir zuvor erstellt haben Vielleicht möchten wir das
Springen überspringen und direkt
zum Fallen übergehen , wenn der Charakter von einem Felsvorsprung
heruntergeht Fügen wir das also als
weiteren Übergang hinzu, vorausgesetzt
, dass sich der Charakter nicht mehr auf dem Boden befindet Dadurch entsteht ein Konflikt in unserer Zustandsmaschine, wenn der Charakter in einem
Fortbewegungszustand befindet und springt Ihre Geschwindigkeit ist beide kleiner als Null und sie
liegen nicht auf dem Boden Welchen Übergang sollte
die Zustandsmaschine also verwenden? In Fällen wie diesem
können wir unseren Übergängen
Vorrang vor anderen einräumen, indem wir
ihre Prioritätseigenschaft herabsetzen. Wenn der Charakter springt, ist
seine Y-Geschwindigkeit kleiner als Null und er befindet sich nicht auf dem Boden Dem Übergang zum
Sprung wird jedoch Priorität eingeräumt. Das ist also der Übergang
, der genutzt werden wird. Wenn der Charakter von einem Felsvorsprung
heruntergeht, ist
seine Geschwindigkeit
größer als Null und er befindet sich nicht auf dem Boden, es gibt
also keinen Konflikt Unser
2-D-Jump'n'Run-Charakter ist jetzt animiert, aber wir können dafür sorgen, dass er sich
viel besser anfühlt , indem wir mehr
Feinschliff hinzufügen Wir sehen uns im nächsten Video.
18. 2-4 Soundeffekte: Hallo Freunde. In diesem Video werden
wir unserem animierten Charakter Soundeffekte
hinzufügen . Dazu müssen wir
einige Sounddateien
in unser Projekt importieren , sortiert in einen
entsprechenden Ordner. Ich werde einige
Soundeffekte hinzufügen, mit denen Sie dieser Lektion folgen
können,
aber ich empfehle Schülern
mit fortgeschrittenem ihre eigenen oder kostenlosen Ressourcen zu
verwenden. Zuerst werde ich
den statischen Körperknoten entfernen, bei dem dieses weiße Rechteck
handelt, da
ich es nicht mehr verwende. zunächst einen
Player Two-D-Knoten für Audiostreams hinzu Player Two-D-Knoten Ihrer Charakterszene zunächst einen
Player Two-D-Knoten für Audiostreams hinzu, falls Sie noch
keinen haben. Der 2-D-Node des
Audio-Stream-Players unterscheidet sich von einem
Audio-Stream-Player-Knoten , dass die Lautstärke
des Soundeffekts je nach
Nähe zum Hörer variiert Der Standard-Listener ist die
Kamera. Wir können die
Stream-Eigenschaft
unseres Audio-Stream-Players mit
einem Soundeffekt füllen unseres Audio-Stream-Players mit und auf den
Wiedergabe-Schalter
klicken, um ihn zu Wenn wir uns die Animationen unseres
Charakters ansehen, insbesondere die Sprunganimation, können
wir der Animation eine Audiowiedergabe hinzufügen und den
Audiostream-Player
auswählen, der als
Player für
diesen
Track Audiostream-Player
auswählen, der als
Player bezeichnet werden soll Wir können dann
Soundeffekte mit Keyframes versehen, um sie als
Teil dieser Animation abzuspielen, aber das ist mit
vielen Einschränkungen verbunden Wenn der Soundeffekt länger als
die Animation
ist ,
wird er gekürzt Wenn
es sich bei der Animation um eine Endlosschleife handelt, wird sie wiederholt ,
und mit Soundeffekten wird
der Spieler beim Spielen
des Spiels wie diesem
oft etwas hören beim Spielen
des Spiels wie diesem
oft Es ist eine gute Idee, etwas Abwechslung und
Zufälligkeit
hinzuzufügen , damit der Spieler nicht
müde wird, es zu hören Lassen Sie uns also diesen Track aus
der Animation entfernen und
eine andere Methode ausprobieren Da wir den genauen
Moment kennen , in dem der Charakter aus dem Drehbuch
springt, wäre
es einfacher, den Sound auf diese Weise
abzuspielen Lassen Sie uns den
Audio-Stream-Player in DNodeT
Jump umbenennen und eine Referenz abrufen um ihn in einer
privaten Variablen zu speichern Wenn der Charakter springt, müssen wir ihm nur sagen, dass er
abspielen Wenn man den Soundeffekt
aus der Animation heraushält, wird
er in seiner
Gesamtheit und nur einmal abgespielt Wir können die beiden D-Knoten dieses
Audio-Stream-Players duplizieren um weitere Soundeffekte hinzuzufügen
, z. B. einen für
ein Landegeräusch Im Drehbuch können wir ihn dann genauso
abspielen
wie den Sprungsound, aber wir haben noch keine
praktische Funktion für den Fall, dass der Charakter auf dem Boden
landet. Im physikalischen Prozess haben
wir eine If-Anweisung, haben
wir eine If-Anweisung überprüft, ob der Charakter von einem Felsvorsprung
heruntergelaufen ist diese Logik umkehren, können wir überprüfen, ob der Charakter diesen Frame erreicht
hat, ob er nicht im letzten Frame
auf dem Boden war und sich in diesem
Frame auf dem
Boden befindet Wir rufen dann eine neue
private Funktion auf. Nennen wir es bei Landed. Vorerst
muss diese Funktion nur den
Lande-Soundeffekt abspielen. Diese Soundeffekte werden abgespielt wenn der Charakter
springt und landet, aber sie werden
immer dieselben sein, was
den Spieler nach einiger Zeit nerven wird Wir können das verbessern, indem wir
die Tonhöhe des Sounds bei
jeder Wiedergabe
leicht zufällig anpassen die Tonhöhe des Sounds bei
jeder Wiedergabe Lassen Sie uns also ein Skript an
unseren Audio-Stream-Player
Two dende anhängen unseren Audio-Stream-Player und
es so etwas wie
Soundeffekt-Randomizer nennen , ohne eine Vorlage zu verwenden, und es
im entsprechenden Ordner speichern Dieses Skript benötigt
eine öffentliche Funktion ihm
sagt, dass es einen
zufälligen Soundeffekt abspielen soll, keine Parameter
akzeptiert
und keinen Wert zurückgibt Das Endergebnis wird sein, dass
die im Audio-Stream-Player definierte Wiedergabefunktion aufgerufen die im Audio-Stream-Player definierte Wiedergabefunktion wird, um
die Klasse
zu kennzeichnen. Bevor wir
den Soundeffekt abspielen, möchten
wir jedoch den Wert
der Eigenschaft Pitch Scale bearbeiten Mithilfe der integrierten
Funktion rand F range können
wir eine
zufällige Gleitkommazahl zwischen
einem von uns angegebenen Minimal- und
Maximalwert erzeugen . Da eins die
Standard-Tonhöhenskala ist, ordne ich sie nach dem Zufallsprinzip auf einen Wert
zwischen 0,5 und 1,5 an,
wodurch ein breites
Spektrum ähnlicher Sounds erzeugt werden sollte Wir können dasselbe Skript an den anderen
Audio-Stream-Player
an
Dnode anhängen , indem wir auf den Knoten im Szenenbaum klicken
und es von
der Registerkarte Dateisystem auf
den Knoten ziehen im Szenenbaum klicken
und es von
der Registerkarte Dateisystem auf
den Knoten Zurück im Zeichenskript rufen
wir, anstatt die
Wiedergabefunktion
des
Audio-Stream-Players für die D-Klassen aufzurufen, stattdessen unsere
Play-Zufallsfunktion Das mag
ausreichen, um
die Monotonie unserer Sprung
- und Landegeräusche zu reduzieren ,
aber während des Spiels werden ständig Schritte zu
hören sein Spiels werden ständig Schritte zu
hören Vielleicht möchtest du
für so etwas mehrere
verschiedene Soundeffekte haben für so etwas mehrere
verschiedene Soundeffekte und den
Audiostream-Player nach dem Zufallsprinzip einen auswählen lassen Lassen Sie uns einen D-Knoten eines
AudioStream-Players mit zwei D-Knoten duplizieren , um einen weiteren
für Schrittgeräusche zu erstellen, ebenfalls mit demselben
Randomizer-Skript, das Im Skript exportieren wir
eine Variable, die all
die verschiedenen Schrittgeräusche
als Array von Audiostreams enthält Dies kann schnell aufgefüllt werden indem eine
Gruppe alle Schrittgeräusche im Assets-Ordner auswählt
und sie
auf das exportierte Array
im Inspektor zieht auf das exportierte Array
im Wenn wir dann einen
zufälligen Soundeffekt abspielen, prüfen
wir, ob die Größe
dieses Arrays nicht Null ist Wenn das Array nicht leer ist, bedeutet
das, dass wir den Wert von
stream als zufälliges
Element dieses Arrays
festlegen sollten stream als zufälliges
Element dieses Arrays Zugriff auf ein Mitglied
des Arrays mit einer Integer-Indexnummer als zufällige Ganzzahl zwischen Null und der Größe des
Arrays minus Eins. Dadurch wird einfach
ein zufälliger Sound aus unserer Reihe von Sounds ausgewählt. Bei unseren anderen
randomisierten Sounds ist die Größe Null, da sie
keinen Wert für das Array angeben, da sie
keinen Wert für das Array angeben,
und es wird nicht versucht, den Soundeffekt
zufällig zu ordnen,
sondern nur seine Tonhöhenskala anzupassen Jetzt muss nur noch der Soundeffekt durch die Walk-and-Run-Animationen
ausgelöst werden von der
Skriptansicht zur Two-D-Ansicht wechseln, wählen Sie
zuerst den
Animationsbaumknoten und
dann den
Animation-Player-Knoten aus, um vorübergehend eine Vorschau der Animationen anzuzeigen, ohne dass der Animationsbaum beeinträchtigt Wenn entweder die Walk- oder
Run-Animation geöffnet ist, können
wir der Animation eine
Aufrufmethodenspur hinzufügen und eine Methode im
Audio-Stream-Player für Schritte aufrufen , um sie zu einen Schlüssel in die
Animation auf diesem Track einfügen, rufen
wir die Methode play Eine Methode ist in diesem Zusammenhang
gleichbedeutend mit einer Funktion. Wir können durch
die Animation blättern, um die Frames zu finden, bei denen die Füße des
Charakters tatsächlich den Boden berühren, und die Keyframes so
einstellen, dass sie sich genau
auf diesen Wiederholen Sie diesen Vorgang dann
mit der anderen Animation. Jetzt haben wir ein paar
zufällige
Soundeffekte für Schritte, Springen und Landen, aber vielleicht
wollen wir auch Staubwolken Wir sehen uns im nächsten Video.
19. 2-5 Animierter Sprite: Hallo Freunde. In diesem Video werden
wir
Staubpartikel
für unseren Jump'n'Run-Charakter erzeugen für unseren Jump'n'Run-Charakter Dafür müssen wir mehr
Spritesheets importieren. Beginnend mit der Charakterszene fügen
wir dem Knoten ein animiertes Sprite hinzu und nennen es
etwa Jump Das Animated Sprite
to Dende unterscheidet sich von einem normalen Sprite-to-de-Node , dass es keine
einzige Textureigenschaft besitzt Es hat eine Sprite-Frames-Ressource. auf das Drop-down-Menü klicken, können
wir eine
neue
Sprite-Frames-Ressource für diesen Animated
Sprite Two D-Knoten erstellen Sprite-Frames-Ressource für diesen Animated
Sprite Klicken Sie dann auf die
Ressource, um sie zu öffnen. Dadurch wird im unteren Bereich eine neue Registerkarte mit
der
Bezeichnung Sprite-Frames geöffnet unteren Bereich eine neue Registerkarte mit
der
Bezeichnung Sprite-Frames In diesem Fenster können wir
eine oder mehrere
Sprite-Frame-Animationen erstellen eine oder mehrere
Sprite-Frame-Animationen , die dieser Knoten
abspielen kann Diese Animationen können nur das Sprite selbst
verändern. Sie können nicht wie ein Animation
Player-Knoten mit Audio,
Funktionsaufrufen oder
anderen Eigenschaften
synchronisiert Funktionsaufrufen oder
anderen Eigenschaften werden Je nachdem, welche
Elemente Sie verwenden, können
Sie Sprites entweder aus
einzelnen Dateien oder aus
einem einzelnen Spritesheet hinzufügen einzelnen Dateien oder aus
einem einzelnen Spritesheet Ich verwende Sprite Sheets, also klicke ich auf die Schaltfläche „Werberahmen
aus Sprite Durchsuchen Sie das Dateisystem , um die gewünschten Assets zu finden Wenn Sie ein Spritesheet verwenden, werden
Sie
aufgefordert, auszuwählen, welche Frames des
Spritesheets Sie verwenden möchten Im Gegensatz zu einer Atlas-Textur müssen
diese Sprite-Frames gleichmäßig verteilt sein Wählen Sie die Anzahl der Frames in jeder Zeile und Spalte
des Spritesheets aus, und sie werden für Sie in Scheiben geschnitten Sie können dann jeden der Frames,
die Sie
verwenden möchten, auswählen , indem Sie darauf klicken Die Zahl in
der Ecke jedes Sprite-Frames gibt die Reihenfolge an, in der er der Animation hinzugefügt
wird Wenn sie nicht in
der richtigen Reihenfolge sind, können
Sie die Sprite-Frames abwählen und
erneut auswählen
oder sie in der falschen Reihenfolge importieren
und später Genau wie bei
Charakteranimationen
, die einen Frame länger
als der letzte Frame sind, ist
es auch bei
Sprite-Animationen wie dieser eine gute Idee Sprite-Animationen wie dieser einen leeren
Frame
zu haben Das letzte Bild
bleibt also für die gesamte Dauer eines Frames auf
dem Bildschirm gezeichnet gesamte Dauer eines Frames auf
dem bevor die Animation
als fertig betrachtet wird Wir können die
Bildrate der Animation festlegen. Ich verwende 12 Bilder pro Sekunde und lege fest, ob
diese Animation in einer Endlosschleife laufen soll oder nicht, was ich dann abschalten werde. Es gibt auch eine Option, um diese Animation
automatisch abzuspielen. Jeder Animated Sprite
Toti-Knoten kann nur eine
Autoplay-Animation
haben, und der Knoten
spielt diese Animation wenn der Knoten
zum Szenenbaum hinzugefügt wird Wenn beim Springen des Spielers eine Staubwolke entsteht
, wollten
wir diese Animation abspielen Lassen Sie uns diese
Animation also automatisch abspielen. Wir können eine Vorschau anzeigen
, wie die Animation aussehen
wird, indem wir
auf die Play-Schaltfläche Um die Animation besser zu sehen, können
wir das
Charakter-Sprite und die Kollisionsform
vorübergehend ausblenden , indem wir im Szenenbaum auf das Augensymbol neben
ihnen Genau wie der Charakter muss
auch
diese Animation sauber auf dem
Boden der X-Achse liegen Im Bereich Offset
im Inspektor können
wir also den Y-Offset auf die
Hälfte der vertikalen Größe einstellen Bei den Assets, die ich verwende, sind
das 16 Pixel mehr. Dadurch bleiben die Ursprünge der Knoten bei 00 und
der Sprite-Offset wird trotzdem dargestellt Wenn die Farbe der
Sprites nicht ganz stimmt oder Sie ihre Transparenz
anpassen möchten, können
Sie dies im Bereich
Canvas-Elemente in den Eigenschaften
des Knotens
im Inspektor tun Eigenschaften
des Knotens
im der Modulate-Eigenschaft handelt es eine Farbe mit
dem
Standardwert Weiß, die Werte Rot,
Grün, Blau
und Alpha hat Grün, Blau
und Alpha Jedes Pixel im Sprite
erhält vor dem Zeichnen eine eigene Farbe, die mit dieser
Modulationsfarbe multipliziert So können wir die Rot-,
Grün-, Blau- oder Alpha-Werte anpassen Grün-, Blau- oder Alpha-Werte Ich gebe meiner Staubwolke halbe Transparenz, indem ich
ihr moduliertes Alpha auf 0,5 setze Wir können die Sprites neu anordnen, indem sie
anklicken und
mit den Pfeiltasten ziehen, Frames
löschen, leere Frames hinzufügen oder bei
Bedarf weitere Frames importieren Wenn Sie mit dem
Aussehen der Animation zufrieden sind, denken Sie
daran, das Charakter-Sprite und die Collusionsform wieder einzublenden Charakter-Sprite Ich werde das Looping zu Demonstrationszwecken einschalten. Wenn wir das Spiel starten, folgt
der Staub dem Charakter, da
er ein Kind von ihm ist Aber was wir normalerweise für so
etwas wollen, ist die Staubwolke an
einem bestimmten Ort erscheint
und sich nicht bewegt Diese Staubwolke muss ein Geschwister des
Charakters sein, kein Kind rechten Maustaste auf den
Animated Sprite Two D-Knoten klicken, können
wir ihn als eigene Szene speichern Legen Sie es in einen neuen Ordner
für Staubwolken. Lösche es aus der
Charakterszene. Dann öffne es, damit wir es isoliert
bearbeiten können. Lassen Sie uns das Looping
in dieser Animation ausschalten. Wir möchten immer noch, dass es automatisch
abgespielt wird, wenn die Staubwolke erzeugt wird, aber
damit werden wir uns im nächsten Video befassen Vorerst müssen wir zwei weitere
Staubwolken erzeugen. Einen, wenn der Charakter landet und einen
, wenn er läuft oder rennt. So können wir
unsere bestehende Jump-Dust-Szene duplizieren , um die Dinge einfacher zu machen. Es wird keinen Unterschied machen, aber ich möchte
sicherstellen, dass der Name
des Stammknotens meiner Szenen
mit dem Dateinamen der Szene übereinstimmt. Dann tausche einfach die Sprites gegen die jeweils
richtigen
aus A Stellen Sie sicher, dass alle richtig versetzt sind, damit sie sauber auf dem
Boden der X-Achse
aufliegen Wir haben jetzt drei
verschiedene Staubwolken wir für
unseren Charakter verwenden möchten Wir müssen sie nur
instanziieren. Wir sehen uns im
nächsten Video.
20. 2-6 Instanziierung: Hallo Freunde. In diesem Video werden
wir
die Staubwolken als
Reaktion auf die Bewegungen
unseres animierten Charakters instanziieren Reaktion auf die Bewegungen
unseres animierten Charakters Ausgehend von der Spielszene wollen
wir, dass unsere
Staubwolken in
der Welt als Geschwister
unseres Charakters existieren , nicht Fügen wir dem World Environment Node ein neues Skript hinzu. Ich nenne es World und lege
es in den Scripts-Ordner. Der
Hauptzweck dieses Skripts
wird vorerst darin bestehen, neue Szenen
als untergeordnete Elemente hervorzurufen Also werden wir eine neue öffentliche
Funktion namens spawn schreiben, die eine gepackte Szene
als ersten Parameter akzeptiert Ich nenne es einfach
etwas vages wie SN und auch eine Position,
an der es erzeugt werden soll, was ein Vektor zwei ist Dann gibt diese Funktion
den Knoten zurück , den sie erstellt,
falls wir ihn verwenden möchten Wir können eine gepackte Szene in
einen Knoten verwandeln , indem wir ihre
Instantiate-Funktion aufrufen Wir müssen diesen Knoten
in einer Variablen speichern , um ihn verwenden zu
können Ich nenne ihn Instanz. Wenn Sie einen Knoten erstellen, wird er nicht zum Szenenbaum
hinzugefügt. Das müssen wir auch tun. Aber um einen Knoten
zum Szenenbaum hinzuzufügen, benötigt
der Knoten einen übergeordneten Knoten. Dieser
Weltumgebungsknoten wird der übergeordnete Knoten sein, also nennen wir ihn die Funktion
add child geben ihm die Instanz
als Argument. Dadurch wird der Knoten
zum Szenenbaum hinzugefügt, aber seine Position wird am Ursprung
der Szene
liegen, die Koordinaten 00. Wir wollen also
die Position des
neu instanziierten Knotens
als Spawn-Position festlegen neu instanziierten Knotens
als Spawn-Position Dies setzt jedoch voraus, dass der neu instanziierte Knoten eine Positionseigenschaft
besitzt, was nicht Dies würde zwar noch keinen Fehler
verursachen, könnte
es aber in Zukunft sein,
wenn wir die Spawn-Funktion verwenden verschiedene
Knotentypen
zu erstellen Es wäre also eine gute Idee,
zu überprüfen, ob es sich bei dieser Instanz um
ein Canvas-Element handelt , bevor Sie versuchen, auf ihre
Positionseigenschaft zuzugreifen Wir können den Parameter
Spawnposition optional machen indem wir ihm den Standardwert
Vector zwei Punkt Null Schließlich können wir
den Instanzknoten zurückgeben. Jetzt müssen wir
diese Funktion
als Reaktion darauf aufrufen , dass der Charakter bestimmte Aktionen
ausführt. Der einfachste Weg,
dies zu tun, ist die Verwendung von Signalen. Im
Charakterskript können wir am Anfang des Skripts
Signale für jedes
der drei Male deklarieren am Anfang des Skripts
Signale für jedes
der , zu denen wir
eine Staubwolke erzeugen wollen , wenn der Charakter getreten,
gesprungen oder Signale werden üblicherweise in der Vergangenheitsform
benannt, bedeutet, dass das fragliche Ereignis
eingetreten Genau wie Funktionen
können Signale Parameter haben. Um
die Staubwolken erscheinen zu lassen, müssen
wir die Position des
Charakters kennen
und wissen, in welche Richtung
er blickt, damit wir
angeben können, ob das
Sprite umgedreht werden soll In der Sprungfunktion können
wir das gesprungene Signal ausgeben und dabei die
aktuelle Position des
Charakters angeben
und angeben, ob das Sprite des Charakters
horizontal umgedreht ist oder nicht, als
Argumente,
die den Parametern des Signals entsprechen Argumente Das Gleiche kann gemacht werden, wenn
der Charakter landet. Für die Schritte können wir eine neue private Funktion
deklarieren. Benennen wir sie Schritt für Schritt
und geben das Signal aus. Wenn Sie möchten, können Sie
den Schrittsound auch
innerhalb dieser Funktion abspielen lassen,
anstatt
ihn
als separate Spur in die Animationen aufzunehmen ihn
als separate Spur in die Animationen Aber um das zu tun, benötige
ich einen Verweis auf den Audio-Player für Schritte am
Anfang meines Skripts Auswahl des
Animation Player-Knotens und der Walk-Animation Wir können der Animation eine
Aufrufmethodenspur hinzufügen, die eine Methode im Stammknoten
der Szene
aufruft. Fügen Sie dann Keyframes ein, um die On-Step-Funktion
während der Frames
aufzurufen , wenn
die Füße
der Figur den Boden berühren Wenn wir die
Soundeffekte über das Skript auslösen, müssen
wir dies nicht mehr in
der Animation tun und können diesen Track
löschen Dann muss ich
diesen Vorgang auch für
meine Laufanimation wiederholen diesen Vorgang auch für
meine Laufanimation zur Spielszene wechseln, können
wir Signale mit
Skripten verbinden , um automatisch auf
sie zu reagieren. den Charakter auswählen und den
Inspektor-Tab auf den Knoten-Tab
umschalten, können
wir unsere Liste der Signale sehen. Doppelklicken
Sie entweder auf ein Signal oder klicken Sie mit der rechten Maustaste und
wählen Sie Verbinden, ein neues Fenster wird geöffnet. In diesem Fenster können wir
den Knoten auswählen, mit dem wir das Signal
verbinden möchten. In diesem Fall der
Weltumgebungsknoten. Geben Sie dann entweder den Namen
einer Funktion ein, die als
Reaktion auf das Signal aufgerufen werden soll, oder
wählen Sie eine Funktion aus einer Liste aus. Ich gebe manuell den Namen einer neuen Funktion
ein und nenne
sie Spawn Jump Dust Wenn Sie auf Connect klicken, wird das Fenster
geschlossen und
das World Environment
Node-Skript
mit dieser automatisch
hinzugefügten Funktion angezeigt das World Environment
Node-Skript mit dieser automatisch
hinzugefügten Funktion Diese Funktion
hat auch ein grünes Symbol, das anzeigt, dass sie über eine Signalverbindung
aufgerufen wird , und der Charakterknoten im Szenenbaum hat ein Signalsymbol uns anzeigt, dass er ein Signal
mit einer Verbindung
aussendet. Diese Signalverbindung ist
auch auf der Registerkarte Knoten aufgeführt. Wir können Variablen für
unsere drei verschiedenen
Staubwolkenszenen exportieren ,
bei denen es sich um Szenen mit vielen Bildern handelt. Füllen Sie dann jede dieser Variablen auf
der Registerkarte „Dateisystem“
mit den entsprechenden Szenen
aus Lassen Sie uns zunächst einfach
die Spawn-Funktion aufrufen und dabei
Jump Dust als Argument
und auch die
aktuelle Position des Charakters übergeben Jump Dust als Argument und auch die
aktuelle Position des Charakters Godot mag
es nicht, wenn wir
unsere
Funktionsparameter genauso benennen wie die bereits
vorhandenen
Eigenschaften eines Knotens Aber wir können
diesen Parameter in
etwas Spezifischeres
wie die Zeichenposition umbenennen etwas Spezifischeres
wie die Zeichenposition Dadurch wird bei jedem Sprung des Charakters
automatisch
eine Sprungstaubwolke
instanziiert jedem Sprung des Charakters
automatisch
eine Sprungstaubwolke
instanziiert Der Knoten Animated Sprite
Two D spielt die von uns erstellte
Sprite-Animation
automatisch ab, aber wir möchten nicht, dass dieser
Staubwolkenknoten nach Abschluss weiter existiert Nachdem der Charakter viele Male
gesprungen ist, würde
der Szenenbaum viele Animated Sprite Two-D-Knoten enthalten
, die nichts tun Also müssen wir sie
aufräumen. Die Methode, Knoten aus
dem Szenenbaum zu entfernen , besteht darin,
ihre freie Funktion aufzurufen. Aber das wollen wir
erst tun, wenn ihre
Animation abgeschlossen ist, was ein Signal für den
Animated Sprite Two D-Knoten Da wir wissen, dass der Knotentyp unserer Staubwolkenszenen
ein Animated Sprite Two D ist, können
wir sie in
einer privaten Variablen dieses
Typs speichern und sie Dust nennen Wir können Signale
durch Code verbinden , genau
wie wir es mit
dem Inspektor getan haben , und das
Signal für die fertige Animation mit seiner freien Funktion verbinden Signal für die fertige Animation mit seiner freien Funktion Denken Sie daran, dass wir keine
Klammern verwenden, wenn
wir auf eine Funktion verweisen , anstatt eine Funktion
aufzurufen keine
Klammern verwenden, wenn
wir Wir können die
Staubwolke auch horizontal umdrehen, wenn das Sprite des Charakters
umgedreht wurde, als dieses Signal weggelassen diesen Vorgang für
die anderen beiden Signale wiederholen, können
wir die Art der
Staubwolke ändern, die erzeugt wird Wenn wir das Spiel starten, kehren
wir
zum Editor-Fenster und klicken im Szenen-Tab auf die
Fernbedienungstaste Wir können den Szenenbaum
des Spiels sehen , das
gerade läuft. erweitern den Baum, sodass wir
die Kinder des
World Environment Node sehen können . Wir können sehen, dass die
beiden D-Nodes von
Animated Sprite erstellt
und zerstört werden, wenn wir springen, landen und herumlaufen Der Remote-Szenenbaum aktualisiert
nicht jedes Bild, sodass einige Staubwolken erzeugt und
zerstört werden
können , ohne
dass sie
im Remote-Szenenbaum angezeigt werden im Remote-Szenenbaum Wir sehen uns
im nächsten Video.
21. Audiobus 2-7: Hallo Freunde. In diesem Video fügen
wir einen separaten
Soundeffekt für die Stimme des
Charakters hinzu. Ich muss weitere Audiodateien
für die Bemühungen des Charakters importieren . Sprach-Soundeffekte unterscheiden sich von anderen Soundeffekten darin, dass wir immer
nur einen nach dem anderen
abspielen möchten, da unsere Sprachboxen jeweils nur einen
Ton erzeugen
können. Wir benötigen also nur
einen TD-Node
für den Audio-Stream-Player für alle Vokalisationen eines
Charakters Lassen Sie uns in der Charakterszene einen der vorhandenen TD-Knoten
des
Audiostream-Players
duplizieren , um einen neuen Knoten für
die Stimme des Charakters zu erstellen Vielleicht möchtest du diesen Knoten auch irgendwo
um den Hals
oder Kopf des Charakters
platzieren um den Hals
oder Kopf des Charakters ,
anstatt zu seinen Füßen. Allerdings wird das bei meinem winzigen Charakter
keinen
nennenswerten Unterschied machen . Der Soundeffekt-Randomizer ist diesen Knoten
nicht
mehr verfügbar, sodass wir das Skript entfernen können indem wir auf die Schaltfläche für das
separate Skript Wir werden das
durch ein neues Skript ersetzen. Nennen wir es Stimme.
In diesem Skript können
wir eine beliebige Anzahl von
Standard-Soundeffekten für die Stimme exportieren, üblicherweise als
Anstrengungen oder Anstrengungen bezeichnet werden Lassen Sie uns eine Variable für den Sound von
Jump
Effort als Audiostream exportieren , den wir
im Inspektor auffüllen können wir auf die Ressource klicken, können wir uns eine Vorschau davon ansehen, wie
sich das
anhören wird Ressource klicken, können wir uns eine Vorschau davon ansehen, wie
sich das
anhören Dann fügen wir eine Funktion hinzu
, die einen Jump-Effort-Sound abspielt. Diese Funktion muss jedoch nichts tun, wenn der Sprach-Audio-Stream-Player gerade damit beschäftigt ist, andere Sounds
abzuspielen Nur wenn er nicht abgespielt
wird, stellen wir den Stream
auf Jump Effort und spielen ihn ab Dadurch wird verhindert, dass neue
Anfragen, einen anderen Effort-Sound
abzuspielen ,
den vorherigen Sound unterbrechen Wir können hier auch
dieselben Techniken verwenden wie bei unseren
Soundeffekten, z. B. die Tonhöhenskala nach dem Zufallsprinzip anpassen oder eine Reihe
von Audiostreams erstellen und jedes Mal einen
zufällig auswählen Und im Gegensatz zu normalen
Soundeffekten, denen immer erwartet wird, dass
sie jedes Mal abgespielt werden, sind
Anstrengungen nicht immer erforderlich Wir können also auch
einen zufälligen Zufall hinzufügen , dass die
Anstrengung nicht funktioniert, auch wenn das möglich ist. Bei Verwendung der Funktion rand F wird eine
Zufallszahl 0-1 zurückgegeben Wir können überprüfen, ob dies weniger
als eine prozentuale Wahrscheinlichkeit ist, sagen
wir, 25%,
ausgedrückt als 0,25 Hängt man das
mit einem Operator und an die
Bedingung an, so darf die
Stimme dieses Charakters keinen anderen Ton abspielen und
muss außerdem eine zufällige Chance von 25% bestehen bevor man diese Anstrengung spielen darf dies
auszulösen, müssen wir lediglich das gesprungene Signal
des Charakters mit der
Jump-Effort-Funktion „Stimmen abspielen“ verbinden gesprungene Signal
des Charakters mit der
Jump-Effort-Funktion „Stimmen abspielen Aber das gesprungene
Signal des Charakters liefert zwei Argumente und die Funktion zum Abspielen
von Stimmen akzeptiert keine Parameter, sodass sie nicht
als kompatibel angesehen Wenn wir auf den Schalter „Nur kompatible
Methoden“ klicken, werden
alle Funktionen angezeigt,
auch wenn sie nicht übereinstimmen, und wir können die Funktion „
Jump Effort abspielen“ auswählen Um zu verhindern, dass dies zu einem Fehler
führt, erweitern
wir den Bereich für
Fortgeschrittene indem wir auf den Schalter für
Fortgeschrittene klicken Hier können wir neue Argumente binden oder die Bindung der
vorhandenen Argumente aufheben Trennen Sie einfach die beiden
vorhandenen Argumente vom
gesprungenen Signal des Charakters, und jetzt ist das Signal
mit dem Funktionsaufruf kompatibel es testen, werden wir hören, dass der Versuch zufällig mit einer Wahrscheinlichkeit von 25%
abgespielt wird, und er wird sich nie von selbst
unterbrechen B. Eine weitere Möglichkeit, Stimmen von
anderen Soundeffekten
zu trennen ,
besteht darin, ihnen Audiobus-Layout
einen separaten Audiobus zuzuweisen Klicken Sie unten im Editor auf die
Audio-Schaltfläche , um
das Audiobus-Layout zu öffnen, das derzeit nur über einen
einzigen Bus, den Master-Bus, verfügt. Wenn wir jedoch auf Bus hinzufügen klicken, können
wir
dem Audiobus-Layout weitere Busse hinzufügen, einen für Soundeffekte und einen für Stimmen. Es ist auch eine gute Idee, einen anderen für Musik zu
haben. Auf diese Weise können wir unser Audio in verschiedene
Kategorien
einteilen und die
gesamte Kategorie im gesamten Spiel
auf einmal steuern . Wir können die Lautstärke
aller Soundeffekte, Stimmen und Musik unabhängig voneinander einstellen, und die Master-Lautstärke
wirkt sich auf alle aus. Es gibt auch viele
verschiedene Audioeffekte , die zu
jedem Bus hinzugefügt werden können, wenn wir möchten. In unserer Charakterszene haben
wir mehrere verschiedene Audiostream-Player mit zwei D-Knoten, und diesen muss jeweils mitgeteilt werden, zu welchem Audio-Bus sie gehören, wobei die Standardeinstellung Master Bus ist. Jeder der Soundeffekte kann so eingestellt werden dass er auf dem
Soundeffekt-Bus abgespielt wird, während die beiden D-Knoten des
Sprach-AudioStream-Players angewiesen werden können
, auf dem Sprachbus abzuspielen Jetzt können wir die Lautstärke unserer Soundeffekte
unabhängig von den Stimmen M. M. Wir
haben jetzt einen sehr ausgefeilten
2-D-Jump'n'Run-Charakter Als Nächstes werden wir anfangen,
Umgebungen zu erstellen , in denen wir uns bewegen können Wir sehen uns
im nächsten Abschnitt.
22. 3-1 Kachelkarte: Hallo Freunde. In diesem Abschnitt werden
wir eine Umgebung schaffen in der sich
unser Charakter bewegen
und herumspringen kann. Dazu muss ich Assets für mein Terrain
importieren, sortiert in einen neuen Ordner
für Terrain-Sprite-Assets auf das Asset doppelklicken, können
wir es
im Inspektor in der Vorschau anzeigen Wir können sehen, dass dieses Asset genau wie der Charakter
ein Spritesheet Mit Ausnahme von
Animationsframes enthält
dieses Spritesheet
verschiedene Sprites zum Zeichnen von Terrain auf der Grundlage der
umliegenden Beginnend mit der Spielszene machen
wir das aktuelle
Level zu einem statischen Körper, machen
wir das aktuelle
Level zu einem statischen Körper seine eigene Szene
zu kennzeichnen Ich erstelle einen neuen Ordner
für Raumszenen. Und je nach
Größe deines Spiels möchtest
du vielleicht auch Räume
nach Regionen sortieren. Also erstelle ich einen weiteren
Ordner für Räume in der Waldregion und speichere diesen Raum als
Startraum ab. Dann öffne diese neue Raumszene. Ich möchte nicht mehr, dass der statische
Body-2-D-Node der Wurzelknoten ist, da dieser Raum
mehr als nur ein Stockwerk enthalten wird. Also werde ich als Kind dieser Szene einen regulären Knoten mit zwei D
hinzufügen . dann mit der rechten Maustaste
auf diesen Knoten klicken, können
wir Make Scene Root auswählen, um den Szenenbaum
neu zu organisieren
, sodass dieser Knoten
jetzt der Wurzelknoten ist Jetzt ist der Boden ein
untergeordnetes Element des Wurzelknotens, und wir könnten diesem Knoten
weitere statische Körper
für Wände,
Decken, Plattformen und
Hindernisse hinzufügen diesem Knoten
weitere statische Körper
für Wände,
Decken, , um unseren Raum zu bauen Ich benenne den Wurzelknoten so
um, dass er dem Namen
der Szene entspricht. Wenn wir Kacheln aus
einem Spritesheet verwenden , die die
gleiche Größe und den gleichen Abstand
haben, können wir einen anderen von Gadot bereitgestellten Knoten verwenden
, die so genannte Kachelmap-Ebene,
um sie einfacher zu zeichnen der Szene einen
Knoten mit einer Kachelkartenebene hinzufügen wird das Kachelkartenfenster am unteren Rand
des Editors geöffnet, aber wir können hier noch
nichts tun Zuerst müssen wir uns die
Eigenschaften der Knoten
der Kachelmap-Ebene im Inspektor ansehen . Der Knoten der Kachelkartenebene kann erst dann etwas
zeichnen, wenn
er über einen Kachelsatz verfügt. auf das Drop-down-Menü klicken, erstellen
wir ein neues Kachelset. Klicken Sie dann auf das Kachelset
, um seine Eigenschaften zu erweitern. Die erste Option ist die Form der Kacheln in diesem Kachelset. Die Kacheln, die ich verwende, sind quadratisch, aber es gibt auch
Optionen für isometrische, halb versetzte quadratische und
sechseckige Diese werden normalerweise für Perspektiven von
oben nach unten verwendet, und dieses Spiel ist
ein Side-Scroller, daher verwende ich
quadratische Kacheln Als Nächstes müssen wir
die Größe der Kacheln festlegen. Mein importiertes Spritesheet hat
die Kachelgröße im Namen, 32 mal 32 Pixel Wir werden die restlichen Einstellungen vorerst ignorieren und
im unteren Bereich des Editors
von Tilemap auf Kachelsatz umschalten unteren Bereich des Editors
von Tilemap auf Jetzt können wir dem gerade erstellten
Kachelset Kacheln hinzufügen. Klicken Sie entweder unten auf die
Plus-Schaltfläche und navigieren Sie
dann durch
das Dateisystem, um
Ihre Assets zu finden , oder klicken Sie auf die Assets und ziehen Sie sie von der Registerkarte Dateisystem in
den Bereich Kachelquellen Dadurch werden wir
aufgefordert, dass die Engine das
Spritesheet für uns automatisch in Kacheln aufteilt Wenn wir Ja wählen und die Kachelgröße korrekt
einstellen, werden die Kacheln im
Spritesheet für uns automatisch auf diese Größe zugeschnitten
und dem Kachelsatz hinzugefügt Wenn wir auf die Schaltfläche mit dem Radiergummi klicken, können
wir auf Kacheln klicken, um sie aus dem Kachelset zu
entfernen Durch Klicken und Ziehen werden
alle Kacheln gelöscht , über die wir ziehen Strg- oder Befehlstaste gedrückt halten und
dann klicken und ziehen, können
wir alle Kacheln
im ausgewählten Bereich entfernen Wenn wir den Radierer wieder ausschalten, können
wir dieselben Steuerelemente verwenden,
um dem Kachelsatz Kacheln hinzuzufügen Wenn Sie übergroße
Kacheln erstellen möchten, können
Sie dies tun, indem Sie die Umschalttaste
gedrückt halten und
dann auf mehrere Kacheln klicken und sie mit der Maus
darüber ziehen Dadurch werden mehrere
Kacheln so behandelt, als ob sie immer als
eine größere Gruppe von Kacheln gezeichnet werden sollen Aber dieses Spritesheet hat
keine übergroßen Kacheln, also lösche ich sie
und füge jede
dieser Kacheln einzeln zum
Kachelset Da unser
Kachelset nun Kacheln enthält, kann
unsere Kachelkartenebene
dieses Kachelset verwenden , um die Kacheln zu zeichnen Wir wechseln also
vom Kachelsatzfenster zum Kachelkartenfenster. Wenn das Malwerkzeug ausgewählt ist, können
wir eine
Kachelquelle aus dem Kachelsatz und
dann eine Kachel aus
der Kachelquelle auswählen . In der Szenenansicht mit zwei
D-Szenen gibt
der Editor
orangefarbene Richtlinien für die Anordnung der Kacheln vor. Wir können
diese Kachel nun durch Klicken an die gewünschte Stelle
malen . Wenn Sie
den Versatz der Kacheln ändern möchten, können
Sie die Transformationsposition der
Tilemap-Ebenenknoten anpassen Transformationsposition der
Tilemap-Ebenenknoten Wie im Kachelset können wir den Schalter „Löschen“ verwenden
, um Kacheln zu löschen,
anstatt Das Auswahlwerkzeug kann verwendet
werden, um
eine Kachel aus der T D-Ansicht und nicht aus dem
Kachelsatzfenster auszuwählen eine Kachel aus der T D-Ansicht und nicht aus dem
Kachelsatzfenster Wir können Kacheln horizontal,
vertikal oder beides
umgedreht zeichnen und sie je nach Bedarf im oder
gegen den Uhrzeigersinn drehen gegen den Uhrzeigersinn Wir können auch mehrere Kacheln
gruppieren und sie alle gleichzeitig bemalen. Option „Zufälliges Feld platzieren“ umschalten, wird stattdessen nach dem Zufallsprinzip aus
den ausgewählten Kacheln ausgewählt Wenn die Streuung zunimmt, bleiben einige Steine unbemalt,
wenn Sie können auch Linien zeichnen. Wenn mehrere Kacheln ausgewählt
sind, werden sie
entlang der Linie wiederholt. Und das Rechteckwerkzeug kann sehr schnell
einen ganzen Bereich der
Kachelkartenebene ausfüllen . Das Bucket-Tool kann verwendet
werden, um
einen leeren, geschlossenen Bereich
der Kachelkartenebene zu füllen . Die Optionen „Zufallsprinzip“ und „
Streuung“
gelten auch für die Werkzeuge „Line Wrecked“
und „Bucket Das Bucket-Tool verfügt außerdem über
einen zusammenhängenden Schalter, der, wenn er
deaktiviert ist
, verwendet werden kann, um alle passenden Kacheln auf der
gesamten Kachelkartenebene der
gesamten Da der
Knoten der Kachelkartenebene unser Terrain zeichnet, benötigen
wir
den statischen
Body-Tutti-Knoten nicht mehr und können
ihn aus der Szene löschen Zurück in der Spielszene
können wir unseren Startraum sehen. Der Knoten wird nicht umbenannt. Es steht immer noch die aktuelle Stufe. Wenn wir das Spiel starten,
kollidiert
der Charakter nicht mit dem Terrain
, sondern fällt einfach hindurch Wir haben jetzt eine Kachelkartenebene einen Kachelsatz zum Zeichnen von Kacheln
verwendet, aber wir müssen noch mehr Arbeit investieren,
um unser Kachelset zu konfigurieren Wir sehen uns im nächsten Video.
23. 3-2 Gelände: Hallo Freunde. In diesem Video werden
wir mehr Optionen für
Kachelsätze verwenden, um Malen von Kacheln auf eine
Kachelkartenebene schneller und einfacher zu gestalten. in der Raumszene Wählen Sie in der Raumszene den Knoten der Kachelkartenebene aus und erweitern Sie
dann das
Kachelset im Inspektor. Wenn Sie den Abschnitt
Physik-Ebene erweitern, ist er derzeit leer Deshalb fügen wir eine neue
Physik-Ebene hinzu. Wir müssen keine der Eigenschaften
der Physikebene bearbeiten . Es muss nur existieren. Wir werden uns
später im Kurs mit Kollisionsebenen und Kollisionsmaskierung befassen Wenn Sie möchten,
können Sie aber auch
ein physikalisches Material hinzufügen , um dessen Reibung,
Rauheit, Sprungkraft
oder Saugfähigkeit
anzupassen Rauheit, Sprungkraft Ich möchte kein Physikmaterial, also lösche ich es aus dem Nachdem die Physikebene zu unserem Kachelset
hinzugefügt wurde, können
wir die
Registerkarte „Kachelsatz“ unten
im Editor öffnen , um diese
Physikebene auf unsere Kacheln anzuwenden. Wechseln Sie vom Atlas-Setup zu den Farbeigenschaften,
indem Sie auf diese Schaltfläche klicken. Hier können wir viele
verschiedene Eigenschaften
auf unsere Kacheln malen , aber die, die wir
jetzt malen
wollen , ist Physik-Ebene Null. Beim Bemalen sollte die gesamte
Kachel standardmäßig mit vier weißen Knoten
an allen Ecken gefüllt
sein . Ist dies nicht der Fall, klicken Sie auf
die drei Punkte und wählen Sie „Auf
Standardform zurücksetzen“ oder drücken Sie die F-Taste Wir können diese physikalische
Kollisionsform jetzt auf unsere Kacheln malen Kollisionsform jetzt auf unsere Kacheln Alle diese Kacheln sind so konzipiert, dass sie
dieselbe quadratische Form haben. Wenn Sie jedoch
unterschiedliche Objekte verwenden, müssen
Sie möglicherweise
die Kollisionsform
für verschiedene Kacheln anpassen . Wir können auf
diese weißen Punkte klicken und sie ziehen um die Kollisionsform anzupassen, sie zu
löschen oder nach
Bedarf weitere hinzuzufügen , um eine
beliebige Form zu erstellen. Wenn Sie eine bessere
Ansicht benötigen, um genauer zu sein, können
Sie diesen Editor so erweitern,
dass er das gesamte Bedienfeld ausfüllt. Es sind auch Optionen zum
Einrasten von Rastern verfügbar. die Rasterausrichtung
auf die Pixelgröße einstellen,
können Sie , wenn Sie möchten, eine
pixelgenaue Kollision erzeugen A Nachdem wir
Kollisionsformen auf die Felder gemalt und das Spiel
erneut
ausgeführt haben, wird
der Charakter
mit unseren Kacheln das Spiel
erneut
ausgeführt haben, wird kollidieren Jetzt haben wir eine Kollision,
aber es ist sehr mühsam, ein
Terrain nach
dem anderen zu zeichnen ist sehr mühsam, ein
Terrain nach
dem Wir können die im Editor integrierten
Tools verwenden, um es einfacher zu machen. den Geländeabschnitt erweitern, können
wir diesem
Kachelsatz ein Gelände-Set hinzufügen. Dem Gelände-Set muss auch ein
Terrain hinzugefügt werden. Also werden wir auch hier ein
Element erstellen. Wir können das Terrain benennen
, wie wir wollen. Ich nenne meinen Wald
und gebe ihm eine Farbe. Diese Farbe wird nicht im Spiel
gezeichnet sondern nur im Editor,
um sie einzurichten. Es hilft, eine
Farbe zu wählen, die sich den im
Spritesheet verwendeten Farben abhebt, sodass sie hervorsticht Ich verwende Rosa als
Kontrast zu meinen grünen und
braunen Geländekacheln Öffnen Sie als Nächstes das Kachelsatzfenster am unteren Rand des Editors. Terrains sind eine Methode zum
Zeichnen von Kacheln, die so
konzipiert sind, dass sie
miteinander verbunden sind, wie es bei diesem
Spritesheet Wechseln Sie zu den Farbeigenschaften, und die Eigenschaft, die wir
malen möchten, ist die Geländeeigenschaft Wir können dann unser
Terrain-Set, das wir gerade erstellt haben,
Terrain-Set Null und das Terrain
in diesem Terrain-Set,
das Waldgelände, auswählen Terrain-Set, das wir gerade erstellt haben,
Terrain-Set Null und das Terrain . Um die
Geländeeigenschaft zu malen, müssen
wir zunächst alle
Kacheln auswählen, die
Teil des Geländes sind , sodass
sie nicht mehr dunkel sind. In diesem Spritesheet sind
das alle. Wenn Sie mit der Maus über ein Plättchen fahren, das
zu diesem Terrain hinzugefügt wurde, wird
das Plättchen
in neun Quadrate aufgeteilt mittlere Quadrat muss
ausgefüllt werden , um dieses Plättchen als
Teil unseres Geländes zu zeichnen Die anderen Quadrate weisen den Editor an,
dieses Plättchen zu zeichnen, wenn
sich in dieser Richtung ein anderes Geländeplättchen neben diesem befindet. Beginnend mit diesem Plättchen soll
dieses gezeichnet
werden, wenn sich keine anderen
Geländeplättchen neben ihm befinden. Es ist also nur das mittlere
Quadrat bemalt. Das Plättchen
ganz links soll
gezogen werden, wenn sich rechts davon ein anderes
Geländeplättchen befindet , sodass das
rechte Quadrat darauf gemalt wird. Das gegenüberliegende Plättchen auf der rechten Seite folgt der
gleichen Logik auf der linken Seite, und das mittlere Plättchen
wird gezogen, wenn sowohl links als auch rechts
angrenzendes Gelände vorhanden ist . Die vertikalen Kacheln sind
identisch, nur nach oben und nach unten. Der große Block in der oberen linken Ecke kombiniert diese beiden Elemente, fügt Ecken hinzu und hat auch die durchgehende Kachel in
der Mitte
, auf der alle Quadrate gemalt sind. Dies reicht aus, um
konvex geformte Geländeblöcke zu zeichnen konvex geformte Geländeblöcke zu Öffnen Sie das Kachelkartenfenster, wechseln Sie von Kacheln zu Terrains und wählen Sie
dann das Terrain aus, das
wir gerade erstellt haben Wenn das Malwerkzeug ausgewählt ist, können
wir wie zuvor Geländekacheln nach
Belieben auf die
Ebene der Kachelkarte malen wie zuvor Geländekacheln nach
Belieben auf die
Ebene der Kachelkarte Wenn unsere
Geländekacheln nun jedoch an
andere Geländekacheln angrenzen und rechteckige Formen
bilden, werden sie automatisch auf die richtige
Kachel aus dem Gelände
aktualisiert. Durch das Löschen von Kacheln werden auch die umliegenden Kacheln
aktualisiert. Das funktioniert auch mit den Tools
Line Wreck und Bucket. Wenn wir
konkave Ecken erzeugen wollen, müssen
wir zur
Geländemalerei zurückkehren alle verbleibenden
Kacheln zum Gelände hinzufügen, füllen
wir alle Quadrate aus,
die der Frage entsprechen, ob in dieser Richtung ein weiteres Geländeplättchen
neben diesem
Feld liegen
sollte liegen
sollte Richtung ein weiteres Geländeplättchen
neben diesem
Feld Wenn du diesen Elementen folgst
und dir nicht sicher
bist , welches Muster auf den einzelnen Kacheln gezeichnet werden
soll, kannst
du das
Video pausieren und meins kopieren. Bei einigen
Kachelobjekten finden Sie eine Anleitung oder Referenz, die Ihnen bei den Regeln für die
Nachbarschaft von Kacheln hilft. Sie können aber auch einfach experimentieren
und herausfinden, was gut aussieht Versuchen Sie,
ein gewisses Terrain in verschiedenen
Formen zu zeichnen , um zu sehen ob alle möglichen Kombinationen berücksichtigt werden, und
zeichnen Sie entsprechend Die Kacheln am unteren Rand
sind auch dazu gedacht, mit angrenzendem
Gelände in alle Richtungen
gezeichnet zu werden . Jede Kachel in einer Kachelkarte ist normalerweise so gestaltet,
dass sie ein einzigartiges Muster aufweist. Wenn Sie jedoch mehrere
Kacheln mit demselben Muster haben, wählt
das Terrain-Werkzeug beim Zeichnen nach dem
Zufallsprinzip eine mit demselben
Muster aus. Wir können die Wahrscheinlichkeit dieser
Zufälligkeit anpassen, indem eine weitere Eigenschaft aus
der Drop-down-Liste Wahrscheinlichkeit
ausmalen der Drop-down-Liste Wahrscheinlichkeit Geben Sie einfach eine Wahrscheinlichkeit ein. Ich nehme 0,01, was
1% entspricht , und male das auf
die Kacheln unten. Jedes Mal, wenn das Terrain-Werkzeug
eine Kachel zeichnet , die
in alle Richtungen angrenzt, eine Chance
von 1%, dass jedes
dieser Kacheln unten gezeichnet wird,
oder
es wird dieser Kacheln unten standardmäßig die leere
Kachel verwendet Wenn Sie Terrain
von der Kachelkarte aus malen die zufällige Verteilung
dieser Kacheln nicht besonders gut
aussieht, können
Sie einfach weiter darüber
zeichnen Der Terrain-Editor
berechnet die zufällige Verteilung
jedes
Mal Wir können jetzt ganz einfach Räume für
unser Spiel zeichnen , indem wir einen Knoten auf einer
Kachelkartenebene verwenden, aber die Kamera bewegt sich nicht, sodass wir unseren
Charakter nicht sehr weit bewegen können Wir sehen uns im nächsten Video.
24. 3-3 Kamera: Hallo Freunde. In diesem Video folgt
die Kamera
dem Charakter, sodass er sich
weiter in der Umgebung bewegen kann . In der Spielszene
haben wir die beiden
D-Knoten des Charakters und der Kamera als Geschwister. Wenn wir
der Kamera ein Kind
des Charakters zuordnen,
folgt sie natürlich der Kamera ein Kind
des Charakters zuordnen, dem Spieler. Dies ist jedoch keine
besonders gute Methode, da die meisten Spiele
Übergänge,
Zwischensequenzen oder andere
Bereiche des Spiels haben , die an die Kameraansicht
anpassen unabhängig vom
Spielercharakter In einigen Spielen hat
der Spieler die Wahl, welchen Charakter
er spielen möchte, und dieser Charakter
muss geladen sein, sodass in
der Spielszene nicht festgelegt werden kann , ob die Kamera diesem Charakter folgen
muss Es ist besser, die
Kamera als Geschwister zu belassen und die Kamera stattdessen
dem Spielercharakter
durch ein Skript folgen stattdessen
dem Spielercharakter
durch ein Skript Lass uns ein Skript zur Kennzeichnung an
unsere Kamera anhängen. Wir könnten es Kamera nennen oder es nach dem Verhalten
benennen, dem Spieler
folgen oder beides kombinieren
, Kamera-Follow Wir könnten den
Spielercharakter
als Variable exportieren , wie wir es
mit dem Eingabe-Handler gemacht haben, aber
nehmen wir stattdessen an, dass diese Kamera angewiesen
wird,
mehr als einem Charakter
während des Spiels zu folgen , und stattdessen eine öffentliche
Funktion namens follow definieren, die ein Subjekt
als Parameter akzeptiert. Theoretisch
könnte dieses Subjekt alles sein, solange es in der
Zwei-D-Welt existiert und eine Position hat Also geben wir ihr eine Art
von Knoten zwei D und nicht
die spezifischere Art von
Charakterkörper zwei D. Auf diese Weise könnte
diese Kamera angewiesen
werden, einem starren Körper zu folgen oder
was auch immer wir wollen Diese Funktion
muss keinen Wert zurückgeben. Alles, was sie wirklich tun
muss, ist
dieses Subjekt in einer
privaten Variablen zu speichern . dann ein Motiv hat, überschreibt sie die
Prozessfunktion Wenn diese Kamera dann ein Motiv hat, überschreibt sie die
Prozessfunktion und setzt
ihre Position so ein, dass sie
der
globalen Position des Motivs entspricht Da das Motiv
Teil einer größeren Szene sein kann, möchten
wir nicht
seine lokale Position
relativ zu seinem Elternteil verwenden , sondern seine globale Position innerhalb
der gesamten Spielszene wir den
Delta-Parameter nicht verwenden, setze ich ihn
mit einem Unterstrich fort Jetzt benötigen wir ein weiteres Skript
, um diese Funktion von
einem Knoten aus aufzurufen , der
Zugriff sowohl auf die Kamera
als auch auf unseren Charakter hat , der der Spielknoten sein wird ein Skript
an den Spielknoten anhängen, nennen
wir es Game Manager, und ich lege es in einen
neuen Skriptordner für Manager-Skripte Es liegt in der Verantwortung
des Spielmanagers, festzulegen, wann der Spieler
das Spiel spielt, sich in einer Zwischensequenz befindet oder
zwischen Szenen wechselt Vorerst, wenn der
Spielmanager
bereit ist ,
die Bereitschaftsfunktion zu überschreiben, weisen wir die Kamera an, dem Spieler zu folgen und
den Eingabe-Handler zu aktivieren Um das zu tun, müssen wir
jeden dieser Knoten
in Variablen speichern jeden dieser Knoten
in Variablen Da die Hierarchie
der Spielszene im Vergleich
zu anderen Szenen ziemlich komplex
ist, müssen
wir die Knoten möglicherweise neu anordnen dabei ihre Herkunft
ändern In diesem Fall ist
der Knotenpfad in unserem Skript nicht mehr gültig, was
zu Fehlern führt Wir können dies vermeiden, indem wir mit der rechten
Maustaste auf Knoten in unserem Szenenbaum klicken und
Access als eindeutigen Namen auswählen. Dadurch wird rechts
neben dem
Knoten im Szenenbaum ein Prozentzeichen hinzugefügt . Auf diese Weise können wir
den mit Dollarzeichen versehenen
Knotenpfad durch den eindeutigen Namen mit
Prozentzeichen ersetzen Knotenpfad durch den eindeutigen Namen mit
Prozentzeichen Wenn dem Knoten bereits ein eindeutiger
Name zugewiesen wurde,
wird dieser automatisch
übernommen, wenn Sie die Strg- oder
Befehlstaste gedrückt halten und ihn in
das Skript ziehen wir nun all
diese Knotenreferenzen haben und der Game Manager bereit ist, Nachdem wir nun all
diese Knotenreferenzen haben und der Game Manager bereit ist, können
wir die Kamera anweisen, dem Spielercharakter zu folgen und
den Eingabe-Handler zu
aktivieren Wir haben noch keine
Aktivierungsfunktion
für den Eingabe-Handler geschrieben , also lasst uns zu
diesem Skript wechseln und es schreiben. Das Erstellen einer aktivierten privaten
Variablen als booleschen Wert
, der standardmäßig auf False gesetzt ist , und eine öffentliche Aktivierungsfunktion, die wir setzen
können, ist auf true aktiviert Bevor wir dann irgendwelche
Eingaben vom Player verarbeiten, überprüfen
wir, ob der Eingabe-Handler aktiviert
ist, und kehren zurück, wenn er nicht aktiviert ist. Wenn aktiviert auf False
steht, verlassen
wir die Funktion und
verhindern so, dass der
restliche Code ausgeführt wird Wenn aktiviert auf False
steht, verlassen
wir die Funktion und
verhindern so, dass der
restliche Code ausgeführt Wir benötigen außerdem eine
Deaktivierungsfunktion, die die
Variable is enabled wieder auf False
setzt. Das mag übertrieben erscheinen, da wir die Variable
is enabled einfach öffentlich machen könnten. Aber wenn wir diese
gekapselte Struktur verwenden, können
wir
innerhalb dieser Funktionen andere Logiken ausführen Wenn beispielsweise der
Eingabehandler deaktiviert ist, weisen
Sie den Charakter an, sich
nicht mehr zu bewegen, indem Sie die
Richtung auf Null setzen und ihm
auch sagen, dass er gehen soll Wenn Sie den Eingabehandler aktivieren, wird die Bewegung bereits automatisch
erkannt,
da
sie gerade
geprüft wird. Wenn der Spieler allerdings
angefangen hat,
die Run-Taste gedrückt zu halten , bevor der
Eingabe-Handler aktiviert wurde wurde die Eingabe
zwar ignoriert, aber der Spieler
erwartet trotzdem, dass sein Charakter läuft. Wir können den Status
der Run-Taste überprüfen, wenn wir den Eingabe-Handler
aktivieren und dem Charakter sagen, dass er
entsprechend laufen soll. Wenn wir die
Eingabefunktion für Bewegungen verwenden, könnten
wir den
Eingabe-Singleton
auf den Status der Bewegung nach links und
rechts überprüfen den Status der Bewegung nach links und dem
Charakter sagen, dass er sich auch hier bewegen soll Zurück zur Spielszene: Da sich die Position
des Charakters auch am Ursprung befindet, zeichnet die Kamera das Bild, wenn das Spiel beginnt Das ist keine besonders gute Darstellung
des Charakters oder des Raums Normalerweise
muss der Spieler mehr
von dem sehen , was sich über ihm befindet oder
was vor ihm können wir der
Kamera einen
Positionsversatz zuweisen , um sie entlang
der Y-Achse nach
oben und entlang der
X-Achse nach rechts zu bewegen der Y-Achse nach
oben und erreichen, können wir der
Kamera einen
Positionsversatz zuweisen, um sie entlang
der Y-Achse nach
oben und entlang der
X-Achse nach rechts zu bewegen. Ich lege es um 64 Pixel nach oben und nach rechts und
ändere auch meinen Zoom auf zwei. Wenn also die
Kameraposition so eingestellt ist , dass sie der
Position des Charakters
entspricht, wird
sie danach in jedem Frame um
diesen Betrag versetzt,
sodass der Spieler einen Blick leicht nach oben
rechts von der Figur hat. Unsere Kamera
folgt jetzt der Figur, aber die Kamera
schaut nur nach rechts. Wir sehen uns im nächsten Video.
25. 3-4 Blick nach vorne: Hallo Freunde. Und
dieses Video ermöglicht es der Kamera, entweder nach links oder rechts vor
den Charakter
zu schauen . dem
Zeichenskript beginnen, können
wir es
uns leichter machen , indem wir
Klassennamen für einige unserer Skripte angeben, indem das Schlüsselwort Klassenname oben im
Skript verwenden. Nennen wir diese Klasse etwas Generischeres wie Character. Dadurch kann Godot die
Namen von Variablen
und Funktionen
automatisch vervollständigen , wenn er
in anderen Skripten auf
Mitglieder dieser Klasse zugreift in anderen Skripten auf
Mitglieder dieser Klasse So wie wir
Signale verwendet haben,
um auf die Aktionen des Charakters
zu reagieren und Staubwolken zu erzeugen, müssen
wir
ein weiteres Signal geben wenn der Charakter die
Richtung ändert, in die er schaut ein Signal mit dem Namen „
Richtungsänderung“ deklarieren, müssen
wir als Parameter angeben, in
welche Richtung der Charakter jetzt
schaut dem Bereich Fortbewegung eine weitere Variable hinzufügen, müssen
wir wissen welche Richtung der
Charakter gerade
schaut um zu wissen, ob er seine Blickrichtung
geändert hat seine Blickrichtung
geändert Da eine boolesche Variable von
Natur aus auf False gesetzt ist, nenne ich die Variable nach links gerichtet,
was, wenn sie falsch
ist, bedeutet,
dass sie In der Face Left-Funktion können
wir unser neues Signal ausgeben und den Wert von
direction als Argument
übergeben Oh, unten im physikalischen Prozess, wenn wir dem Charakter
sagen, dass er in die Richtung schauen soll, passiert
das jedes Mal der Spieler bei jedem Frame eine
Eingabe macht. Wir wollen
dieses Signal nicht bei jedem Frame ausgeben, sondern nur bei Frames, wenn
sie die Richtung ändern. Also fügen wir die Bedingung hinzu
, dass das Zeichen nach links zeigt und die Richtung größer als Null
ist, oder dass das Zeichen nicht nach
links zeigt und die Richtung kleiner als Null
ist. Jetzt werden diese Funktionen
nur noch während
des Frames aufgerufen , wenn der Charakter tatsächlich seine
Blickrichtung ändert. Dadurch wird
das Signal ausgegeben
, damit wir darauf reagieren können. zum Kameraskript wechseln, benötigen
wir eine Funktion, die der Signatur
des Signals
entspricht , das wir gerade
erzeugt haben, um es zu verbinden. Nennen wir es bei Betreff
geänderter Richtung, da das Zeichen das Subjekt sein
wird. Die Richtung, in die
das Zeichen
zeigt, wird als Gleitkomma
akzeptiert und es wird kein Wert
zurückgegeben. Wir wollen,
dass der X-Offset der Kamera dem Richtungszeichen entspricht
. Also müssen wir den Wert des
Offsets unverändert in einer anderen
Variablen
speichern Offsets unverändert in einer anderen
Variablen Wir nennen es
Standard-Offset und setzen es mithilfe eines Ready-Tags
auf den Wert Offset Jetzt können wir den Wert von
Offset sicher
bearbeiten , ohne zu vergessen,
was der ursprüngliche Wert war H. Wenn das Motiv die Richtung
ändert, setzen
wir den Wert
für den Offset auf den Standard-Offset
multipliziert mit dem Richtungsvorzeichen Wenn die Richtung also positiv ist, dann ist auch der Offset
der Kamera positiv, und das Gleiche gilt für negativ Um dieses Signal zu verbinden wenn die Kamera angewiesen wird, einem Motiv
zu folgen, wenn das Motiv nicht
Null ist und das Motiv ein Charakter
ist,
die Klasse, die wir gerade benannt haben, dann können wir sicher auf
das geänderte
Richtungssignal des Charakters zugreifen das geänderte
Richtungssignal des Charakters und es mit unserer Funktion verbinden. Ein Godot
erkennt neue Klassennamen erst, nachdem Sie Ihre Skripte
gespeichert haben Wenn wir diese
Follow-Funktion jedoch aus irgendeinem Grund mehr
als einmal für dasselbe Thema aufrufen , führt
dies zu einem Fehler, da das Signal bereits verbunden ist Lassen Sie uns zunächst überprüfen, ob das Motiv, dem die Kamera
folgen soll, dasselbe ist wie das Objekt, dem sie
bereits folgt. In diesem Fall müssen wir
nichts tun und können es einfach zu dieser Funktion
zurückkehren. Jetzt wissen wir, dass das Thema
etwas anderes als
das aktuelle Thema ist . Lassen Sie uns überprüfen, ob das
aktuelle Thema
nicht Null ist und ob es
sich um ein Zeichen handelt. Wenn beides zutrifft,
sollten wir auch prüfen, ob das
Richtungsänderungssignal des Charakters mit der Funktion „Beim Subjekt hat die Richtung
geändert“
verbunden ist. Und wenn das stimmt,
schalten wir das Signal ab, da die Kamera dem Motiv nicht mehr folgt und
nicht darauf reagieren muss. Wenn das Spiel ausgeführt wird, die Kamera
vor dem Charakter
positioniert, aber das passiert
sofort, was
für den Spieler ziemlich verwirrend ist Besser wäre es,
den Wert des Offsets im Laufe der Zeit
schrittweise anzupassen , was wir ganz einfach mit einem Tween, der
Abkürzung für „Zwischen“,
tun können Abkürzung Also deklarieren wir eine neue Variable, nennen sie so etwas wie
Look Ahead Tween Dann, wenn das Zeichen die Richtung
ändert, wird der Wert dieser
Variablen zugewiesen, um ein Tween zu erzeugen Create Tween ist eine Funktion
der Node-Klasse, sodass sie von jedem Node verwendet werden kann Wenn das Tween erstellt ist, greifen
wir auf seine
Tween-Eigenschaftsfunktion Dies akzeptiert ein Objekt
als erstes Argument, das dieser Knoten selbst ist Wir können dies
mit dem Schlüsselwort self spezifizieren. Dann die Eigenschaft, die wir als Zeichenfolge verbinden
wollen, das ist die Offset-Eigenschaft, genauer gesagt die X-Komponente, die wir
mit dem Doppelpunkt angeben können Das nächste Argument
ist der Endwert handelt es
sich um den voreingestellten X-Offset multipliziert mit dem zuvor berechneten
Richtungszeichen berechneten
Richtungszeichen Und schließlich die Dauer des
Tweens in Sekunden. Im Moment stelle ich
es auf 1 Sekunde ein. Da dieses Tween 1 Sekunde
dauert, es
aber durchaus möglich
ist, dass der Charakter in dieser Sekunde
mehrmals die Richtung
wechselt, würde
dies zu dass der Charakter in dieser Sekunde
mehrmals die Richtung
wechselt, mehreren
Tweens führen, die alle versuchen den
Offset-Wert
zu bearbeiten. Bevor wir das Tween erstellen, sollten
wir also zuerst überprüfen, ob es
bereits existiert, und ob es dadurch beendet wird Auf diese Weise kann nicht mehr als
eines dieser Tweens gleichzeitig
existieren und
versuchen, den X-Offset zu bearbeiten das jetzt ausführen,
zwickt der X-Offset
der Kamera , dass er über eine Sekunde vor
der Figur schaut, aber es ist immer noch ein wenig Wir können die Art und Weise, wie dieser Tween
entsteht, anpassen , indem wir weitere Variablen exportieren Lassen Sie uns zunächst eine
Dauer für dieses Tween als
Gleitkommazahl exportieren und ihr einen
Standardwert von 1 Sekunde geben Ersetzen Sie dann die Variable in unserer
Funktion durch diese Variable. Als Nächstes fügen wir einen
Übergangstyp und einen Beschleunigungstyp hinzu. Zusammen ermöglichen uns diese drei Variablen
, eine Vielzahl
verschiedener Tweens zu erstellen , indem wir anpassen wie schnell sich der Wert am Anfang und
am Ende
des Tweens ändert Anfang und
am Ende
des Da create tween ein Tween
zurückgibt, können
wir auf dessen Funktion set
trans zugreifen und unseren Übergangstyp als
Argument in derselben Zeile
übergeben Die Funktion set trans gibt
auch das Tween zurück, sodass wir
diese Zeile fortsetzen und
unmittelbar danach auch
die Funktion set Es aufrufen unmittelbar danach auch
die Funktion set Es Wir übergeben unsere Es-Variable
als Argument. All dies
gibt das Tween mit
den
eingestellten Transitions- und Easetypen zurück den
eingestellten Transitions- und Easetypen und weist das
Ergebnis der Variablen zu der Spielszene, indem wir
den Kamera-Tutti-Knoten auswählen seine
Eigenschaften im Inspektor ansehen, können
wir die Werte
dieser Variablen bearbeiten, wobei
die Übergangs- und Beschleunigungstypen praktische
Drop-down-Listen bereitstellen Wir können auch die Dauer des Tweens verkürzen Ich lasse meinen über 2 Sekunden ein Quad in
Out Tween verwenden. Experimentieren Sie mit
den verschiedenen Optionen , um ein Gefühl dafür zu bekommen, wie sie funktionieren Der Übergangstyp bestimmt welche mathematische Formel verwendet
wird , um
das Verhalten zu ändern, während der Typ der Lockerung
entscheidet, wie sich dies auf die erste oder
zweite Hälfte des Tweens auswirkt Die Kamera schwenkt jetzt
sanft nach links oder rechts, um zu zeigen, was sich vor
der Richtung befindet, in die der
Charakter blickt Manchmal möchte der Spieler
aber auch nach
oben und unten schauen Wir sehen uns im nächsten Video.
26. 3-5 Nach oben schauen: Hallo Freunde. In diesem Video ermöglichen
wir dem Spieler,
dem Charakter zu sagen, dass er nach oben und unten
schauen soll. Zunächst müssen wir der Eingabemap in
den
Projekteinstellungen
weitere Eingabeereignisse hinzufügen Eingabemap in
den
Projekteinstellungen
weitere Eingabeereignisse , damit
sie nach oben und unten suchen können. Ich verwende die Aufwärts- und Abwärtspfeiltasten. Die
Richtungstasten nach oben und unten und der rechte Stick sind nach oben und unten
geneigt Im Spielerskript wird dann, anders als bei der Bewegungsrichtung, anders als bei der Bewegungsrichtung,
die nur von der Figur
verwendet wird, die Blickrichtung sowohl
von der Figur
als auch von der Kamera verwendet ,
was bedeutet, dass wir einen
Verweis auf die Kamera benötigen Es lohnt sich,
die Blickrichtung
in einer Variablen zu speichern , sodass wir
sie nur einmal pro Bild berechnen müssen. dann in der Prozessfunktion Sie dann in der Prozessfunktion ihren Wert aus
dem Eingabe-Singleton ab, genauso wie wir es mit
der Funktion Get Axis für die Bewegungsrichtung
getan haben Funktion Get Axis für die die Namen
der Eingabeaktionen
geändert Denken Sie daran, dass
up das erste Argument sein
wird, da up negativ ist erste Argument sein
wird Wir können
diese Blickrichtung dann sowohl
an den Charakter
als auch an die Kamera senden . Für die Kamera
verwende ich einen Funktionsaufruf. Aber für den Charakter zerlege
ich den Wert einer öffentlichen Variablen Um den Namen der
Richtungsvariablen der Zeichenklasse
etwas klarer zu machen, könnte
es klug sein,
sie in Bewegungsrichtung umzubenennen Da diese Funktion im Kameraskript nicht
existiert, werde
ich sie vorerst auskommentieren, um Fehler zu vermeiden, bis ich
bereit bin, sie zu schreiben. Drüben im Zeichenskript können
wir den Ersetzen-Dialog
mit Strg oder Befehls-R öffnen und Richtung durch die Bewegungsrichtung
ersetzen sodass klarer ist, wofür
sie verwendet werden soll. Fügen Sie dann eine neue öffentliche Variable
für die Blickrichtung hinzu. Die L-Richtungsvariable muss an keiner
Stelle im Skript verwendet werden. Sie wird nur
vom Animationsbaum gelesen. In der Szene mit den Charakteren den Animation Player
auswählen muss
ich den Animation Player
auswählen
und LU- und L-Down-Animationen erstellen. Ich werde meine inaktive Animation duplizieren
, um die Dinge einfacher zu machen. Bearbeiten Sie dann einfach die Y-Werte
meiner Keyframes, um
den Charakter entsprechend nach
oben oder unten zu zeichnen . Dann kann
ich in der
Animationsbaum-Zustandsmaschine die die
Locomotion-Zustandsmaschine
bearbeitet, , die die
Locomotion-Zustandsmaschine
bearbeitet, die Animationen für die Suche nach oben und die
Anzeige nach unten hinzufügen Übergang zu ihnen erfolgt
auf der Grundlage des Werts der Blickrichtung Und stellen Sie sicher, dass ihre
X-Geschwindigkeit Null bleibt, andernfalls sollten sie stattdessen zum Gehen
übergehen Und zurück in den Leerlauf
, falls die Blickrichtung gleich Null
ist. Oder wenn sie angefangen haben zu laufen, wird die
Figur animiert, nach
oben oder unten zu schauen , wenn wir die
Aufwärts- und Abwärtsrichtung drücken, aber die Kamera bewegt sich noch nicht Versuchen Sie in der Spielszene, den Y-Offset
der Kamera zu ändern und entscheiden Sie, wie weit die Kamera bewegen soll, wenn der
Charakter nach oben oder unten schaut Ich verwende 128 Pixel und setze es auf die
Standardeinstellung von minus 64 zurück Um zum Player-Skript zurückzukehren, werde
ich jetzt die
Kamerafunktion auskommentieren und
dann zum Kameraskript wechseln, dann zum Kameraskript wechseln diese Funktion
zu deklarieren Ich akzeptiere eine Richtung als
Float und gebe keinen Wert zurück. Der Hauptteil dieser Funktion
wird fast identisch mit Funktion „
Beim Betreff hat sich die
Richtung geändert“ sein. Alles, was wir tun müssen, ist,
alle Instanzen eines Kopfes durch
ein Hoch-Down zu ersetzen . Deklarieren Sie diese dann
als neue Variablen. Wir benötigen außerdem eine weitere
exportierte Variable für den zuvor festgelegten maximalen Blickabstand
, den wir anstelle
des Standard-Offsets verwenden werden,
und Offset X ist Offset Y. Wenn wir
jedoch die Aufwärts- oder Abwärtspfeile
loslassen, soll die Kamera zum
Standard-Offsetwert zurückkehren, nicht zu Null Das erfordert also ein
wenig zusätzliche Logik. Eine andere Möglichkeit,
einfache if-Anweisungen zu
Ihren Skripten hinzuzufügen , besteht darin,
eine ternäre Operation zu verwenden, die in GDScript
dieselben if-Schlüsselwörter wie eine
normale if-Anweisung verwendet , beginnend mit dem Standardfall, dem Wert, den wir
bereits berechnet haben,
aber nur, wenn die Richtung
nicht Null ist, gefolgt von else Wenn die Richtung also Null ist, wollen wir stattdessen unseren
Standard-Y-Offset verwenden Das funktioniert, aber in den meisten Spielen
mit dieser Mechanik muss der Spieler
die Taste einige Zeit gedrückt halten ,
bevor sich die Kamera bewegt Dies können wir erreichen, indem Player-Knoten
einen Timer-Knoten Geben wir ihm einen Namen. Schau, warte. Wir können die
Wartezeit vom Inspektor aus anpassen, aber 1 Sekunde ist in Ordnung, und der Timer
muss auf einmal eingestellt sein. Das
Timeout-Signal dieses Timers mit dem Player-Skript verbinden .
In diesem Moment teilt das
Player-Skript
der Kamera mit, In diesem Moment teilt das
Player-Skript dass sie anfangen soll,
in die Richtung zu schauen Am Anfang des Skripts müssen
wir einen Verweis
auf den alten Timer-Knoten abrufen. Außerdem benötigen wir
einen booleschen Wert, damit wir wissen, ob der Spieler
gerade schaut oder In der Prozessfunktion setzen wir, nachdem wir den Wert der
Blickrichtung aus
dem eingegebenen Singleton erhalten haben, die
Kamera zurück,
wenn der Spieler
bereits hinschaut und
dann auch, wenn die
Blickrichtung Null ist nachdem wir den Wert der
Blickrichtung aus
dem eingegebenen Singleton erhalten haben, die
Kamera zurück,
wenn der Spieler
bereits hinschaut und
dann auch, wenn die
Blickrichtung Null ist, indem
wir
ihre Look-Funktion aufrufen und
Null als Argument übergeben Dann sieht Set als falsch aus. Der Grund, warum ich keine and-Anweisung verwendet habe, ist, dass
ich
eine Else-Anweisung verwenden kann , wenn ich hier und jetzt davon
ausgehe, dass das Suchen falsch ist. Überprüfe dann auch, ob die
Blickrichtung nicht Null ist. In diesem Szenario, in dem der
Spieler noch nicht
hinschaut, aber die Blickrichtung eingibt, müssen wir ihn starten, wenn der Hold-Timer gestoppt
ist. noch einen hinzufügen, wenn der Spieler nicht hinschaut und
keine Blickrichtung eingibt, dann auch, wenn der
Hold-Timer nicht gestoppt ist, bedeutet
das, dass wir
ihn anhalten und den Blick abbrechen müssen. Hinzufügen von Print-Anweisungen
für all diese können
wir sicherstellen, dass
jede Anweisung
nur einmal aufgerufen wird , wenn es angemessen
ist. Außerdem müssen wir die Variable
is looking auf
true setzen, wenn der
Look-Hold-Timer abgelaufen und die Kamera zu
zwängen beginnt. wir das Spiel starten, auf
die Aufwärts- oder Abwärtspfeile tippen ,
ohne
die Taste gedrückt zu halten, wird der Hold-Timer gestartet, aber gestoppt und die
Kamera bewegt sich nicht, aber der Charakter
animiert immer noch, indem er nach oben und unten schaut Wenn Sie die
Aufwärts- oder Abwärtstasten gedrückt halten, läuft
der Timer nach 1 Sekunde ab und weist die
Kamera an, nach oben oder unten zu schauen Sie die Aufwärts- oder Abwärtstasten loslassen, wird
die Kamera auf
ihre voreingestellte Offset-Position zurückgesetzt. Ich kommentiere diese
Print-Anweisungen und passe meine Tween-Einstellungen
im Inspektor an, dass sie sich über eine
halbe Sekunde vervierfachen Der Spieler kann jetzt
die Aufwärts- und Abwärtsrichtung gedrückt halten ,
um nach oben und unten zu schauen. Möglicherweise möchten wir
jedoch einschränken, wie weit sich die Kamera bewegen kann um zu verhindern, dass Inhalte
außerhalb des aktuellen Raums angezeigt werden Wir sehen uns im nächsten Video.
27. 3-6 Grenzen: Hallo Freunde. In diesem Video beschränken
wir die Kamera so, dass sie innerhalb
der Umgebungsgrenzen
bleibt. Ausgehend von der Raumszene können
wir den
Wurzelknoten so ändern, dass er ein
Bereichs-2-D-Knoten ist und nicht
nur ein normaler Zwei-D-Knoten. Dies ist einem physikalischen Körper
insofern
ähnlich , als er eine
Kollisionsform hat, aber er hat keine
Masse und reagiert auch nicht auf Kräfte. Stattdessen können Sie es sich
wie einen Bewegungs- oder Wärmemelder vorstellen . Er stellt eine Region
des Weltraums dar und
sendet ein Signal aus, wenn physikalische
Körper ihn betreten oder verlassen. Dies wird später nützlich sein, um zu erkennen, wann der
Spielercharakter den Raum betritt. Aber vorerst müssen wir nur
wissen, welche Form es hat. eine Kollisionsform hinzufügen,
um sie als Kind zu kennzeichnen, können
wir ihr eine Formressource geben Wir werden eine rechteckige Form verwenden. Wir können die Form dann verschieben und ihre Größe ändern , um
Raumgrenzen zu erstellen Wenn ein Skript
an den Stammknoten der Szene
anhängen , nennen
wir es Room und sortieren
es in den Skriptordner Wir benötigen einen Verweis auf die
Kollisionsform, um zu enden. Ich benenne es in Shape Node um. Dann benötigen wir Funktionen
, die
verwendet werden können , um die
obere linke Ecke
und die untere rechte Ecke
dieses Rechtecks abzurufen und die untere rechte Ecke
dieses Rechtecks sodass sie
Vektor-2-Koordinaten zurückgeben. Wir können auf die
Kollisionsform, zwei
Bezeichnungen der Formeigenschaft
, über ihren Namen shape zugreifen Bezeichnungen der Formeigenschaft
, über ihren Namen shape Dann wollen wir auch eine Funktion für
die Shape-Ressource Get wrecked
aufrufen die Shape-Ressource Get Die Funktion G wrecked
gibt ein Wrack zwei zurück. Wenn wir
die
Dokumentation für diese Klasse öffnen, können
wir sehen, dass sie eine
Position und ein Ende hat Die Position ist die
obere linke Ecke und das Ende ist die
untere rechte Diese beziehen sich jedoch
auf die Position der Knoten. Wir benötigen diese
Koordinaten im globalen Raum, also fügen wir sie der globalen Position der
Knoten hinzu. Die globale Position eines Knotens wird relativ zum Ursprung
des Spiels sein, nicht zur Position der übergeordneten Knoten. Wir können diese Werte dann zurückgeben. Jetzt müssen wir der Kamera nur noch sagen , dass sie diese
Grenzen einhalten soll. Aus der Game
Manager-Szene holen
wir uns vorerst einfach einen Verweis auf den Startraum und speichern ihn in einer Variablen namens Current Room. Wenn die Spielszene fertig ist, können
wir die obere
linke Ecke und
die untere rechte Ecke
aus dem aktuellen Raum abrufen und sie
an die Kamera weitergeben, indem wir eine Funktion
aufrufen, die ihre Grenzen
festlegt. zum Kameraskript wechseln, deklarieren
wir diese
Funktion, indem sie
die beiden Vektor-Zweien akzeptiert , die
aus dem aktuellen Raum abgerufen wurden,
und keinen Wert zurückgibt In dieser Funktion werden
wir herausfinden, wie nah die Kamera an
die obere linke und untere
rechte Ecke
dieses Raums herankommen kann die obere linke und untere
rechte Ecke , ohne
etwas zu sehen, das über diese Punkte hinausgeht Um das zu tun, müssen wir
diese Variablen als Vektor-Zweier erstellen ,
und es ist hilfreich, einen booleschen Wert dafür zu
haben ob die Kamera gerade gebunden
ist oder nicht Wir müssen auch
die Größe des Viewports kennen,
die wir mit der
Funktion Get Viewport automatisch abrufen können .
Dann können wir auf die Größeneigenschaft zugreifen und sie
mit dem Tag on ready in einer Variablen speichern Die Funktion Get Viewport ist in der Node-Klasse
deklariert
und gibt einen Vektor zwei zurück, der der Größe des Fensters
entspricht, das wir in den Projekteinstellungen festgelegt haben Diese Viewport-Größe
entspricht
nicht unbedingt der Anzahl der
Pixel, die von der Kamera
gezeichnet werden,
da die Kamera die Ansicht vergrößern oder verkleinern
kann Wir müssen die Größe
des Viewports durch den Zoom
der Kamera dividieren , um
die tatsächliche Pixelgröße des
Bereichs zu erhalten , den die Kamera sehen kann Ein Vektor kann jedoch nicht
durch einen anderen Vektor geteilt werden . Wir
müssen einen Float verwenden. Ich verwende nur den X-Zoom und gehe davon aus, dass der Zoom der Kamera
immer einheitlich ist. Aber das ist immer noch nicht
gut genug, da die Position der Kamera
in der Mitte ihrer Ansicht befindet. Die Position
, an der sich die Kamera am nächsten an
der linken oberen oder unteren
rechten Ecke des Raums positionieren
kann ,
ohne
diese Punkte zu überschreiten , ist tatsächlich halb
so groß. Wenn ich diesen Wert durch zwei teile, benenne
ich die Variable
um, um ihren neuen Wert widerzuspiegeln. Bei der Festlegung der Grenzen entspricht
die
Position ganz oben links der oberen linken Ecke des Raums plus der halben Größe
der Kameraansicht. Die Position
ganz unten rechts entspricht der unteren rechten Ecke
des Raums minus der Hälfte
der Kameraansicht, und wir können den Grenzwert
auf true setzen. H. In der Prozessfunktion werden wir, nachdem
wir der Kamera mitgeteilt haben, dass sie der Position des Motivs
entspricht, diese
Grenzbeschränkungen
mit der Funktion Clamp F anwenden . Die Funktion Clamp F verwendet einen Float-Parameter wie
die Position der Kamera, dann einen Minimalwert
und einen Maximalwert und gibt
dann einen Wert zurück, der innerhalb dieser Grenzen
bleibt. Dann überschreiben wir die Position der
Kamera mit dem Ergebnis der Fixierung und
wiederholen dies für das Y. Da unsere Kamera
aber
auch einen Offset hat, ihre Position nicht genau
genug
der Mitte des Viewports Wir bearbeiten auch den Wert des
Offsets zu unvorhersehbaren Zeiten Offsets Wir können ihn also bei
den Berechnungen oben links und unten
rechts nicht berücksichtigen , da sich der Wert
wahrscheinlich häufig ändern wird. Wir müssen also den Offset
bei
den Klemmfunktionen berücksichtigen ,
indem wir
ihn jedes Mal von oben links und
unten rechts subtrahieren ihn jedes Mal von oben links und
unten rechts Wenn du möchtest, dass deine
Kamera
während des Spiels ein- und auszoomt und
dabei diese Grenzen respektiert, musst
du diese auch bei
den Berechnungen innerhalb der
Prozessfunktion berücksichtigen den Berechnungen innerhalb der
Prozessfunktion Das funktioniert, aber
die Kameratweens scheinen mit
den Grenzwerten zu kämpfen Durch das Tween wird der
Offset der Kamera leicht über
die Grenzen hinaus verschoben Offset der Kamera leicht über
die Grenzen hinaus Der Frame wird gezeichnet, und in
der nächsten Prozessschleife die
Kameraposition von der Grenze wegbewegt , um
den neuen Offset zu
kompensieren Dies geschieht wiederholt,
bis der Tween aufhört. Das liegt daran, dass die Tweens nach dem Vorgang
am Ende des Frames ausgeführt
werden ,
kurz bevor
alles auf den Bildschirm gezeichnet Um dieses Problem zu beheben, können wir unsere Tweens
von der Verwendung der Tween-Eigenschaft
auf die Tween-Methode
umstellen von der Verwendung der Tween-Eigenschaft
auf die Tween-Methode eine Methode aufrufen, können
wir
die Grenzgrenzen
gleichzeitig anwenden ,
während wir
den Wert von Offset ändern Die Argumente für die Tween-Methode erfordern anstelle eines
Verweises
auf ein Objekt eine aufrufbare Wir sagen „Y−Offset setzen“. Gefolgt
vom Startwert, der
dem aktuellen Wert
des Y-Offsets der Kamera entspricht, dann sind die übrigen
Argumente identisch. Zwei ist der
Endwert am Ende
des Tweens und die
Dauer des Tweens Das Gleiche können wir mit dem Look Ahead
Tween Two machen. Wir müssen nur diese
Set-X-Offset-Funktion schreiben und dabei einen einzigen
Parameter
akzeptieren, einen einzigen
Parameter
akzeptieren der dem Typ von
from und zwei Argumenten
entspricht Nachdem wir den
Wert von X-Offset geändert
haben, können wir die
Grenzgrenze für
die Kameraposition so festlegen
, dass sie
sofort kompensiert wird, und
dasselbe für den Y-Offset tun. dies jetzt ausführen,
werden
die Offset-Tweens die Raumgrenzen nicht Wir haben die Kamera jetzt darauf beschränkt , nur zu zeigen, was sich
im aktuellen Raum befindet, aber die Umgebung
sieht sehr flach Wir sehen uns im
nächsten Video.
28. 3-7 Parallaxe: Hallo Freunde. In diesem Video korrigieren
wir das
Parallax-Scrolling von Vordergrund und Hintergrund
mit einem benutzerdefinierten Skript Ab der
zweiten Raumszene kopiere
ich alle meine
Modulationsfarben
von den Parallax-Tut-Knoten
auf ihre untergeordneten Knoten Dann kann ich
das Parent der Sprites aufheben und
die Parallax-Tut-Knoten löschen , während beibehalte Ich füge dann einem dieser Sprites ein neues Skript
hinzu,
nenne es Parallax und lege
es Das gleiche Skript kann an alle Sprites
angehängt werden , die
ich an Parallax haben möchte Um ein benutzerdefiniertes Verhalten zu erstellen, ist
es hilfreich, sich
etwas Zeit zu nehmen, um
darüber nachzudenken , was Sie
erreichen möchten, welche Knotenreferenzen und andere Informationen erforderlich Ich habe eine Reihe
verschiedener Sprites. Ich möchte mich
relativ zur
Position der Kamera
unterschiedlich bewegen ,
und ich weiß, dass sich die Kamera
derzeit innerhalb
der Grenzen dieses Raums befindet derzeit innerhalb
der Grenzen dieses Raums Ich füge der Szene vorübergehend einen
Kamera-D-Node hinzu und
zoome ihn um den Faktor zwei heran zu tun, als ob es sich um die Spielszene
handelt Wenn sich die Kamera genau in
der Mitte dieses Raums befindet, wollte
ich alles
genau so zeichnen, wie es ist Wenn sich die Kamera jedoch von der Mitte
wegbewegt, verschiebe
ich alle
Parallax-Sprites um einen relativen Betrag, wobei die Hintergrundelemente
weniger bewegen als die Kamera und die Vordergrundelemente sich
in
die entgegengesetzte Richtung bewegen Dazu muss jedes Sprite
die Position
der
Kamera relativ
zur Raummitte
sowie seine eigene
ursprüngliche Position kennen Position
der
Kamera relativ zur Raummitte sowie seine eigene Im Parallax-Skript
deklariere ich eine
exportierte Variable, deklariere ich eine
exportierte Variable die den Faktor
enthält,
um den sich das Sprite relativ zur Kamera
bewegt, und nenne sie Scroll-Skala
als Vektor 2. Das funktioniert ähnlich wie die Scroll-Skalenvariable
im Parallax-Zwei-D-Knoten Wenn dieser Raum
in den Szenenbaum geladen ist, können
wir das
Tag on ready verwenden, um seine Position zu ermitteln und sie
als ursprüngliche Position in einer Variablen zu speichern Dank
der Viewport-Funktion von Node
G ist es
ganz einfach, einen Verweis auf die aktuelle Kamera zu erhalten Dank
der Viewport-Funktion von Node
G ist es
ganz einfach, einen Verweis auf die aktuelle Kamera zu den Viewport zurück, in dem sich
dieser Node befindet, auch über
die Funktion Get camera
to D verfügt , um die Kamera abzurufen Wir können dies auch in
einer Variablen speichern, indem wir das Tag on ready verwenden Wenn wir die Prozessfunktion außer Kraft
setzen, benötigen wir Delta nicht und
können sie als unbenutzt markieren Ich setze die
Position des Sprites einfach auf seine ursprüngliche Position plus den Abstand der
Kamera vom Mittelpunkt des Raums,
multipliziert mit
der Scroll-Skala Jetzt benötigt die Kamera nur noch eine
öffentliche Funktion, die uns ihre Position
relativ zum Mittelpunkt des aktuellen
Raums
mitteilen kann uns ihre Position
relativ zum Mittelpunkt des aktuellen
Raums
mitteilen relativ zum Mittelpunkt des aktuellen
Raums Wenn ich
zum Kameraskript
übergehe, schreibe ich diese Funktion,
Offset vom Mittelpunkt, was der Position der
Kamera plus ihrem Offset minus dem Mittelpunkt
des Wenn ich dies
als neue Variable deklariere, kann
ich sie
als Durchschnitt der oberen linken und
unteren rechten Ecke
des Raums berechnen , wenn ich
sie mit
der Funktion „Grenzen setzen
“ akzeptiere Funktion „Grenzen setzen Wir könnten diese Funktion so ändern
, dass sie den Mittelpunkt und die
Größe des Rechtecks akzeptiert und nicht die obere linke und
untere rechte Ecke, aber das würde sowieso
keinen Unterschied in der
Effizienz machen ,
also werde ich mich Jetzt können wir die
Scroll-Skala für jedes
der Parallax-Sprites so einstellen , dass
sie jeweils einen anderen
Abstand zur sie jeweils einen anderen
Abstand Ich verwende weiterhin nur die
horizontale Parallaxe gebe meinen Hügeln eine Scroll-Skala von einem Drittel entlang der X-Achse
und den weiter
hinten liegenden Hügeln zwei Für den Vordergrund müssen
sie sich in die entgegengesetzte
Richtung
bewegen wie die Kamera Sie haben eine Bildlaufskala von
minus einem Drittel und
minus zwei Dritteln Das wird ausreichen,
um
die Illusion von
Tiefe in unseren Räumen zu erzeugen. das Spiel ausführen, können wir in den zweiten Raum gehen
und sehen, dass der Parallax-Effekt dem des Startraums identisch
aussieht, obwohl er
von einem sehr einfachen Skript ausgeführt wird Da sich die Sprites im Vordergrund in die entgegengesetzte
Richtung der Kamera
bewegen, müssen
sie
entweder ihre Position wiederholen und umdrehen, sodass eine Endlosschleife
entsteht, oder wir können das
Sprite einfach größer als den Raum machen Wenn ich meine Sträucher 1,5-mal
länger mache als der Raum und das
Gras doppelt so lang wie
der Raum, bleibt auf
beiden Seiten
genug übrig , sodass die Kanten nie die
Sicht der Kamera erreichen A Es wäre möglich, den
Parallax-Zwei-D-Knoten zu verwenden, um Vordergrund und Hintergrund in einem
separaten Viewport zeichnen
und sie auf
verschiedenen Leinwandebenen zeichnen
oder zu versuchen,
den aktuellen Raum immer am Ursprung der
Spielszene Diese Lösungen würden später
zu weiteren Komplikationen und
Einschränkungen führen , wenn
es beispielsweise darum geht , die
Karte des Spiels
zu zeichnen Ich finde es
manchmal einfacher, benutzerdefinierte
Lösungen wie diese zu schreiben , als die bereitgestellten Knoten zu
verwenden. Die Lösung speichert auch alles für einen
Raum an einem Ort, was es einfacher
macht, die Räume intuitiver zu entwerfen und zu
bauen. Ich benötige diesen
Kamera-Tuti-Knoten nicht mehr, also lösche ich ihn die Wolken vom
Parallax-Touti-Knoten entfernen, können
wir das
Parallax-Skript ändern und die auch automatisch scrollen das Wrect-Gebiet erweitern, müssen wir nur den Expositionswert mit
der Zeit verringern, um die Wolken nach rechts
zu verschieben verringern, um die Wolken nach rechts
zu das
Parallax-Skript an diesen Knoten anhängen, können
wir zunächst
seine Scroll-Skala
auf eins setzen , sodass sie der Bewegung
der Kamera entspricht Dadurch erscheinen
die Wolken im Vergleich zu den Parallax-Hügeln unendlich weit entfernt einen weiteren Vektor zwei
für die automatische Scrollgeschwindigkeit exportieren, müssen
wir jetzt Delta in
der Prozessfunktion verwenden und
können den Unterstrich entfernen auf die
Eigenschaft region rect und ihre Position zugreifen, beginnend mit dem
X, subtrahieren wir den AutoScrollX-Wert Dadurch wird die Geschwindigkeit des
Autoscrollens auf Pixel pro Sekunde erhöht. Ordnen Sie das Ergebnis dann
der Region recs X-Position zu. Wenn wir dies
jedoch über einen sehr langen Zeitraum ausführen würden, würde sich
diese Zahl den Grenzwerten
einer Fließkommazahl
nähern und könnte zu Problemen führen Der Wert der X-Position
entspricht der Größe, das Ergebnis ist tatsächlich dasselbe. wäre es besser,
die X-Position wieder auf
Null zurückzusetzen diesem Fall wäre es besser,
die X-Position wieder auf
Null zurückzusetzen, damit wir das
für unendlich lange Zeit wiederholen können . Mit der AP F-Funktion können
wir einen Minimal
- und Maximalwert angeben, um den Wert so zu begrenzen, dass er nur zwischen
Null und der Größe der Aufnahme liegt. Diese Funktion
gibt ein Ergebnis zurück , das zwischen
diesen beiden Werten liegen muss, aber im Gegensatz zu
Clamping wird der Rest immer noch im Ergebnis enthalten
sein. Und wir können
dasselbe tun, wenn wir das vertikale
automatische Scrollen verwenden
wollen Ich gebe den Wolken zur Demonstration
einen großen automatischen Bildlauf entlang des X. Und wenn wir das Spiel starten, scrollen
die Wolken automatisch nach rechts und drehen sich in einer Endlosschleife Mama. Mama. Ich setze den Auto-Scroll-Wert wieder
auf einen vernünftigen Wert zurück. Wir haben jetzt das
Parallax-Scrollen im Vordergrund und im Hintergrund für beide Räume Die Übergänge zwischen den
Räumen erfolgen jedoch sehr plötzlich. Wir sehen uns im nächsten Video.
29. 4.1 Inhalt: Hallo Freunde. In diesem Abschnitt ermöglichen
wir dem Spieler, zwischen mehreren
Räumen in unserem Spiel zu wechseln. die Startraumszene öffnen, können
wir sehen, dass die
visuellen Komponenten dieses Raums außerhalb
der Kameragrenzen liegen. Wenn wir uns in einem Raum befinden würden, der an diesen
angrenzt, würden
wir nicht wollen
, dass diese Sprites würden
wir nicht wollen
, dass diese Sprites
zeichnen, obwohl sie eigentlich
in einem anderen Raum sein Und wenn wir uns vorstellen würden, dass unser gesamtes Spiel aus
vielen verschiedenen Räumen bestünde, wäre
es eine enorme Verschwendung von
Ressourcen, all
ihre visuellen Komponenten
geladen zu haben ihre visuellen Komponenten , wenn wir nur einen nach dem anderen
betrachten Also fügen wir der Szene einen weiteren
Knoten zwei D hinzu. Nennen Sie es Inhalt. Ordnen Sie dann all diese anderen Knoten mit
Ausnahme
der Kollisionsform wieder dem Inhaltsknoten zu Ausnahme
der Kollisionsform wieder dem der rechten Maustaste auf den Inhaltsknoten klicken, speichern
wir ihn als eigene Szene Ich erstelle im Ordner
Forest Rooms einen neuen Ordner
für Inhalte. Geben Sie der Szene dann den Namen
Start Room-Inhalt. Löschen Sie dann
den Inhalt dieser Szene. Wenn der Spielercharakter diesen Raum
betritt, müssen wir nur
seinen Inhalt laden und
ihn der Szene hinzufügen. Löschen Sie dann den Inhalt
, wenn sie ihn verlassen. Wir können erkennen, wann der
Spielercharakter
den Raum betritt , indem wir das vom Körper eingegebene Signal verbinden
, da der
Tutti-Knoten des Charakters ein physischer Körper ist dieses Signal mit
dem Raumskript verbinden, fügt
es automatisch wir
dieses Signal mit
dem Raumskript verbinden, fügt
es automatisch
eine Funktion für den eingegebenen Körper hinzu, wobei der Körper
als Parameter
akzeptiert Da wir den
Text nicht benötigen, können wir ihn mit einem Unterstrich
als unbenutzt markieren Am Anfang des Skripts
ist es hilfreich, diesem Skript einen Klassennamen zu geben Nennen wir es Room. Exportieren Sie dann den Inhalt,
der als gepackte Szene angezeigt wird. Und füllen Sie diese Variable aus,
indem Sie auf
die Inhaltsszene klicken und sie von der Registerkarte
Dateisystem in den Inspektor ziehen die Inhaltsszene klicken und sie von der Registerkarte
Dateisystem in den Außerdem deklarieren wir eine
Inhaltsvariable als Knoten zwei D. Wir deklarieren eine neue Funktion
namens Wenn der Inhalt Null ist, weisen wir
ihm den Wert des instanziierten Inhalts zu Fügen Sie dann als Kind den Inhaltsknoten
zur Szene hinzu. Wenn der Spielercharakter diesen Raum
betritt, rufen
wir die Funktion zum Laden von
Inhalten auf. Lassen Sie uns vorübergehend
den Wert von body ausdrucken , damit
wir sehen können, was er ist. Wir werden auch
eine weitere Funktion benötigen, um den Inhalt des Raums zu entladen,
wenn er nicht mehr benötigt wird, obwohl wir
das erst mit dem nächsten Video
testen können das erst mit dem nächsten Video
testen Prüfen Sie zunächst, ob
Inhalte entladen werden müssen. Wenn Inhalte vorhanden sind, rufen Sie die Funktion Qu free auf und
setzen Sie die Variable auf Null Sie einen Knoten aus
dem Szenenbaum befreien, wird der Inhalt der
Variablen nicht automatisch
gelöscht Wenn wir also einen Raum verlassen, seinen Inhalt
entladen und dann denselben Raum wieder
betreten würden , diese If-Anweisung, die prüft, ob der Wert des
Inhalts Null ist, würde
diese If-Anweisung, die prüft,
ob der Wert des
Inhalts Null ist, sagen, ja, da ist
tatsächlich etwas in
dieser Inhaltsvariablen Allerdings wurde der Knoten
, der
hier gespeichert wurde , zuvor
aus dem Szenenbaum entfernt, sodass es zu einem Fehler kommen wird Das Setzen der
Variablen auf Null, nachdem sie aus dem
Szenenbaum
entfernt wurde, behebt dieses Problem. Beim Ausführen des Spiels befindet sich
unser Charakter im Kollisionsbereich des
Startraums, sodass der Inhalt
des Startraums geladen wird. Wir wollen jedoch nicht, dass
andere Physikkörper das Signal
auslösen
und versehentlich den Inhalt des Raums
laden Wir müssen sicherstellen, dass
der Spielercharakter
der einzige Körper ist, der das
bewerkstelligen kann. zur
Spielercharakterszene wechseln, können
wir den Tutti-Knoten des
Charakters auswählen und
den Kollisionsbereich in den Eigenschaften,
die
von Collision Object übernommen wurden, erweitern den Kollisionsbereich in den Eigenschaften,
die
von Collision Object übernommen wurden Hier haben wir eine
Kollisionsebene und eine Kollisionsmaske mit
jeweils 32 nummerierten Schaltflächen Dies sind Bitmasken, bei denen es sich lediglich um ganze Zahlen handelt, die auf eine bestimmte Weise
verwendet werden. Da Ganzzahlen
als 32 binäre Nullen und Einsen gespeichert werden , können
wir jedes einzelne
Bit als Ebene verwenden Wenn es an der Zeit ist, nach Kollisionen zu
suchen, indem wir einfache logische
Operationen zwischen Kollisionsmaske
eines Objekts und der
Kollisionsebene des anderen Objekts anwenden, können
wir bestimmen, ob sie kollidieren
sollen Nur wenn die
Maske des ersten Objekts eine Eins hat, die sich an derselben Bitposition wie die Ebene des zweiten Objekts befindet,
wird eine Kollision ausgelöst Andernfalls wird es einfach so
hindurchgehen , als ob es nicht da wäre. Wenn die
Kollisionsebene des
Charakters auf eine andere Zahl geändert wird, existiert er nun auf seiner
eigenen Kollisionsebene getrennt von allem
anderen im Spiel. Da sich die Zahlen
in Achtergruppen befinden, verwende
ich gerne die
ersten acht Ebenen für
Kollisionsebenen in
der Umgebung, die nächsten acht für
den Spielercharakter, die nächsten acht für
Feinde usw. Der Körper des Charakters maskiert
immer noch die erste Ebene, sodass er
während seines physikalischen Prozesses immer noch
mit dem Terrain kollidiert,
wenn wir Move und Slide aufrufen Wir können diese Ebenen in den Projekteinstellungen unter
Ebenennamen Physik zwei D benennen. Ich nenne Ebene eins als Terrain und Ebene
neun als Diese Namen werden
zusammen mit ihrem Bit
- und Integer-Wert
angezeigt, wenn Sie mit der Maus über die
Ebenenschaltflächen im Inspektor fahren der Maus über die
Ebenenschaltflächen im Inspektor zusammen mit ihrem Bit
- und Integer-Wert
angezeigt, wenn Sie mit In der Startraumszene können
wir die
Kollisionsmaske ändern, sodass dieser Bereich zwei Enden
nur die Kollisionsebene des
Spielercharakters maskiert,
nur der Spielercharakter Kollisionen mit diesem Bereich
auslöst mit diesem Bereich
auslöst Wenn wir das Spiel erneut starten, wird sich
nichts ändern, aber wir können sicher sein
, dass keine anderen Personen Inhalt des Raums laden
werden Wir haben jetzt den Inhalt unseres Raums dynamisch geladen, wenn der
Spielercharakter ihn betritt, aber wir haben immer noch nur einen Raum. Wir sehen uns im nächsten Video.
30. 4-2 Zimmer: Hallo Freunde. In diesem Video fügen
wir einen zweiten Raum hinzu, in
den der Charakter ziehen kann. Wir beginnen damit,
die Startraumszene zu duplizieren. Ich nenne diesen zweiten Raum. Dann dupliziere auch die Inhaltsszene des
Startraums und öffne sie, damit ich sie bearbeiten kann Entferne
dann die
Bäume und das Blätterdach, sodass sie sich optisch
vom Startraum unterscheidet Wir können auch das
Gelände und die Grenzen bearbeiten wenn wir die beiden
Räume noch besser voneinander unterscheiden möchten Wenn ich die zweite Raumszene öffne, benenne
ich den Stammknoten der Szene so um, dass er dem Dateinamen
entspricht. Vergessen Sie nicht, die Inhaltsszene des
zweiten Raums
der Raumszene des zweiten
Raums zuzuweisen , damit bei der Eingabe der richtige
Inhalt geladen
wird. Da
meine Welt in Regionen
aufgeteilt sein wird, füge
ich in der Spielszene meine Welt in Regionen
aufgeteilt sein wird, füge
ich in einen Knoten zwei D hinzu
und nenne ihn Wald. Dann mache meine beiden Räume zu
Kindern der Waldregion. Speichern Sie die Waldregion
als eigene Szene im Ordner Räume und öffnen Sie die
Waldregionsszene, um sie zu bearbeiten. In der Waldregionsszene können
wir
diese beiden Räume jetzt problemlos
nebeneinander positionieren . Wir möchten die Räume
nebeneinander positionieren , sodass wir den Raum
wechseln können , wenn der Spieler einen Raum
verlässt und einen anderen
betritt. Wir schalten das Raster-Snapping ein, erweitern
dann die Fangoptionen
und wählen
Snap und wählen Wir können den Rasterschritt
auf die Kachelgröße
unserer Geländekacheln einstellen unserer Geländekacheln Dadurch ist es sehr
einfach,
die Räume exakt
nebeneinander zu positionieren die Räume exakt
nebeneinander zu Das vom
Körper der Tutti-Knoten eingegebene Signal wird ausgegeben, sobald des Charakters Tutti mit der
Kollisionsform des
Raums
überschneidet Einfachheit halber müssen
wir zwischen den Räumen etwas
Platz lassen, der so
groß ist, dass sich der Körper des
Charakters nicht mit mehr als
einem Raum gleichzeitig
überschneiden kann mit mehr als
einem Raum gleichzeitig
überschneiden Andernfalls müssten wir zusätzliche Logik für den
Fall hinzufügen der Charakter einen Raum betritt ohne
den vorherigen Raum vollständig zu verlassen. Ihr
Charakterkörper überschneidet sich gleichzeitig mit den Bereichen beider Räume
, dreht sich dann
aber um und
kehrt in den ersten Raum zurück Es ist viel einfacher, wenn die
Räume voneinander entfernt sind. Wenn der Charakter einen neuen Raum
betritt, wissen
wir, dass er den vorherigen Raum bereits
verlassen hat Dadurch kann sich
der Charakter auch vollständig außerhalb
der Kameragrenzen bewegen , bevor der Übergang
in den neuen Raum
ausgelöst Da die
Kollisionsform meines Charakters nur 12 Pixel
breit ist und der Abstand zwischen den
Räumen 32 Pixel breit ist, weiß
ich mit Sicherheit, dass
der Charakter
zwischen diese beiden Räume passt , ohne beide gleichzeitig zu
berühren Diese Lücke
bedeutet auch, dass alle unsere Räume
ihre Bodenkollision weit
genug über die
Kameragrenzen des
Raums hinaus ausdehnen
müssen ihre Bodenkollision weit genug über die
Kameragrenzen des , um zu verhindern, dass
die Figur herunterfällt, bevor sie
den angrenzenden Raum erreicht. Ich werde die Kamera
etwas verkleinern und die Codezeile
auskommentieren , die die Kamera
an die Grenzen des aktuellen
Raums bindet an die Grenzen des aktuellen
Raums Beim Ausführen des Spiels können wir sehen, dass der Inhalt des
Startraums sofort
geladen wird,
da sich der Charakter bereits in diesem Raum
befand Wenn wir zu dem
zweiten Raum wechseln, wird dessen Inhalt
geladen, sobald der Spielercharakter den Schwellenwert
überschreitet. Wir wollen aber auch den Inhalt des
vorherigen Raums,
den wir gerade verlassen haben, entladen Inhalt des
vorherigen Raums,
den wir gerade verlassen Es liegt in der Verantwortung
des Spielmanagers, sich um die Übergänge zu
kümmern, da dabei
viele Komponenten der Spielszene
zusammenarbeiten Wir müssen ein Signal von dem Raum,
der betreten wurde,
an den Spielmanager senden , der sich in unserem Projekt nicht einmal in
derselben Szene befindet. Wir werden auch viele verschiedene Räume in unserem Spiel haben
und es wäre mühsam ,
dieses Signal für jeden
einzelnen Raum einzeln manuell verbinden zu müssen. Es wäre also einfacher,
unsere Skripte zu verwenden, um es zu automatisieren. Aus dem Raumskript fügen wir oben im Skript
ein neues Signal hinzu, oben im Skript
ein neues Signal das wir aussenden können, um mitzuteilen, dass der
Spielercharakter
diesen Raum mit dem Raum betreten hat , der als Parameter eingegeben
wurde. Wenn dann das vom Körper eingegebene
Signal empfangen wird, senden
wir dieses Signal aus,
anstatt
den Inhalt zu laden , und geben diesen
Raum selbst als Argument weiter. Wenn dieser Raum fertig ist, können
wir auf den Stamm der
Szenenbäume zugreifen, indem wir
eine Puppe starten oder den annotierten
Knotenpfad mit einem Schrägstrich,
dann dem Wort root und einem
weiteren Schrägstrich kennzeichnen dann dem Wort root und einem
weiteren Schrägstrich Von der Wurzel des Szenenbaums aus heißt
der erste Knoten, auf den wir zugreifen
wollen, Spiel, so wie er
in der Spielszene benannt ist Dadurch erhalten wir Zugriff auf das Game
Manager-Skript mit einem Punkt. Dann können wir auf eine Funktion verweisen, die
wir noch nicht geschrieben haben. Rufen wir es an, wenn der
Spieler den Raum betreten hat. Dann können wir
diese Funktion mit
einem passenden Raumparameter in
das Game Manager-Skript schreiben . Ich nenne es Room Entered , um es
in diesem Zusammenhang klarer zu machen. Um den Inhalt des
vorherigen Raums zu entladen, müssen
wir wissen, was
der vorherige Raum war, also benötigen wir eine Variable für
den Raum, in dem sich der
Spielercharakter gerade befindet Ich ersetze dieses aktuelle Level durch das aktuelle Zimmer
und lasse es leer Ich benötige
das On Ready-Etikett nicht mehr. Als erstes sollten wir
überprüfen, ob der Raum, der
betreten wird, derselbe ist wie der Raum in
dem sich der Spielercharakter gerade
befindet. In diesem Fall müssen wir nicht
wirklich
etwas tun und können diese Funktion einfach
verlassen. Jetzt können wir davon ausgehen
, dass der aktuelle Raum und der eingegebene Raum unterschiedliche Räume
sind. Beim ersten Start des Spiels gibt es keinen aktuellen Raum. Wir werden zuerst prüfen, ob der
aktuelle Raum nicht Null ist. Wenn es einen aktuellen Raum gibt, sollten
wir ihn mit der Funktion, die wir im vorherigen Video geschrieben
haben, anweisen,
seinen Inhalt zu entladen mit der Funktion, die wir im vorherigen Video geschrieben
haben, anweisen,
seinen Inhalt im vorherigen Video geschrieben
haben dann den aktuellen Raum
dem Raum zuweisen, den wir betreten
haben, können wir diesen
aktuellen Raum anweisen,
seinen Inhalt zu laden und schließlich die Kamera
an die Grenzen des
aktuellen Raums zu binden Aber ich werde das auskommentieren, damit wir sehen
können, was
mit dem verkleinerten Bild passiert Wenn wir jetzt das Spiel starten, sendet das
Betreten des zweiten Raums ein Signal an den Spielmanager, den Inhalt
des Startraums zu entladen,
bevor der Inhalt
des zweiten Raums geladen Wir haben jetzt mehrere
Räume in unserem Spiel, aber das
Parallax-Scrolling im Vordergrund
und Hintergrund funktioniert nicht für Räume, die nicht um den Ursprung der Szene herum
zentriert sind um den Ursprung der Szene herum
zentriert Wir sehen uns im nächsten Video.
31. 4-3 Parallaxe: Hallo Freunde. In diesem Video korrigieren
wir das
Parallax-Scrolling von Vordergrund und Hintergrund
mit einem benutzerdefinierten Skript Ab der
zweiten Raumszene kopiere
ich alle meine
Modulationsfarben
von den Parallax-Tut-Knoten
auf ihre untergeordneten Knoten Dann kann ich
das Parent der Sprites aufheben und
die Parallax-Tut-Knoten löschen , während beibehalte Ich füge dann einem dieser Sprites ein neues Skript
hinzu,
nenne es Parallax und lege
es Das gleiche Skript kann an alle Sprites
angehängt werden , die
ich an Parallax haben möchte Um ein benutzerdefiniertes Verhalten zu erstellen, ist
es hilfreich, sich
etwas Zeit zu nehmen, um
darüber nachzudenken , was Sie
erreichen möchten, welche Knotenreferenzen und andere Informationen erforderlich Ich habe eine Reihe
verschiedener Sprites. Ich möchte mich
relativ zur
Position der Kamera
unterschiedlich bewegen ,
und ich weiß, dass sich die Kamera
derzeit innerhalb
der Grenzen dieses Raums befindet derzeit innerhalb
der Grenzen dieses Raums Ich füge der Szene vorübergehend einen
Kamera-D-Node hinzu und
zoome ihn um den Faktor zwei heran zu tun, als ob es sich um die Spielszene
handelt Wenn sich die Kamera genau in
der Mitte dieses Raums befindet, wollte
ich alles
genau so zeichnen, wie es ist Wenn sich die Kamera jedoch von der Mitte
wegbewegt, verschiebe
ich alle
Parallax-Sprites um einen relativen Betrag, wobei die Hintergrundelemente
weniger bewegen als die Kamera und die Vordergrundelemente sich
in
die entgegengesetzte Richtung bewegen Dazu muss jedes Sprite
die Position
der
Kamera relativ
zur Raummitte
sowie seine eigene
ursprüngliche Position kennen Position
der
Kamera relativ zur Raummitte sowie seine eigene Im Parallax-Skript
deklariere ich eine
exportierte Variable, deklariere ich eine
exportierte Variable die den Faktor
enthält,
um den sich das Sprite relativ zur Kamera
bewegt, und nenne sie Scroll-Skala
als Vektor 2. Das funktioniert ähnlich wie die Scroll-Skalenvariable
im Parallax-Zwei-D-Knoten Wenn dieser Raum
in den Szenenbaum geladen ist, können
wir das
Tag on ready verwenden, um seine Position zu ermitteln und sie
als ursprüngliche Position in einer Variablen zu speichern Dank
der Viewport-Funktion von Node
G ist es
einfach, einen Verweis auf die aktuelle Kamera zu erhalten Dank
der Viewport-Funktion von Node
G ist es
einfach, einen Verweis auf die aktuelle Kamera zu den Viewport zurück, in dem sich
dieser Node befindet, auch über
die Funktion Get camera
to D verfügt , um die Kamera abzurufen Wir können dies auch in
einer Variablen speichern, indem wir das Tag on ready verwenden Wenn wir die Prozessfunktion außer Kraft
setzen, benötigen wir Delta nicht und
können sie als unbenutzt markieren Ich setze die
Position des Sprites einfach auf seine ursprüngliche Position plus den Abstand der
Kamera vom Mittelpunkt des Raums,
multipliziert mit
der Scroll-Skala Jetzt benötigt die Kamera nur noch eine
öffentliche Funktion, die uns ihre Position
relativ zum Mittelpunkt des aktuellen
Raums
mitteilen kann uns ihre Position
relativ zum Mittelpunkt des aktuellen
Raums
mitteilen relativ zum Mittelpunkt des aktuellen
Raums Wenn ich
zum Kameraskript
übergehe, schreibe ich diese Funktion,
Offset vom Mittelpunkt, was der Position der
Kamera plus ihrem Offset minus dem Mittelpunkt
des Wenn ich dies
als neue Variable deklariere, kann
ich sie
als Durchschnitt der oberen linken und
unteren rechten Ecke
des Raums berechnen , wenn ich
sie mit
der Funktion „Grenzen setzen
“ akzeptiere Funktion „Grenzen setzen Wir könnten diese Funktion so ändern
, dass sie den Mittelpunkt und die
Größe des Rechtecks akzeptiert und nicht die obere linke und
untere rechte Ecke, aber das würde sowieso
keinen Unterschied in der
Effizienz machen ,
also werde ich mich Jetzt können wir die
Scroll-Skala für jedes
der Parallax-Sprites so einstellen , dass
sie jeweils einen anderen
Abstand zur sie jeweils einen anderen
Abstand Ich verwende weiterhin nur die
horizontale Parallaxe gebe meinen Hügeln eine Scroll-Skala von einem Drittel entlang der X-Achse
und den weiter
hinten liegenden Hügeln zwei Für den Vordergrund müssen
sie sich in die entgegengesetzte
Richtung
bewegen wie die Kamera Sie haben eine Bildlaufskala von
minus einem Drittel und
minus zwei Dritteln Das wird ausreichen,
um
die Illusion von
Tiefe in unseren Räumen zu erzeugen. das Spiel ausführen, können wir in den zweiten Raum gehen
und sehen, dass der Parallax-Effekt dem des Startraums identisch
aussieht, obwohl er
von einem sehr einfachen Skript ausgeführt wird Da sich die Sprites im Vordergrund in die entgegengesetzte
Richtung der Kamera
bewegen, müssen
sie
entweder ihre Position wiederholen und umdrehen, sodass eine Endlosschleife
entsteht, oder wir können das
Sprite einfach größer als den Raum machen Wenn ich meine Sträucher 1,5-mal
länger mache als der Raum und das
Gras doppelt so lang wie
der Raum, bleibt auf
beiden Seiten
genug übrig , sodass die Kanten nie die
Sicht der Kamera erreichen A Es wäre möglich, den
Parallax-Zwei-D-Knoten zu verwenden, um Vordergrund und Hintergrund in einem
separaten Viewport zeichnen
und sie auf
verschiedenen Leinwandebenen zeichnen
oder zu versuchen,
den aktuellen Raum immer am Ursprung der
Spielszene Diese Lösungen würden später
zu weiteren Komplikationen und
Einschränkungen führen , wenn
es beispielsweise darum geht , die
Karte des Spiels
zu zeichnen Ich finde es
manchmal einfacher, benutzerdefinierte
Lösungen wie diese zu schreiben , als die bereitgestellten Knoten zu
verwenden. Die Lösung speichert auch alles für einen
Raum an einem Ort, was es einfacher
macht, Räume intuitiver zu entwerfen und zu
bauen. Ich benötige diesen
Kamera-Tuti-Knoten nicht mehr, also lösche ich ihn die Wolken vom
Parallax-Touti-Knoten entfernen, können
wir das
Parallax-Skript ändern und die auch automatisch scrollen das Wrect-Gebiet erweitern, müssen wir nur den Expositionswert mit
der Zeit verringern, um die Wolken nach rechts
zu verschieben verringern, um die Wolken nach rechts
zu das
Parallax-Skript an diesen Knoten anhängen, können
wir zunächst
seine Scroll-Skala
auf eins setzen , sodass sie der Bewegung
der Kamera entspricht Dadurch erscheinen
die Wolken im Vergleich zu den Parallax-Hügeln unendlich weit entfernt einen weiteren Vektor zwei
für die automatische Scrollgeschwindigkeit exportieren, müssen
wir jetzt Delta in
der Prozessfunktion verwenden und
können den Unterstrich entfernen auf die
Eigenschaft region rect und ihre Position zugreifen, beginnend mit dem
X, subtrahieren wir den AutoScrollX-Wert Dadurch wird die Geschwindigkeit des
Autoscrollens auf Pixel pro Sekunde erhöht. Ordnen Sie das Ergebnis dann
der Region recs X-Position zu. Wenn wir dies
jedoch über einen sehr langen Zeitraum ausführen würden, würde sich
diese Zahl den Grenzwerten
einer Fließkommazahl
nähern und könnte zu Problemen führen Der Wert der X-Position
entspricht der Größe, das Ergebnis ist tatsächlich dasselbe. wäre es besser,
die X-Position wieder auf
Null zurückzusetzen diesem Fall wäre es besser,
die X-Position wieder auf
Null zurückzusetzen, damit wir das
für unendlich lange Zeit wiederholen können . Mit der AP F-Funktion können
wir einen Minimal
- und Maximalwert angeben, um den Wert so zu begrenzen, dass er nur zwischen
Null und der Größe der Aufnahme liegt. Diese Funktion
gibt ein Ergebnis zurück , das zwischen
diesen beiden Werten liegen muss, aber im Gegensatz zu
Clamping wird der Rest immer noch im Ergebnis enthalten
sein. Und wir können
dasselbe tun, wenn wir das vertikale
automatische Scrollen verwenden
wollen Ich gebe den Wolken zur Demonstration
einen großen automatischen Bildlauf entlang des X. Und wenn wir das Spiel starten, scrollen
die Wolken automatisch nach rechts und drehen sich in einer Endlosschleife Mama. Mama. Ich setze den Auto-Scroll-Wert wieder
auf einen vernünftigen Wert zurück. Wir haben jetzt das
Parallax-Scrollen im Vordergrund und im Hintergrund für beide Räume Die Übergänge zwischen den
Räumen erfolgen jedoch sehr plötzlich. Wir sehen uns im nächsten Video.
32. 4-4 Übergang: Hallo Freunde. In diesem Video werden
wir den Übergang zwischen Räumen mit einem
einfachen Übergang zu Schwarz glätten. In der Spielszene beginnen die
meisten Spiele entweder
mit einem
Ladebildschirm oder komplett schwarz und werden dann ausgeblendet, wenn
das Spiel gestartet wird. der Canvas-Ebene einen Knoten hinzufügen, können
wir einen farbzerstörten Knoten verwenden , um einfache Farben einfach zu zeichnen den Layout-Bereich erweitern, ändern
wir die
Voreinstellung für Anker auf Full Wreck Dadurch wird die zerstörte Farbe angewiesen, die gesamte Leinwand auszufüllen Es ist derzeit weiß, aber
Schwarz ist üblicher, sodass wir die Farbe oben
auf Schwarz ändern können Wenn das Spiel beginnt,
müssen wir diese
Farbe nur schrittweise von Schwarz zu Durchsichtig ändern, sodass Sichtfenster der Kamera dahinter
sichtbar In unseren kleinen, einfachen Räumen werden
sie sofort geladen. Das Laden und Entladen von Rauminhalten verursacht
derzeit keine Verzögerung Wenn wir uns aber vorstellen, dass
unsere Räume aus
viel mehr Sprites bestehen werden und vor allem Soundeffekte und Hintergrundmusik geladen werden, führt das dazu, dass das
Laden des Raums länger dauert
als ein einzelnes Bild Wir können denselben Effekt auch
rückwärts verwenden, um zu Schwarz zu wechseln, unseren Raum zu entladen
und zu laden und
dann wieder einzublenden,
wenn
alles fertig ist Dieses Projekt wird nicht so groß werden , dass wir einen echten
Ladebildschirm benötigen Benennen wir diesen Node Fade um
und geben ihm einen eindeutigen Namen. Wir müssen
sicherstellen, dass dieser Knoten am unteren Rand
des Szenenbaums
bleibt damit er über alles
andere gezeichnet werden kann, oder wir müssen seinen Z-Index erhöhen. Dieses große
schwarze Rechteck in der Spielszene kann die Arbeit
an anderen Dingen behindern. Vielleicht möchten wir, dass dieser
Knoten standardmäßig ausgeblendet wird. Wenn ich ein Skript an diesen Knoten anhänge, nenne
ich es fade und speichere
es im Ordner scripts ich die Ready-Funktion überschreibe, möchte ich als Erstes ihre
Eigenschaft visible auf true
setzen,
sodass
alles schwarz dargestellt wird ihre
Eigenschaft visible auf true
setzen, sodass
alles schwarz dargestellt Wir benötigen zwei
öffentliche Funktionen, um die Farbe
entweder auf Schwarz oder Transparent
einzustellen Um den Wert
einer Eigenschaft im Laufe der Zeit anzupassen, ist es
am einfachsten, ein Tween
zu verwenden Also werden wir
eine als Variable deklarieren. Ich erwarte zwar nicht, dass das
Fading mehr als einmal
in schneller Folge erlaubt wird, es ist trotzdem eine gute
Idee, zu überprüfen, ob das Tween bereits existiert,
und es für alle Fälle zu beenden Dann erstelle ein neues Tween. Hier sind keine ausgefallenen Übergangs
- oder Lockerungsarten erforderlich, ein lineares Tween
funktioniert einwandfrei wird
dieser Knoten selbst, seine Farbeigenschaft und seine Farbe so verändert dass er
im Laufe der Zeit transparent ist. Vorerst werde ich 1 Sekunde warten. In der Klasse ist eine transparente
Farbe definiert,
aber wenn wir mit
der Maus darüber fahren, können
wir sehen, dass sie Rot-, Grün
- und Blauwerte von Eins
hat, was bedeutet, dass es sich um transparentes
Weiß und nicht um transparentes Schwarz handelt Dadurch wird nicht
der gewünschte Effekt erzielt, also definiere ich meine eigene
transparente Farbe als Konstante und nenne sie klar Es ist
üblich, bei der
Benennung von Konstanten ausschließlich Großbuchstaben zu verwenden üblich, bei der
Benennung von Konstanten Dies wird eine Farbe
mit Null Rot-,
Grün-, Blau- und Alphawerten Wir können auch eine
Konstante für die Dauer
des Tweens definieren und die 1
Sekunde durch diese Konstante ersetzen Dies macht es etwas einfacher, die Dauer zu ändern,
ohne
das Skript durchsehen zu müssen und ohne eine Variable für
etwas
zu
exportieren, das Sie
für Ihr gesamtes Projekt konsistent halten möchten Ihr gesamtes Projekt Für die Funktion Feed to Black könnten
wir den
gesamten Code kopieren und einfügen und dabei nur das
Endwertargument
des
Funktionsaufrufs der Eigenschaft Tween ändern , aber es wäre besser, Redundanz
zu vermeiden Stattdessen machen wir daraus eine eigene private Funktion
namens tween color, private Funktion
namens tween color,
akzeptieren die endgültige
Farbe als Parameter übergeben sie
dann als Argument an den
Funktionsaufruf der
Eigenschaft Tween Funktionsaufruf der
Eigenschaft Dann
können sowohl die Funktion Fate to Black als auch zwei Clear-Funktionen diese Funktion aufrufen
und dabei unterschiedliche
Argumente übergeben Im Game Manager-Skript finden
wir oben einen Verweis auf
den Fade-Knoten. Wenn der Spielercharakter
einen Raum betritt , nachdem er
den Rauminhalt geladen hat, können
wir sagen, dass der Fade zu
Tween seine Farbe auflöst. Wenn das Spiel zum ersten Mal
startet, gibt es keinen aktuellen
Raum zum Entladen, also wird dieser sofort eingeblendet Nachdem wir den zweiten Raum betreten
haben, sollten wir ihn zu Schwarz verblassen lassen bevor wir den Inhalt des
aktuellen Raums entladen Dann fahren wir mit dem Laden
des zweiten Raums fort und
blenden Diese Funktion wartet jedoch
nicht ab, bis der Tween
fertig ist, bevor der Inhalt
des Raums entladen wird Sie wird es sofort tun. Um diese Funktion anzuhalten, während
das Tween schwarz wird, können
wir das Schlüsselwort await verwenden Auf Await folgt ein
Signal. Das Signal, auf das wir warten wollen, ist das fertige Signal des Tweens
im Fade-Skript Wir können dieses Signal also
von unserer Tween-Funktion zurückgeben. Änderung des Rückgabetyps unserer Funktion von
void auf signal Das gleiche
Rücksignal wird durch die Funktionen „Fade to
Black“ und „Clear“
erneut weitergeleitet. Zurück im Game Manager-Skript kann
der Game Manager jetzt jederzeit auf
dieses Signal zugreifen , wenn er diese Funktionen
aufruft. Wir können warten, bis es schwarz wird,
oder darauf,
dass das Ausblenden gelöscht wird. Diese Funktion wird also pausieren und warten, bis der Tween
beendet ist, bevor wir fortfahren Wir wollen generell nicht, dass
der Spieler
währenddessen die Kontrolle über den Charakter
hat Deshalb können wir vor dem Start
des Übergangs oben
in der
Funktion den
Spielerpunkt Disable aufrufen vor dem Start
des Übergangs oben
in der
Funktion den und
den Spielerknoten am Ende
wieder aktivieren und
den Spielerknoten am Ende , nachdem der Übergang abgeschlossen
ist. Ich habe vergessen,
diese
Richtungsvariable auf die Bewegungsrichtung zu aktualisieren , als ich sie umbenannt habe. Diese Räume
sind zwar recht klein und sollten recht schnell be- und
geladen werden, aber
wir können vielleicht trotzdem einen Fall
sehen, in
dem der vorherige Raum entladen
wird und weil es kein Terrain gibt , auf
dem der Charakter stehen kann, fallen
sie durch
den Boden, bevor der Inhalt
des nächsten Raums
geladen wird, um eine neue Etage zu schaffen Deshalb sollten wir
den Charakter gleichzeitig
deaktivieren und aktivieren wie den Spielerknoten Eine andere Möglichkeit,
Knoten zu
aktivieren und zu deaktivieren , besteht darin, ihre
Prozessmodus-Eigenschaft zu ändern. Wenn
der Übergang beginnt, deaktiviert, und
dann erben, wenn der
Übergang abgeschlossen ist Jetzt kann der Spieler den Charakter nicht mehr
kontrollieren und der Charakter
wird beim Übergang
zwischen Räumen nicht von der
Schwerkraft beeinflusst beim Übergang
zwischen Räumen nicht von der
Schwerkraft Als Nächstes werden wir daran arbeiten,
unsere Räume auf einer Karte zu zeichnen. Wir sehen uns im nächsten Video.
33. 4-5 Ansichtsfenster: Hallo Freunde. In diesem Video beginnen
wir damit, unsere Räume auf einer Karte zu
zeichnen. Es ist zwar möglich,
die Karte getrennt
von der Spielwelt zu zeichnen , aber es ist viel aufwändiger, Konsistenz zwischen
der Welt und der Karte aufrechtzuerhalten ,
wenn Sie
beide bei jeder
Änderung separat aktualisieren müssen . Positionieren von Symbolen auf der Karte, insbesondere von Symbolen, die sich
wie der Spielercharakter bewegen können, kann zu einer noch schwierigeren Aufgabe werden Eine viel einfachere Methode,
eine Karte zu erstellen, besteht darin, einfach
eine zweite Kamera zu haben eine zweite Kamera die Welt aus einer vergrößerten
Perspektive zu betrachten, aber die Welt und ihren
Inhalt auf einfachere Weise zu zeichnen Lassen Sie uns also eine weitere Kamera zu
unserer Spielszene hinzufügen und
diese in Kartenkamera umbenennen Standardmäßig wird nur die erste
Kamera verwendet und sie zeichnet das Hauptfenster des
Spiels Um die Karte zu zeichnen, muss
die Kartenkamera einen
anderen Viewport zeichnen, also fügen wir einen als
Knoten im Szenenbaum hinzu
, der ein untergeordneter Viewport-Knoten ist Benennen Sie es in Map Viewport um
und geben Sie ihm einen eindeutigen Namen. In einigen unserer Skripte haben
wir bereits
die G-Viewport-Funktion verwendet, haben
wir bereits
die G-Viewport-Funktion verwendet um den Haupt-Viewport des Spiels zu ermitteln
, der zum Zeichnen
der beiden D-Welten des Spiels verwendet wird Die Zwei-D-Welt ist in
diesem Kontext nicht dasselbe wie der
Welt-Umgebungsknoten Er enthält alle
TD-Knoten, die sich derzeit in der Mitte befinden, einschließlich des Spielmanagers. Wenn wir die Kartenkamera
dem Karten-Viewport unterordnen, zeichnet
diese Kamera jetzt den Karten-Viewport statt des Haupt-Viewports
des Spiels, aber sie hat keine Stelle
auf dem Bildschirm, um ihn zu Deshalb
müssen wir der Leinwandebene einen Knoten hinzufügen,
der die Textur beschädigt hat , damit
die Kamera den Viewport zeichnen kann Nennen wir das Ganze
Map-Viewport-Textur. Ich entferne all diese
Dummy-Steuerknoten
und stelle sicher, dass der Knoten dem die Textur beschädigt wurde, vor dem
Fade-Knoten gezeichnet wird , indem ich
ihn in
der
Szenenhierarchie weiter oben positioniere auf das
Textur-Dropdown-Menü klicken, können
wir die Viewport-Textur auswählen und
dann das
Map-Viewport auswählen, das als Textur für dieses
Textur-Wret
gezeichnet werden soll für dieses
Textur-Wret
gezeichnet Die Größe der Textur wird
automatisch Größe des
Viewports angepasst Derzeit wird nur
die standardmäßige graue
Hintergrundfarbe gezeichnet , da die Kartenkamera und das
Viewport nichts sehen können Standardmäßig hat jeder Viewport
seine eigene Welt. Sie können sich
diese Welten wie
Parallelwelten oder
Existenzebenen vorstellen Parallelwelten oder
Existenzebenen Sie können
zur gleichen Zeit
denselben Raum einnehmen , aber
unabhängig voneinander existieren. Aber wir möchten, dass dieser Viewport dieselbe Welt
zeichnet
wie unser Haupt-Viewport Im Game Manager-Skript holen
wir uns einen Verweis auf
den Map-Viewport-Knoten Sie dann in der Ready-Funktion die
Eigenschaft World Two D des Viewports Wir können auf den
Haupt-Viewport zugreifen, indem den Game
Manager-Knoten die Funktion „Viewport“
aufrufen dann auf dessen Eigenschaft World
Two D zugreifen Jetzt
zeichnen sowohl der Haupt-Viewport als auch der Map-Viewport dieselbe Welt Wir möchten generell
, dass unsere Karten viel mehr von der Welt zeigen,
also stelle ich den Zoom auf
ein Achtel ein Wenn wir die
Abmessungen der Map-Textur ändern möchten, können
wir die
Pixelmaße
des Viewports festlegen , indem wir
es im Szenenbaum auswählen Ich mache
die Hälfte der Abmessungen
meines Spiels auf 640 mal 360 Pixel Anstatt diese graue
Farbe zu zeichnen, wenn nichts da ist, würde
ich es vorziehen, wenn der Hintergrund meines Map Viewports transparent ist Ich schalte den
transparenten Hintergrund ein. Dadurch ist die
Karte jedoch schwer lesbar.
Ich möchte, dass diese
Kartentextur in
einem Panel enthalten ist, damit sie vom Hauptspiel
getrennt erscheint der Canvas-Ebene einen Panel-Container
hinzufüge, ordne ich die Map-Textur
so an , dass sie ein untergeordnetes Element des
Panel-Container-Knotens Dann benenne ich den Panel-Container Map
um und gebe
ihm einen eindeutigen Namen Mit dem Standarddesign zeichnet
der Panel-Container eine transparente schwarze Farbe
. Da es
sich um einen Container handelt, passt er seine Größe automatisch an, sodass
er auch seine untergeordneten Objekte enthält Dadurch wird deutlich
, dass die Map-Textur auf der Leinwand gezeichnet
wird nicht als Teil der Welt, und wir können das
Aussehen des Panel-Containers später über
den Theme-Editor anpassen Aussehen des Panel-Containers später über
den Theme-Editor Ich verwende die Anker des
Panel-Containers , um ihn in der
Mitte des Bildschirms zu verankern Wir wollen generell, dass die
Kartenkamera
dem Spielercharakter folgt ,
genau wie die Hauptkamera, aber ohne
Tweening oder andere Funktionen Im Gegensatz zur Hauptkamera muss
die Kartenkamera nie etwas anderes tun, sodass es sicher ist, dass sie
immer exakt der
Position
des Spielercharakters exakt der
Position
des Spielercharakters Es gibt keine Möglichkeit, die Kartenkamera an
den Spielercharakter anzupassen, da sie ein untergeordnetes Element des Karten-Viewports bleiben muss , um
die Karte
zu zeichnen Wir könnten ein anderes
Skript schreiben, um diese Kamera zu bewegen, aber es gibt einen Knoten, den wir
verwenden können, um die Dinge einfacher zu machen, den Ferntransformationsmodus von zwei D. Mit der Ferntransformation zwei D als untergeordnetes Element
des Spielercharakters können
wir seinen entfernten
Pfad zur Kartenkamera festlegen Jetzt werden die
Transformationseigenschaften, die
Position, die Drehung und die Skalierung
der Kamera automatisch aktualisiert, sodass sie denen des
Spielercharakters entsprechen. Wir können
die Rotation und
Skalierung ausschalten , indem wir
den Update-Bereich erweitern Selbst wenn wir
die
Rotation oder Skalierung des Spielercharakters bearbeiten würden , würden
wir nicht wollen, dass die Karte
diese Eigenschaften kopiert Mm. Unsere Spielewelt wird jetzt auf der Leinwand
gezeichnet, aber wir wollen lieber eine
vereinfachte Version
der Welt zeichnen als eine exakte Kopie. Wir sehen uns im nächsten Video.
34. 4-6 Sichtbarkeit: Hallo Freunde. In diesem Video lassen wir die Kartenkamera eine vereinfachte
Version der Welt
zeichnen. im Startraum und fügen
wir vorübergehend
den Inhalt des Raums hinzu. Ich möchte nicht all
diese Sprites auf die Karte zeichnen, sondern nur einen Umriss der Form und des Geländes des
Raums Wir können zwei beliebige D-Knoten verwenden, um dies zu
zeichnen, je nachdem, welchen Stil wir wollen Ich verwende einen Ebenenknoten vom Typ „Tile Map“. Geben Sie ihm ein neues Kachelset mit Kacheln, die 32 mal 32 Pixel groß sind. Ich importiere ein neues Sprite, das nur ein einfaches weißes Quadrat
mit 32 mal 32 Pixeln Dann füge es dem Kachelset hinzu. dieses weiße Quadrat
auf meiner Ebene „Tile Map“ zeichne, zeichne
ich einen Umriss
des Raums, wobei ich das Gelände
als Boden anstelle der Kameragrenze verwende und Türöffnungen
lasse, um
Verbindungen zu anderen Räumen herzustellen Wir möchten, dass die Hauptkamera nur den Inhalt
zeichnet, während die Kartenkamera stattdessen diese Notiz auf der
Ebene „Tile Map“
zeichnet Während beide denselben Raum
betrachten, werden
sie zwei
verschiedene Versionen davon sehen. Jetzt, wo ich die
Form meines Raums
habe, lösche ich den Inhalt
aus der Szene. Da der Layer-Knoten
„Tile Map immer
von der Kartenkamera betrachtet
wird, bleibt er immer geladen und
wird nicht wie der Inhalt
geladen und entladen den Bereich
Sichtbarkeit
ausdehne, kann ich die Eigenschaft „
Farbe modulieren“ verwenden , um meine weißen Quadrate in farbige umzuwandeln, wenn ich möchte Da dies Teil
der Waldregion ist, werde
ich die Karte grün zeichnen Damit die Kartenkamera das zeichnet, aber nicht die Hauptkamera, ändere ich ihre
Sichtbarkeitsebene 1—2. Die
Standardsichtbarkeitsebene 1 ist alles, was
von der Hauptspielkamera gezeichnet wird, während Ebene zwei alles ist, was ich auf der Karte zeichnen möchte
. Genau wie bei den
Kollisionsebenen können
wir diese
Sichtbarkeitsebenen in
den Projekteinstellungen unter
Ebenennamen zwei D-Rendern benennen . Ich nenne Ebene eins
Welt und Ebene zwei Karte. Diese Sichtbarkeitsebenen
hängen von den
Sichtbarkeitsebenen ihrer Eltern ab. Wenn der Viewport den Knoten
im Startbereich des Raums nicht sehen kann, er sich nicht die Mühe,
zu überprüfen, ob er untergeordneten Knoten der
Ebene „Tile Map“ sehen
kann Die Sichtbarkeitsebene des übergeordneten
Knotens des
Startraums muss sowohl
auf eins als auch auf zwei gesetzt sein, da er untergeordnete Elemente hat, die von beiden Viewports gezeichnet werden
können In der Hierarchie nach oben muss die Sichtbarkeit
der Waldregion so eingestellt sein, dass
beide Sichtbarkeitsebenen verwendet werden, ebenso wie der Stammknoten
der Spielszenen Der Weltumgebungsknoten besitzt
keine Eigenschaft der
Sichtbarkeitsebene. nun den Map-Viewport auswählen, können
wir seine Canvas-Aufrufmaske so einstellen , dass nur Ebene zwei
und nicht Ebene eins angezeigt Dies funktioniert ähnlich wie die Eigenschaft Kollisionsmaske
für Kollisionsobjekte Nur wenn das Bit für die
Maske auf eins gesetzt ist, kann sie
dann alles sehen, auf dessen Ebene
dasselbe Bit auf eins gesetzt ist? Aber wir können nicht vom Editor aus auf
den Haupt-Viewport zugreifen , um
die Canvas-Aufrufmaske so zu ändern , dass nur Ebene eins
und nicht Ebene zwei angezeigt Standardmäßig
maskiert es jede Ebene. Also müssen wir
es per Skript bearbeiten. In der
Skriptbereitschaftsfunktion des Game Managers können
wir
mit der G-Viewport-Funktion auf den Haupt-Viewport zugreifen und
dann dessen Eigenschaft Canvas-Aufrufmaske festlegen Maus über Ebene eins fahren, können
wir sehen, dass ihr ganzzahliger
Wert ebenfalls eins ist Wir können den Wert der
Canvas-Aufrufmasken einfach auf eins setzen. Jetzt wird nur die
Sichtbarkeitsebene eins und nicht die zweite Ebene oder eine
andere Ebene. kopiere den
Ebenenknoten „Tile Map“ im ersten Raum Ich kopiere den
Ebenenknoten „Tile Map“ im ersten Raum und füge ihn in den zweiten Raum ein, um diesen Raum auch auf der Karte zu
zeichnen. Ich instanziiere den Inhalt des
Raums und bearbeite
dann die Kacheln, sodass sie die Form
dieses Raums
genauer wiedergeben . Wenn ich fertig bin, lösche ich den
Inhalt Denken Sie daran, die
Sichtbarkeitsebene
der übergeordneten Knoten so einzustellen , dass sie auf
beiden
Sichtbarkeitsebenen vorhanden ist, damit die Kinder von
ihren jeweiligen Viewports aus gesehen werden können Jetzt sind beide Räume auf der Karte
deutlich sichtbar, und das großen
Aufwand,
wenn wir weitere Räume hinzufügen ohne großen
Aufwand,
wenn wir weitere Räume hinzufügen. Sie müssen lediglich die Karte für
jeden Raum in seiner Szene auf einer
separaten Sichtbarkeitsebene hinzufügen jeden Raum in seiner Szene auf einer
separaten Sichtbarkeitsebene Wir können der zweiten Karte ganz einfach weitere
Dinge hinzufügen, indem ihnen weitere Sprites
hinzufügen
und sie auf Sichtbarkeitsebene zwei platzieren, wie zum Beispiel ein Symbol für die
Charakterkarte eines Spielers die Szene mit den
Spielercharakteren öffnen, fügen
wir ein Sprite zur Kennzeichnung hinzu
und nennen es Ich fülle die Textur
mit einer Atlas-Textur, verwende dasselbe Spritesheet
und wähle eine Region aus, die als Kartensymbol
verwendet werden soll Ich verwende den
Kopf des Charakters irgendwo im Spritesheet, wo
der Schwanz nicht im Nachdem wir die
Textureigenschaft ausgefüllt
haben, setzen wir ihre
Sichtbarkeitsebene auf zwei und nicht Dann
muss der Wurzelknoten
dieser Szene sowohl die Ebene eins als auch die zweite Ebene haben Ich passe den
Abstand des Sprites an, sodass es
wie der Charakter auf dem Boden sitzt. weiß, dass der
Zoom der Kamera ein Achtel beträgt, vergrößere
ich dieses Symbol um das
Achtfache , sodass es in der Szene
sehr groß erscheint Da ich nicht möchte, dass
dieses Symbol meinen Charakter
verdeckt , wenn
ich in der Szene arbeite, möchte
ich es lieber verstecken
. Das gilt
dann alles in meinem Spiel, dem ich ein Kartensymbol hinzufügen
möchte. Ich füge diesem Knoten ein Skript hinzu und
nenne es Kartensymbol. Und ich lasse es einfach
die Eigenschaft visibility bei ready
auf true setzen. Nun, dieses sehr große
Kartensymbol
muss nicht im Editor gezeichnet werden während ich
an meinem Charakter arbeite, sondern es wird gezeichnet,
wenn ich das Spiel starte. Wir haben jetzt unsere Karte, die Umrisse von
Räumen und den
Spielercharakter mit einem Symbol
zeichnet , aber vielleicht möchten wir, dass die Karte mit einer Taste ein- und ausgeschaltet Wir sehen uns im nächsten Video.
35. 4-7 Karte: Hallo Freunde. In diesem Video ermöglichen
wir dem Spieler, die
Karte mit einer Taste zu öffnen und zu schließen. Ab der Spielszene werde
ich die Karte
standardmäßig
ausblenden, indem ich die Sichtbarkeit des
Containerknotens, auf dem sie gespeichert ist, ein- und ausschalte Hängen Sie dann ein neues Skript
an den Container an. Ich verwende zwar derzeit dafür einen
Panel-Container, muss aber auf keine der Funktionen
des
Panel-Containers
in diesem Skript zugreifen Funktionen
des
Panel-Containers und kann
von dem allgemeineren
Steuerelementtyp erben von dem allgemeineren
Steuerelementtyp Wenn ich in Zukunft
einen anderen Typ
von Kontrollknoten verwenden möchte, muss
ich mein Skript nicht
ändern Dieses Skript benötigt
öffentliche Funktionen , um die Map zu öffnen
und zu schließen. Um die Dinge einfach zu halten, setze
ich die Sichtbarkeit
des Knotens entsprechend auf true oder
false. Es gibt auch Funktionen zum Ein
- und Ausblenden die in der
Canvas-Elementklasse
definiert sind und dasselbe tun. Es mag zwar
sinnlos erscheinen,
eine Funktion zu haben , die nur eine andere Funktion
aufruft, Ihre Implementierungen in solche
öffentlichen Funktionen
gekapselt
halten , können
wir sie in Zukunft problemlos aktualisieren Wir können diesen Funktionen zusätzliche Logik
hinzufügen, um Dinge geschehen zu lassen, wenn die
Karte geöffnet oder geschlossen wird,
oder wir könnten einen Tween verwenden, um die Karte außerhalb des Bildschirms zu verschieben oder
sie vergrößern und verkleinern zu lassen, anstatt nur
ihre Sichtbarkeit umzuschalten sie vergrößern und verkleinern zu lassen, anstatt nur . Wenn ich diese Änderungen vornehmen möchte, muss
ich nur dieses Skript bearbeiten und muss nicht auch das Player-Skript oder
andere Skripts bearbeiten ,
die , Da ich mich entschieden habe,
eine Umschalttaste zu verwenden , um
die Map ein- und auszuschalten, anstatt Funktionen zum Öffnen
oder Schließen aufzurufen, hätte
ich lieber eine einzige Umschaltfunktion eine private Variable hinzufüge ob die Map gerade geöffnet
ist oder nicht, lasse
ich mit der
Umschaltfunktion
die Map schließen , wenn sie geöffnet ist, oder
sie öffnen, wenn sie Dann können die Funktionen Öffnen und
Schließen den Wert von Ich
öffne entsprechend
festlegen Beim Öffnen der Projekteinstellungen der Registerkarte Eingabekarte müssen
wir eine
neue Eingabeaktion
zum Öffnen und Schließen der Map hinzufügen . Ich verwende die Rücktaste und die Auswahltaste
auf meinem Controller den meisten Spielen mit dieser
Art von Spielkarte kann der Spieler auch die Kamera
schwenken Ich habe bereits die Eingaben „Nach oben“
und „Nach unten suchen“. Ich füge einfach Look
Left und Look Right hinzu. Mit der linken und rechten
Pfeiltaste oder dem nach links oder rechts
geneigten rechten Stick auf meinem Controller Im Player-Skript können wir eine Variable
exportieren, die einen
Verweis auf den Kartenknoten enthält, und
diese dann in den Inspektor Sie dann in der Eingabefunktion der Karte mit, Teilen Sie dann in der Eingabefunktion der Karte mit, dass sie ein- oder ausgeschaltet werden soll, wenn die
Kartentaste gedrückt wurde Wenn Sie das Spiel starten, wird die
Karte versteckt, aber wenn Sie die Kartentaste drücken, wird die Karte angezeigt und durch erneutes Drücken
wird sie geschlossen Um die Kartenkamera zu schwenken, müssen
wir nur ihren Offset-Wert
anpassen. Also geben wir dem
Kartenskript einen Verweis
auf die Kartenkamera. Hinzufügen einer öffentlichen
Funktion namens pan, die ein Vektor-Zwei-Argument
für die Richtung
akzeptiert, ein Vektor-Zwei-Argument
für die Richtung
akzeptiert in die die Kamera geschwenkt werden
soll. Wir addieren zum Kameraversatz diese Richtung
multipliziert mit einer Pan-Geschwindigkeit, und wir können auf Delta zugreifen,
obwohl wir uns nicht in einer Prozessfunktion befinden, indem wir
die Knotenklassen Get
Process Delta t function aufrufen die Knotenklassen Get
Process Delta t function diese
Pan-Geschwindigkeits-Variable
exportiere, setze ich meine auf 1024 Das mag schnell erscheinen, aber denken Sie daran dass die Kartenkamera sehr weit
herausgezoomt ist, sodass sie sich scheinbar mit einem Achtel der
Geschwindigkeit bewegt Damit das
Spielerskript diese Kamera
steuern kann,
wenn die Map geöffnet ist, muss
es
wissen können, ob die Map geöffnet ist.
Anstatt die Variable
is open öffentlich zu machen und jedem anderen Skript
zu
erlauben, ihren Wert zu ändern, können
wir eine Funktion schreiben, die den Wert
der Variablen
zurückgibt Wenn die Karte geschlossen ist, setze
ich den Offset
der Kamera wieder auf Null zurück, sodass sie wieder auf dem
Spielercharakter
zentriert ist. wir
zum Spielerskript wechseln, fügen
wir in der Prozessfunktion die Steuerelemente für das
Schwenken
der Karte Aber nur, wenn die Karte geöffnet ist. Wenn die Karte geöffnet ist,
weisen wir sie an, zu schwenken. So wie wir die G-Achse verwendet haben, um den Zustand zweier entgegengesetzter
Richtungen als Gleitkommazahl zu berechnen, können
wir den G-Vektor verwenden, um
einen Vektor zwei aus
vier Richtungen zu erhalten . Wir müssen
ihm nur die Namen der vier Eingabeaktionen geben ,
die der X- und Y-Achse
entsprechen. Schau nach links, schau nach rechts, schau nach oben und schau nach unten. Das letzte Argument
ist eine tote Zone, das ist die Mindestlänge des Vektors, der verwendet wird. Wenn der Vektor zu kurz ist, können
wir ihn ignorieren, was für
Analogsticks
nützlich ist , um Drift zu ignorieren. Das wird auf
einem Controller zwar keine Probleme
bereiten, da ich
den rechten Analogstick verwende, aber einem Controller zwar keine Probleme
bereiten, da ich
den rechten Analogstick verwende, meine PC-Steuerung verwendet
die Pfeiltasten sowohl für die
Bewegung als auch für das Schauen. Wenn die Karte geöffnet ist, lege
ich die restlichen Steuerelemente für das
Suchen und die Bewegung in einem Block zusammen, um sie zu überspringen. Wenn du möchtest, dass der
Spielercharakter
sich weiterhin bewegen und nach oben oder unten schauen kann,
während die Karte geöffnet ist, musst
du die
Eingabeaktionen so ändern , dass sie sich nicht überschneiden. Um zu verhindern, dass sich der Charakter nach dem Öffnen der Karte
weiter bewegt, setze
ich seine Bewegungsrichtung auf Null, wenn die Karte geöffnet wird. Der Spieler kann jetzt eine
Taste drücken, um auf eine Weltkarte zuzugreifen, unsere beiden Räume
und die
aktuelle Position des Spielers
angezeigt werden, und wir können die
Kartenkamera schwenken, wenn wir wollen. Im nächsten Abschnitt werden wir
damit beginnen, die Statistiken des Spielers
im Auge zu behalten und
sie auf dem Head-up-Display darzustellen. Wir sehen uns
im nächsten Abschnitt.
36. 5-1 HUD: Hallo Freunde. In diesem Video beginnen
wir damit,
Informationen über den Spielercharakter auf
dem Heads-up-Display anzuzeigen. Seit Beginn dieses Kurses wurde
Godot 4.6 veröffentlicht Die Aktualisierung des Projekts auf Godot 4.6 hat keine Probleme verursacht, daher werde ich die Lektionen
in der aktualisierten Version fortsetzen Ich empfehle nicht, während der
Arbeit an
einem Projekt auf eine neuere Version einer
Game-Engine zu aktualisieren während der
Arbeit an
einem Projekt auf eine neuere Version einer
Game-Engine ,
es sei denn, Sie haben Versionskontrolle, um bei Bedarf
zurückzukehren Ich muss
einige UI-Sprites in
mein Projekt importieren , um die
Charakterstatistiken auf dem In der Spielszene haben wir eine Leinwandebene, die
im Inspektor auf Ebene eins
eingestellt ist im Inspektor auf Ebene eins
eingestellt Das Hauptfenster, in dem
die beiden D-Welten des Spiels dargestellt werden,
wird als Ebene Null betrachtet Alles in der
Zwei-D-Welt des Spiels wird also unabhängig von ihrem Z-Index auf Ebene Null
gezeichnet Leinwandebene, Ebene eins, wird all das überziehen,
um Dinge wie Menüs und das
Kopfdisplay unserer Charaktere wie
Gesundheit und Magie zu zeichnen. den Knoten auf der Canvas-Ebene
handelt es sich in der Regel um Kontrollknoten von Goy. Sie sind alle mit
grünen Symbolen gekennzeichnet, um sie von zwei blauen
D-Knoten zu unterscheiden Beginnen wir damit,
einen Kontrollknoten als untergeordnetes Element
der Canvas-Ebene hinzuzufügen , ihn in HUD
umzubenennen, ihn so
anzuordnen, dass er sich
ganz oben in den untergeordneten Objekten der Canvas-Ebenen
befindet, und die
Map zu einem untergeordneten Element des HUD machen Anschließend können wir
diesem übergeordneten Knoten so
viele Symbole, Messanzeigen
und Text hinzufügen, wie wir benötigen, um unser Head-up-Display zu erstellen Es ist aus mehreren Gründen hilfreich, wenn ein einfacher
Kontrollknoten als
übergeordneter Knoten für dein gesamtes
HUD fungiert mehreren Gründen hilfreich, wenn ein einfacher
Kontrollknoten als
übergeordneter Knoten für dein gesamtes
HUD Einige Eigenschaften
des übergeordneten HUD-Knotens werden
von allen untergeordneten Knoten übernommen Da der
Canvas-Layer-Knoten kein Kontrollknoten
ist, hat er nicht
dieselben Eigenschaften kann
daher diesen Vorteil nicht bieten Wenn Sie all
Ihren HUD-Elementen ein
einheitliches Erscheinungsbild verleihen möchten , können
Sie
dem übergeordneten Knoten ein Thema hinzufügen, das angewendet wird automatisch auf alle
untergeordneten Knoten Außerdem bleibt der
Überblendungsübergang auf natürliche Weise am unteren Rand des
Szenenbaums
stehen, da du nur übergeordnete Objekte
hinzufügst, sodass du dir nicht jedes Mal Gedanken darüber machen musst den
Szenenbaum
neu anzuordnen Im Gegensatz zu zwei D-Knoten, die anhand ihrer Eigenschaft „
Transformationsposition definieren, wo sie sich relativ
zum Ursprung der Szene befinden, verwenden
Kontrollknoten
sowohl eine Position eine Größe, um ihre Position
innerhalb eines definierten Raums zu definieren Normalerweise das Spielfenster, das als
dieses blaue Rechteck angezeigt wird. Wir können sehen, dass der
HUD-Knoten eine Größe von 40 mal
40 Pixeln hat und sich an Position 00 befindet, was der oberen linken
Ecke des Fensters entspricht Wir können den Kontrollknoten zwar einfach verschieben und seine Größe ändern, indem wir diese Werte
bearbeiten, diese Änderungen lassen sich nicht gut
skalieren oder funktionieren effektiv, wenn wir
die Fenstergröße in
den Projekteinstellungen ändern würden die Fenstergröße in
den Projekteinstellungen Kontrollknoten haben also diese grünen Anker, mit denen wir die
Position und Größe
jedes Kontrollknotens relativ zu
seinem übergeordneten Knoten festlegen können die
Position und Größe
jedes Kontrollknotens relativ zu
seinem übergeordneten Knoten festlegen jedes Kontrollknotens relativ zu
seinem übergeordneten Knoten , wobei
die Leinwandebene das gesamte
Fenster darstellt Wir möchten, dass das HUD
das gesamte Fenster abdeckt, sodass wir voreingestellten Anker auf Full Wreck setzen
können Dadurch werden die Anker an jeder
der vier Ecken
des Fensters platziert und die werden
dann automatisch entsprechend aktualisiert Werte für Größe und Position Wenn wir die Karte sichtbar machen, wurde
ihre Position nicht aktualisiert, daher setze ich ihre
Anker auf die Mitte zurück Jetzt können wir sehen, dass die Karte
, da sie in der
Mitte des übergeordneten Knotens
verankert ist , Verschieben oder Ändern der Größe des HUD-Knotens durch
Verschieben oder Ändern der Größe des HUD-Knotens so verschoben
wird, dass sie zentriert Um die
Gesundheit und Magie des Charakters darzustellen, füge
ich einen neuen
Kontrollknoten hinzu, in dem
diese Elemente
gruppiert werden, und ich nenne ihn „lebenswichtig Ich lasse ihn oben
links
verankert, setze aber seine Größe auf Null zurück Als Nächstes füge ich einen Knoten mit zerstörter
Textur hinzu, um eine einfache Textur,
ein Profil des Charakters, zu zeichnen und seine
Textureigenschaft aufzufüllen, und seine
Textureigenschaft aufzufüllen indem ich das Asset
aus der Registerkarte „Dateisystem“ ziehe einen weiteren Knoten
mit zerstörter
Textur hinzufüge, nenne ich dieses Gesundheitssymbol
und füge seiner Textur eine nenne ich dieses Gesundheitssymbol
und füge seiner Textur eine Atlas-Textur hinzu. Dabei wähle ich ein Sprite aus meinem
Spritesheet Spritesheet Ich benötige
mehrere davon
, um die Gesamtgesundheit meines
Charakters darzustellen Also werde ich es ein paar
Mal duplizieren und sie
grob nacheinander positionieren. Es wäre eine gute Idee
, diese Symbole unter
einem einzigen übergeordneten Knoten
zusammenzufassen. Also füge ich einen weiteren
Kontrollknoten mit dem Namen Health Counter hinzu und ordne alle Gesundheitssymbole so an,
dass sie diesem Knoten untergeordnet Jedes
dieser Symbole manuell zu positionieren ist ziemlich mühsam Godot stellt also Kontrollknoten sogenannte Container, zur Verfügung
, um dies für uns zu erledigen Da ich möchte, dass diese Symbole horizontal angeordnet
werden, ändere
ich den Typ
des übergeordneten Knotens in einen
horizontalen Box-Container Dadurch werden alle
untergeordneten Knoten automatisch angeordnet. Sie werden so gestreckt, dass sie
die vertikale Höhe des
horizontalen Box-Containers ausfüllen , der
die
Standardgröße von 40 Pixeln hat dieser Wert zurückgesetzt wird,
wird er gezwungen, auf
die Größe
des größten Kindes herunterzufahren auf
die Größe
des größten Ich möchte, dass sie näher
beieinander liegen.
Deshalb stelle ich unter „Theme-Overrides
“ -Abschnittskonstanten den Abstand auf Das Hinzufügen weiterer Symbole
zu diesem Zähler ist so einfach wie das Duplizieren
des Es ist eine gute Idee, Ihre HUD-Elemente unter Berücksichtigung ihrer
maximalen Grenzwerte Ich werde also neun Gesundheitssymbole haben. Das ist
die maximale Anzahl, die
ich in mein Spiel integrieren möchte Wenn Sie einen
der untergeordneten Knoten auswählen, können
deren Positionswerte
nicht mehr manuell bearbeitet werden, da der Containerknoten jetzt
für die Steuerung
ihrer Position zuständig ist . Behalten Sie also diese Einschränkung im Hinterkopf. Wenn Sie
die Positionen dieser
Texturen einzeln animieren wollten , könnten
Sie das nicht tun
, solange
sie sich in einem übergeordneten
Container befinden Als Nächstes füge ich einen weiteren
Knoten hinzu, der die
Textur zerstört hat , um die magische Leiste des
Charakters zu zeichnen Füllen Sie dann die
Textureigenschaft mit dem Asset aus
der Registerkarte „Dateisystem Diese Textur dient zwar nicht als
Maßstab, aber
sie hilft, alles, was Sie auf
Ihrer Motorhaube haben
möchten, zu zeichnen , damit Sie
sich vor der Implementierung
ein Bild davon
machen können, wie es aussehen soll vor der Implementierung
ein Bild davon
machen können, wie es aussehen Wie bei den Gesundheitssymbolen möchte
ich sehen, wie diese
magische Anzeige in
mein Layout passt , wenn sie ihre maximale Grenze erreicht hat. dieses Bild dehnen,
um die Anzeige zu verlängern die einzelnen Pixel
des Bildes
gestreckt , was schlecht aussieht. Wir werden uns im
nächsten Video damit befassen, aber im Moment brauchen
wir nur eine Vorstellung davon, brauchen
wir nur eine Vorstellung davon wie groß oder klein die
Magieanzeige sein kann. Vielleicht möchten Sie sich
etwas Zeit nehmen, um das Layout Ihrer Hüttenelemente so zu
gestalten, wie Sie es möchten. Dieses Layout sieht gut aus. Aber wenn ich mein Spiel starte, ist
es sehr klein und entspricht
nicht
der Pixeldichte des restlichen Spiels. Da ich einen
Kamerazoom von zwei verwende, sind
alle meine Pixel
doppelt so groß. Also setze ich die Skala
meines Vitalknotens auf zwei verdoppele damit die Größe
aller seiner Das ist einfacher zu lesen und passt besser zur Ästhetik
meines Spiels Wenn wir die Anker-Voreinstellungen
des Elternknotens von vitals ändern, können
wir ihn leicht
ändern, um
seine Position relativ
zu einer beliebigen Ecke
des Bildschirms oder zur
Mitte eines beliebigen Randes zu definieren seine Position relativ
zu einer beliebigen Ecke des Bildschirms oder zur
Mitte eines beliebigen Randes Oder die Mitte des
Bildschirms wie auf der Karte. Sie können dann
die Positionen
der untergeordneten Knoten im Verhältnis
zum verankerten übergeordneten Knoten anpassen , sodass sie
ihre relative Position beibehalten auch wenn Sie
die Auflösung Ihres Spiels ändern Ich lasse meinen in der
oberen linken Ecke und gebe
ihm 20 Pixel Abstand
zum Fensterrand Wir haben jetzt einige Texturen auf dem Head-up-Display
gezeichnet, aber sie
machen noch nichts Wir sehen uns im nächsten Video.
37. 5-2 Messgerät: Hallo Freunde. In diesem Video implementieren
wir den Magic
Gauge mithilfe von Style-Boxen. Beginnen wir damit, den
Typ des Magic Gauge-Knotens zu ändern. Es gibt einen
Kontrollknoten, der
genau das tut, was wir brauchen,
einen Fortschrittsbalken. Wenn Sie den Typ ändern,
wird die Textur entfernt. Der Fortschrittsbalken wird
als halbtransparentes
graues Rechteck gezeichnet , und ein Prozentwert
wird als Text angezeigt. Ich möchte diese
Prozentangabe nicht, also deaktiviere ich sie
im Inspektor. Der Umschalter „Unbestimmt“ gilt
nicht für Messgeräte, sondern für Fortschrittsbalken die eigentlich keinen Fortschritt
messen Nachdem wir die Minimal
- und Maximalwerte
für unsere magische Anzeige festgelegt haben, können wir den
Wert auf eine beliebige Zahl
dazwischen setzen, um zu sehen, wie sich der
Fortschrittsbalken füllt Der Schrittwert ist der kleinste Wert,
den der Wert erhöhen kann, wodurch er gezwungen wird, zur nächsten Stufe
zu Die anderen Eigenschaften, die aus dem Bereich
übernommen wurden für
ein Messgerät
nicht wirklich geeignet und können ignoriert werden Wir können auch die
Richtung ändern, in der der Fortschrittsbalken
gefüllt wird, wenn wir möchten. Ich lasse meinen von Anfang bis Ende stehen. Wie der Fortschrittsbalken aussieht
, hängt vom Thema ab. Da wir noch kein Thema haben, wird
das von Godot bereitgestellte
Standarddesign verwendet Wenn wir nur
das Thema für diesen
Knoten selbst ändern möchten , können
wir den Abschnitt „
Theme-Overrides“ erweitern Da ich die
prozentuale Textanzeige nicht verwende, die Farben, Konstanten, sind
die Farben, Konstanten,
Schriftarten und Schriftgrößen irrelevant. Sie können
sie jedoch verwenden, um zu ändern, wie die Schrift auf Ihrem
Fortschrittsbalken geschrieben wird, wenn Sie möchten Im Bereich „Stile“
finden Sie die Stilfelder für die Darstellung des Hintergrunds
und der Füllung der Fortschrittsbalken. auf das Drop-down-Menü klicken, können
wir ein leeres Stilfeld auswählen, wodurch einfach nichts gezeichnet wird. Stylen Sie die Box-Linie, um
nur eine einfache Linie zu zeichnen, stylen Sie die Box flach, um
ein einfaches Rechteck zu zeichnen , oder stylen Sie die Box-Textur, um
ein importiertes Textur-Asset zu verwenden. auf die
Style-Box-Textur klicken um ihre Eigenschaften zu erweitern, können
wir die
Textureigenschaft
mit einem Asset aus
der Registerkarte Dateisystem füllen mit einem Asset aus
der Registerkarte Dateisystem Wenn wir die Größe
des Fortschrittsbalkens ändern, wird
die Textur so
gestreckt, dass sie den Raum ausfüllt, was nicht sehr gut aussieht Style-Boxen verfügen über mehr Eigenschaften , mit denen Sie ändern können, wie das Bild gezeichnet
wird, wenn es gestreckt wird. die Texturränder wird die Textur
in neun Segmente umgewandelt Durch die Texturränder wird
die Textur
in neun Segmente umgewandelt. Dabei wird das Bild zweimal horizontal und
zweimal vertikal aufgeteilt, sodass es
in neun Segmente aufgeteilt wird Die Ecken werden
nicht gestreckt. Die Kanten werden
nur in eine Richtung gestreckt , um die Ecken
miteinander zu verbinden, und die Mitte
wird in
beide Richtungen gestreckt , um den
Rest des Raums auszufüllen. Oder wir können
das Zeichnen der Mitte der Textur ausschalten und nur die Ränder zeichnen Wenn Sie nicht möchten die einzelnen Segmente gestreckt
werden, Eigenschaften für
die Achsenstreckung bieten Ihnen die Eigenschaften für
die Achsenstreckung die Option, stattdessen Kachelung zu
verwenden, oder bei der Option „Kachelanpassung“
wird eine Kombination aus
Kachelung und Dehnung verwendet , um dem zugewiesenen Raum
optimal zu entsprechen Erweitern der Ränder wird die Textur
über das Rechteck hinaus
gezeichnet , das
durch die Position und Größe der Knoten definiert durch die Position und Größe der Knoten Eine Unterregion kann verwendet werden , um einen Bereich
eines Spritesheets zu zeichnen Modulate funktioniert genauso wie die Sichtbarkeit des
Canvas-Elements. Dabei wird die Farbe
jedes Pixels mit dieser Farbe
multipliziert Inhaltsränder sind für Stilfelder vorgesehen, die zum
Zeichnen von Containerknoten verwendet werden, sodass sie hier nicht
relevant sind Wenn Sie eine weitere
Style-Box-Textur für
die Fortschrittsbalken hinzufügen , füllen Sie sie
und füllen Sie sie mit
der entsprechenden Textur Wenn Sie
die
Texturbereichswerte nicht manuell eingeben möchten , können Sie
den
Unterregionseditor auch verwenden, um die
Texturränder visuell zu bearbeiten Bei Verwendung dieser Elemente der Magic Gauge nicht dazu gedacht
, vertikal gestreckt zu werden. Ich stelle die Höhe
auf 16 Pixel so ein, dass sie
der Höhe der Elemente entspricht . Mithilfe der Stilfelder kann
das Messgerät jedoch horizontal
beliebig weit gestreckt werden , und es wird ohne
Dehnung der Pixel gezeichnet. Der Wert kann auch bearbeitet werden,
und die Fülltextur wird ebenfalls so weit wie nötig gedehnt ohne dass die Enden des
Balkens gestreckt werden. Wenn wir möchten, dass
diese Stilfelder auf mehr als
nur einen Fortschrittsbalken angewendet werden, können
wir dies
automatisch machen, indem wir
das Design bearbeiten , anstatt Theme-Overrides zu
verwenden den HUD-Knoten auswählen und dann den Themenbereich
erweitern, können
wir
aus der Drop-down-Liste ein neues Thema erstellen Wenn Sie auf die
Themenressource klicken, wird das Themenfenster am
unteren Rand des Editorfensters geöffnet. Hier können wir die meisten
Kontrollknoten sehen, die Godot
zu bieten hat , und wie sie
derzeit vom Thema
gezeichnet werden , einschließlich eines Fortschrittsbalkens hier. auf die Plus-Schaltfläche klicken, können
wir
diesem Thema einen Fortschrittsbalken hinzufügen und
seine Designeigenschaften überschreiben , genauso wie wir
es
im Inspektor für
den Fortschrittsbalkenknoten getan haben Für Farben,
Konstanten, Schriften,
Schriftgrößen und Stile stehen hier dieselben
Theme-Eigenschaften Konstanten, Schriften,
Schriftgrößen und Stile Wenn wir auf die Plus-Schaltflächen
neben Hintergrund und Füllung klicken , können
wir diesem Thema Stilfelder
für
den Fortschrittsbalken hinzufügen diesem Thema Stilfelder
für
den Fortschrittsbalken Da wir
diese Stilfelder bereits erstellt
haben, können wir den
Fortschrittsbalkenknoten auswählen. Klicken Sie dann auf die Ressourcen der
Stilbox und ziehen Sie aus dem Inspektor
in den Theme-Editor. Der Fortschrittsbalken in
der Theme-Vorschau wurde aktualisiert und verwendet nun
die Style-Boxen. Jetzt
erbt jeder Fortschrittsbalken, der vom
HUD-Knoten erbt dieses Thema und verwendet diese Stilfelder, um den
Fortschrittsbalken automatisch zu zeichnen Dies gibt uns die
Möglichkeit alle Kontrollknoten
desselben Typs auf die gleiche
Weise zeichnen zu lassen oder Theme-Overrides
zu verwenden , um einzelne Kontrollknoten unterschiedlich zu zeichnen Wir können die
Theme-Overrides
aus dem Fortschrittsbalkenknoten entfernen aus dem Fortschrittsbalkenknoten da diese Stilfelder nun vom
HUDS-Theme übernommen
werden Wenn Sie
dieses Thema für
Ihr gesamtes Projekt verwenden möchten , ohne es
in jede Szene kopieren zu
müssen, können
Sie es als Projektressource speichern Dann können wir in den Projekteinstellungen unter GUI-Thema
ein benutzerdefiniertes Thema festlegen, indem wir die gespeicherte Themenressource auswählen Dies erfordert einen Neustart
des Editors, um wirksam zu werden. Jetzt wird jeder Fortschrittsbalken in jeder Szene des
gesamten Projekts auf die gleiche Weise gezeichnet Stellen wir uns jedoch vor,
Sie möchten
mehrere magische Anzeigen haben , die
diese Stilfelder verwenden, und mehrere andere Fortschrittsbalken
, die andere Stilfelder verwenden Anstatt
mehrere Themen zu haben, können
wir Variationen des
Thementyps verwenden auf die Plus-Schaltfläche klicken, können
wir einen benutzerdefinierten
Namen eingeben,
der dem Thema hinzugefügt werden soll, z. B. Magic Gauge. Klicken Sie dann auf die Schaltfläche Tools
und geben Sie ihr einen
Basis-Typ-Fortschrittsbalken , indem Sie ihn
entweder eingeben oder aus der Liste auswählen
. Jetzt enthalten die anderen Registerkarten die Eigenschaften, die
von der Fortschrittsleiste übernommen wurden, und wir können die Werte
der Felder Hintergrund und
Füllstil ändern . Ich kopiere die Stilfelder
aus meinem Magic Gauge-Knoten und klicke
dann auf das
Kettengliedsymbol, um die Verknüpfung zu der
Stelle aufzuheben, an der sie kopiert wurden Wenn ich zu den Eigenschaften des
Fortschrittsbalkendesigns wechsle, entferne
ich die Stilfelder und setze alles wieder
auf das Standarddesign zurück Wählen Sie dann den
Magic-Gauge-Knoten im Szenenbaum
aus und erweitern Sie den
Themenbereich im Inspektor Ich kann Magic Gauge
in der Typvariante auswählen, um ihnen
mitzuteilen, dass sie
die Theme-Eigenschaften
für das Magic Gauge verwenden sollen. Jetzt kann mein Spiel bei
Bedarf
mehrere Magieanzeigen haben, ohne dass ich die Stile für jeden
von ihnen einzeln einrichten die Stile für jeden
von ihnen einzeln Ich muss dem Theme nur sagen, dass es die Eigenschaften des
Magic-Gauge-Designs
verwenden soll , und ich kann immer noch
andere Fortschrittsbalken in
meinem Spiel haben und ich kann immer noch
andere Fortschrittsbalken in
meinem Spiel haben, bei
denen es sich
nicht um Zauberanzeigen handelt, sondern die auch in
verschiedenen Stilen gezeichnet werden können Wir haben jetzt eine
einfache Zauberanzeige, aber wir müssen noch den Gesundheitszähler
implementieren Wir sehen uns im nächsten Video.
38. 5-3 Symbol: Hallo Freunde. In diesem Video erstellen
wir ein
Gesundheitssymbol mit
Animationen, die anzeigen, wann der Charakter seine Gesundheit
wiedererlangt oder verliert Derzeit werden die
Gesundheitssymbole als Knoten mit zerstörter
Textur angezeigt , die
horizontal nach dem Containerknoten der horizontalen
Box angeordnet horizontal nach dem Containerknoten der horizontalen
Box Wenn Sie
diese als Sprites animieren
möchten, könnten Sie sie
in Animated
Sprite Two D Nodes umwandeln in Animated
Sprite Das Mischen von Kontrollknoten mit
zwei D-Knoten verursacht jedoch zwei D-Knoten Ich werde schnell
die
Animations-Sprite-Frames-Ressource einrichten die
Animations-Sprite-Frames-Ressource , damit ich das demonstrieren kann Zwei D-Knoten
verhalten sich nicht wie Kontrollknoten. Sie verankern
ihre Positionen nicht Verhältnis zu ihren übergeordneten Knoten, werden Containerknoten
organisiert Größe
wird auch nicht automatisch an die Fensterauflösung
angepasst Anstatt den
Typ des verwendeten Knotens zu ändern, müssen
wir diesen
Textur-Wret-Knoten so animieren, wie Wenn wir das Drop-down-Menü für
Textureigenschaften erweitern, können
wir sehen, dass es eine Option für
animierte Texturen gibt Diese animierte Texturressource kann
bereits nur eine
einzige Animation enthalten , sie entspricht in diesem Fall nicht wirklich unseren
Bedürfnissen Wenn wir damit das Symbol animieren wollten, müssten
wir jedes
einzelne Bild
der Animation über
diese klobige Oberfläche als
separate Atlas-Textur mit
einer Dauer in Sekunden festlegen einzelne Bild
der Animation über
diese klobige Oberfläche als separate Atlas-Textur mit separate Atlas-Textur mit
einer Dauer in Sekunden Und nach all dem müssten
wir
ein benutzerdefiniertes Skript verwenden, um zu kontrollieren, welche Frames der Animation trotzdem verwendet
werden Wenn wir dieselbe Textur haben
wollten, sollten mehrere Animationen
abspielen. Es wäre also besser,
diese Textureigenschaft
als Atlas-Textur zu belassen . Wir könnten zwar ein
benutzerdefiniertes Skript schreiben, um
den Wert der
Regionseigenschaft dieser Atlas-Textur zu ändern , der Zeit- und Arbeitsaufwand würde
sich nicht wirklich lohnen, wenn der Animation Player-Knoten bereits existiert. Fügen wir also einfach einen
Animation Player-Knoten als untergeordnetes Element dieses Gesundheitssymbols hinzu. Bevor wir irgendwelche Animationen machen, wäre
es eine gute Idee,
dieses Symbol zuerst als
eigene Szene zu speichern . Dadurch wird der
Animation Player-Knoten gekapselt, da er für den Kontext des
HUD
des Spiels nicht wirklich relevant ist In dieser Szene setze
ich zunächst den
Symbolbereich auf den Standardstatus, den ich als Standardstatus
verwenden möchte . Dieser ist
leer Erstellen Sie dann eine neue Animation
für den Fall, dass sich dieses Symbol füllt, stellen Sie die Bildrate
auf 12 Bilder pro Sekunde ein, passen Sie den Zoom an und
aktivieren Sie den Frame-Snapping Ich setze das Bild dann mit einem Keyframe
an den Anfang
der Animation und füge
es dem Reset-Track hinzu Auch wenn ich
das nicht als ersten Frame der Animation verwenden möchte , ist
es jetzt
der Standardstatus, der von der
Reset-Animation verwendet
wird. Als Nächstes überschreibe ich
den ersten Schlüssel
meiner Füllanimation mit
dem eigentlichen ersten Frame Fahren Sie dann mit den restlichen Frames fort,
die das Symbol ausfüllen Ich setze die Dauer der
Animation auf acht Frames. Denken Sie daran,
den Aktualisierungsmodus
auf diskret zu ändern , wenn Sie
Frame-Animationen wie diese verwenden. Das sieht gut aus, also werde
ich es duplizieren und eine weitere Animation
erstellen wenn der Charakter Schaden erleidet, wodurch das Symbol geleert wird. Da ich weiß, dass meine
Spritesheet-Sprites alle gleichmäßig verteilt
sind, kann
ich die Werte für die eingegebenen Bereiche einfach
um ein Vielfaches
von 32 Pixeln bearbeiten , um die gewünschten Frames zu
erhalten Diese Animation ist mit nur sechs Frames kürzer
. Es ist wichtig, dass diese
Animationen mit
dem Frame enden , der auch nach
dem Ende erhalten bleibt. Sobald diese leere Animation abgespielt wird, bleibt
das Symbol leer, bis die
Füllanimation abgespielt wird. Ebenso bleibt das Symbol nach dem Abspielen
der
Füllanimation gefüllt, bis die leere Animation abgespielt wird . Anhängen eines Skripts an den Stammknoten des Integritätssymbols und Speichern dieses Skripts in einem neuen
Ordner für UI-Skripte Wir gehen davon aus, dass dieses
Skript für
jedes animierte Symbol verwendet werden kann jedes animierte Symbol falls wir es für
etwas anderes als Gesundheit verwenden möchten Dieses Skript benötigt nur dann einen Verweis auf den
Animation
Player-Knoten , wenn es bereit ist. Stellen Sie dann bei Bedarf öffentliche Funktionen bereit, um jede der
Animationen
abzuspielen. Zurück in der Spielszene können wir alle
anderen Gesundheitssymbole
löschen. Ich benenne dieses
erste in das Gesundheitssymbol um und
dupliziere es dann
achtmal, um
den Rest mit dem
Animation Player und dem angehängten
Skript neu zu erstellen den Rest mit dem
Animation Player und dem angehängten
Skript Wenn wir das testen wollen, können
wir das
Player-Skript verwenden, um
dem Gesundheitssymbol per Tastendruck mitzuteilen , ob es gefüllt
oder leer sein Wenn ich die Run-Taste drücke, verwende
ich den mit dem
Dollarzeichen versehenen Knotenpfad, um diesem
ersten Gesundheitssymbol mitzuteilen, dass es gefüllt werden soll Wenn ich die Run-Taste loslasse, mache
ich dasselbe,
um zu sagen, dass es leer Da dies nur zu
Testzwecken dient, muss
ich mir keine Gedanken darüber machen, wie
ineffizient dieser Code ist das Spiel starten und die Run-Taste
drücken, alle Symbole
gefüllt,
obwohl ich nur
dem ersten gesagt habe, dass es gefüllt werden soll Das liegt daran, dass Godot natürlich versucht, so
ressourcenschonend wie
möglich zu sein , und
nur eine Atlas-Texturressource erstellt hat nur eine Atlas-Texturressource , die für alle Symbole verwendet werden kann Wenn wir also ein Symbol animieren, verwenden
alle Symbole dieselbe Textur, sodass alle animiert sind In der Gesundheitssymbol-Szene können
wir dieses Verhalten überschreiben, indem die
Atlas-Texturressource im Inspektor
erweitern Aktiviere im Bereich „Ressourcen“ die Option
„Lokal
zur Szene“ Dadurch wird Godot mitgeteilt, dass jede Instanz
der Szene eine
eigene Kopie
dieser Atlas-Texturressource
mit eigener Regionseigenschaft benötigt eigene Kopie dieser Atlas-Texturressource
mit eigener Regionseigenschaft Dieses Spritesheet
wird weiterhin von allen Icons gemeinsam genutzt, aber welche Region
des Spritesheets sie zeichnen, wird Das Spiel wird erneut ausgeführt.
Diesmal füllt sich nur das erste Symbol, wenn ich
die Run-Taste drücke und leert sich, wenn ich die
Taste loslasse Wenn der Test erfolgreich ist, können
wir
die zusätzlichen Codezeilen entfernen oder auskommentieren Wir haben jetzt animierte
Gesundheitssymbole, aber der Gesundheitszähler zählt nicht wirklich die Gesundheit unseres
Charakters. Wir sehen uns im nächsten Video.
39. 5-4 Zähler: Hallo Freunde. In diesem Video schreiben
wir ein
Skript, das
die animierten Symbole so verwaltet, dass die animierten Symbole so verwaltet, einen Wert und
einen Maximalwert
widerspiegeln. Wir haben hier unsere animierten Symbole, aber wir müssen ein Skript
an den übergeordneten Knoten anhängen , das steuert,
wie und wann sie animiert werden , um die Zählung der Gesundheit des
Spielercharakters
widerzuspiegeln Ich nenne dieses Icon Counter und lege es in den Ordner
UI-Skripts Dieses Skript enthält nichts speziell die Funktionen
des horizontalen Box-Containers nutzt . Deshalb werde ich den
generischeren
Steuerungstyp erweitern, sodass ich
den Typ dieses Knotens
später ändern kann , wenn ich möchte. Das Skript
benötigt zwei ganze Zahlen, eine für die
maximale Gesundheit des Charakters und eine weitere für seine
aktuelle Gesundheit Da ich möchte, dass dieses Skript nützlich ist,
um alles zu
zählen, nicht nur Gesundheit, werde ich
den Oberbegriff Wert verwenden Vorerst können wir
den Standardwert für maximale Gesundheit so festlegen, dass er
der Anzahl der Kinder
entspricht diesen Knoten haben,
die das Tag on ready verwenden. Als Nächstes benötigen wir zwei
öffentliche Funktionen , die beide
Werte setzen, indem sie einen Integer-Parameter akzeptieren und den alten
Wert durch den neuen überschreiben Wenn unser
Spielercharakter Schaden
erleidet und
seine Gesundheit wiedererlangt, können
wir
diese öffentlichen Funktionen aufrufen, um Spieler die
Änderungen des Gesundheitswerts
mitzuteilen Es liegt in der Verantwortung dieses Skripts, zu kontrollieren,
wie viele Symbole
angezeigt werden und welche,
basierend auf den Werten
dieser Ganzzahlen und
wie sie sich ändern, gefüllt oder geleert
werden basierend auf den Werten
dieser Ganzzahlen und
wie sie sich ändern dieser Ganzzahlen und
wie sie Wir beginnen damit,
den Wert ihrer
aktuellen Gesundheit festzulegen den Wert ihrer
aktuellen Als Erstes sollten wir überprüfen, ob
es sich bei der Zahl auf die
wir den
Wert setzen sollen, um eine gültige Zahl handelt. Wir können den Charakter nicht anzeigen,
der weniger als null Lebenspunkte hat
, und auch nicht mehr
als die Anzahl der verfügbaren Symbole,
also seine maximale Gesundheit. Also setzen wir den
Wert zunächst auf den Rückgabewert
einer Ganzzahl zwischen
Null und maximaler Gesundheit. Wenn wir versuchen, diese Funktion
mit einer negativen Zahl aufzurufen, wird
sie stattdessen health
auf Null setzen. Und ebenso wird alles, was über dem Maximum liegt, auf das Maximum
begrenzt Wenn wir als Nächstes
den Wert auf dieselbe
Zahl setzen, die er bereits ist, sollten
wir nichts tun
müssen, also könnten wir einfach
aus dieser Funktion zurückkehren Sobald wir festgestellt haben, dass
wir den Wert, der von
diesem Symbolzähler
angezeigt
wird, in eine neue gültige Zahl ändern von
diesem Symbolzähler
angezeigt
wird , unterscheidet sich
der Vorgang, je nachdem, ob die Zahl steigt
oder fällt. Wenn der neue Wert größer
als der alte Wert ist, weisen wir einige
der Symbole an, dass sie gefüllt werden sollen. Aber welche Symbole? Die Symbole
werden praktischerweise vom horizontalen Box-Container in derselben Reihenfolge gezeichnet wie ihr
untergeordneter Index im Szenenbaum. Mithilfe einer einfachen Schleife
mit vier Schleifen und I als Index können
wir den
Wertebereich bis zum neuen Wert durchzählen. Range gibt ein Array zurück, das die Folge
von ganzen Zahlen
enthält , die
von der ersten bis
zur zweiten Zahl hochgezählt werden, schließt
jedoch die zweite Wenn also der alte Wert eins
und der neue Wert vier war, erhalten wir die
Zahlen eins, zwei und Da der Index
des ersten untergeordneten Elements Null und
nicht Eins ist ,
passt dies perfekt zu den Indizes der Symbole
, die gefüllt werden müssen. Also werden wir den untergeordneten Knoten auf Index I setzen und ihm sagen, dass er gefüllt werden soll. Das Verfahren zum Verringern
des Werts ist sehr ähnlich. Nur weil wir wissen, dass der neue Wert kleiner
als der alte Wert ist, müssen
wir der Bereichsfunktion
ein zusätzliches Argument
geben , nämlich ein
negatives, das ihr
sagt, dass sie herunterzählen soll. Wenn der alte Wert vier war
und der neue Wert eins ist, range 43 und zwei zurück. Diese sind nicht
identisch mit den untergeordneten Indizes der Symbole,
sondern sind um eins größer. Wir können das also beheben, indem wir in
der Funktion „Get Child“ eins von I
subtrahieren und diese Icons so einstellen,
dass sie Erst wenn das alles erledigt ist, setzen
wir den alten Wert
auf den neuen Wir können das
testen,
ohne zusätzliche Skripte
oder Eingabezuordnungen hinzuzufügen ohne zusätzliche Skripte
oder Eingabezuordnungen Wir müssen dem Skript lediglich eine
Eingabefunktion hinzufügen. Zunächst prüfen wir, ob
das Eingabeereignis
eine Eingabeereignistaste war und ob es sich bei dem Ereignis um
eine Taste handelte, die gedrückt wurde. Verwenden Sie dann eine Match-Anweisung für
den Tastencode des Ereignisses. Wenn es sich bei der
gedrückten Taste um eine der Zifferntasten handelt, können
wir den
Wert des Symbolzählers auf diese Zahl setzen eine
Zahlenvariable als Ganzzahl deklarieren, können
wir die Zahl, die gedrückt wurde, berechnen
, indem wir einfach Taste Null
vom Event-Tastencode
subtrahieren Das funktioniert, weil
Tastencodes eine Aufzählung sind, eine einfache nummerierte Liste . Was auch immer der Schlüsselcode für Schlüssel Null
ist, der Schlüsselcode für Schlüssel
Sieben wird der Schlüsselcode für
Schlüssel Null plus Sieben
sein Wir können eine Anweisung ausdrucken, die so etwas wie Set
Current Health Two plus die in eine Zeichenfolge umgewandelte
Zahl
sagt Current Health Two plus die in eine Zeichenfolge umgewandelte
Zahl Rufen Sie dann die
Set-Value-Funktion auf und übergeben Sie die Zahl. Wenn wir das Spiel starten, wird durch Drücken einer beliebigen Zifferntaste
der Symbolzähler auf
diese Zahl gesetzt und
die Symbole animiert , je nachdem, ob sie
gefüllt oder geleert werden Und dasselbe können wir auch für die Einstellung des Maximalwerts Wir könnten zwar bereits die
maximale Anzahl von Symbolen in
der Szene haben und nur diejenigen
ausblenden, die wir nicht verwenden, es wäre skalierbarer, neue Symbole
nach Bedarf zu instanziieren Da dies nicht sehr oft
vorkommt, es keinen Einfluss auf die Leistung
und ermöglicht es,
so viele weitere hinzuzufügen , wie wir benötigen, falls wir später die maximale Anzahl
einstellen möchten Also werden wir eine
Variable exportieren, um
die Icon-Szene
als gepackte Szene zu speichern . Den Inhalt
der Sollwertfunktion kopieren. Nachdem Sie jede Instanz
eines Werts auf den Maximalwert geändert haben, müssen nur noch wenige
Änderungen vorgenommen werden. Erstens können wir
den Maximalwert nicht
anhand seiner selbst validieren . Wir müssen also eine Grenze setzen , wie hoch der
Höchstwert möglicherweise sein kann. Möglicherweise möchten Sie
diese Obergrenze exportieren , anstatt einen Wert
fest zu codieren. Anstatt Symbole auszufüllen, werden
wir neue Symbole instanziieren und sie als Kinder hinzufügen Und anstatt Symbole zu leeren, werden
wir sie aus dem Szenenbaum entfernen, indem wir sie kostenlos Um das zu testen, verwende ich dasselbe
Zifferntasteneingabesystem, setze aber den Maximalwert fest, indem ich
den Aufwärtspfeil gedrückt halte Maximalwert fest, indem ich
den Aufwärtspfeil Wenn also die Eingabepunkt-Aktion
gedrückt wird, suche nach oben, dann drucke ich Max
Health aus und stelle
stattdessen diesen Wert ein und füge den aktuellen
Gesundheitsteil in den anderen Block ein. das Spiel starte, kann ich
den maximalen
Gesundheitswert ändern , indem ich
den Aufwärtspfeil gedrückt
halte und eine der
Zifferntasten drücke und den Aufwärtspfeil loslasse Ich kann auch weiterhin den
aktuellen Gesundheitswert ändern. Denk daran, die
Eingabefunktion nach dem Testen auszukommentieren. Wir haben jetzt einen animierten
Symbolzähler, der die
maximalen und aktuellen
Gesundheitswerte der Spielercharaktere
verfolgen kann der die
maximalen und aktuellen
Gesundheitswerte der Spielercharaktere
verfolgen . Aber weder der
Gesundheitssymbolzähler noch die Magieanzeige sind tatsächlich mit dem
Spielercharakter verbunden. Wir sehen uns im nächsten Video.
40. 5-5 Verletzungsbox: Hallo Freunde. In diesem Video geben
wir dem Charakter
etwas Gesundheit, damit er sich
mit dem
Gesundheitssymbolzähler verbinden kann. Wir könnten
dem Charakterskript Gesundheitsvariablen hinzufügen und es auf diese Weise verfolgen. Dies würde es
jedem Charakter in
unserem Spiel ermöglichen ,
ohne zusätzliche Arbeit gesund zu sein. Aber wenn wir bedenken
, dass Dinge, die
keine Charaktere sind , möglicherweise auch Gesundheit
benötigen, wie zum Beispiel zerbrechliche
Wände, wird
das weniger vorteilhaft, zumal unser
Charakter ein Charakterkörper
zwei D ist und die zerbrechliche
Mauer ein statischer Körper zwei D. Und vielleicht haben
wir noch einen starren Körper
für D, der ebenfalls Gesundheit benötigt Fälle müssten wir
dieselben Variablen und Für jeden dieser Fälle müssten wir
dieselben Variablen und
Funktionen in mehreren Skripten verwenden Wir könnten unser
Charakterskript so umschreiben , dass es von
Physics Body Two D übernommen wird.
Alles in unserem
Spiel, das
Gesundheit benötigt, kann dieses Skript ebenfalls verwenden Aber es gibt eine Menge Dinge
in diesem Skript, die diese anderen Objekte nicht
anwendbar
wären Es wäre verschwenderisch
, all diese Variablen und
Funktionen an eine zerbrechliche Wand
anzuhängen , die sie niemals benutzen
müsste , und ebenso die Variablen und
Funktionen, die für
eine zerbrechliche Wand gedacht
sind , an unseren Charakter
anzuhängen In solchen Fällen möchtest
du vielleicht das zusammengesetzte
Muster anstelle der
objektorientierten Vererbung verwenden , um deine Skripte in
deinem gesamten Spielprojekt
wiederzuverwenden Durch die Erstellung einer Gesundheitskomponente kann
diese unabhängig
davon existieren, womit sie verknüpft ist. Charaktere können eine
Gesundheitskomponente haben und zerbrechliche Wände können auch
eine Gesundheitskomponente haben In der Charakterszene fügen
wir ein neues Kind hinzu,
einen D-Node in Area Two, und nennen es Hurt Box Fügen Sie dann einen TD-Node mit
Kollisionsform als untergeordnetes Element der Hurt
Box hinzu, um deren Form zu definieren. Dies ist der Bereich in
der Luft,
in dem ein Charakter Schaden erleidet,
wenn er getroffen wird. Möglicherweise
möchtest du nicht immer, dass dies der Kollisionsform
ihres Charakters
entspricht. Außerdem solltest du
generell immer wollen, dass die
Kollision des Charakters aktiv bleibt, während die Verletzungsbox oft
ausgeschaltet ist, um zu verhindern, dass der Charakter beispielsweise
beim
Ausweichen oder in
Zwischensequenzen Schaden Ausweichen oder in
Zwischensequenzen Es hilft also, deiner Hurt-Box
einen separaten Kollisionsbereich zu
geben einen separaten Kollisionsbereich Ich mache meine auch zu einer Kapsel, aber etwas kleiner als
der Hauptteil des Charakters und setze ihre Debug-Farbe auf Grün, damit ich
sie leichter voneinander unterscheiden kann Dieser Bereich muss nicht für die
Überwachung von irgendetwas
verantwortlich sein Überwachung von irgendetwas
verantwortlich Es muss nur überwachbar sein, damit Hit-Boxen es erkennen können den Kollisionsbereich
unter Kollisionsobjekt zwei D erweitern , können
wir dieses Objekt so einstellen, dass es sich auf Ebene zehn befindet und seine
Maske vollständig entfernen In den Projekteinstellungen gebe
ich zwei D Physics Layer Ten den Namen Spieler Hurt Box. Jetzt kann alles im Spiel,
das Schicht zehn sowohl überwacht als auch maskiert , den
Spielercharakter verletzen Wenn ich ein Skript an diesen Knoten anhänge,
nenne ich es Hurt Box Dieses Skript benötigt
die gleichen Werte für maximale Gesundheit und dieselben aktuellen Integritätswerte
wie für den Symbolzähler Da ich den
Gesundheitswert mit Symbolen angeben werde, müssen
diese Ganzzahlen sein Wenn du eine Anzeige für die Gesundheit
deines Charakters verwendest,
hast du die Möglichkeit, stattdessen Gleitkommazahlen zu
verwenden da eine Anzeige Dezimalwerte
anzeigen kann Im Moment setze ich die
maximale Gesundheit einfach auf fünf und verwende den Tag on ready, um die aktuelle
Gesundheit auf Max Health zu
setzen Im Gegensatz zum Icon-Counter-Skript verändert eine Verletzungskiste
den Wert der
aktuellen Lebenspunkte hauptsächlich den Wert der
aktuellen Lebenspunkte dadurch, dass sie
Schaden
durch die Trefferbox erleidet
oder Lebenspunkte wiederherstellt. Das werden also unsere
öffentlichen Funktionen sein, denen
beide
akzeptieren, dass eine bestimmte Menge an
Lebenspunkten als Ganzzahl verloren oder
gewonnen wird. Wenn wir Schaden erleiden,
ziehen wir einfach den Betrag von der aktuellen Gesundheit des
Charakters Wir können dann die Max-Funktion verwenden um entweder
diesen Wert oder Null zurückzugeben,
je nachdem, welcher Wert größer ist, und als neuen
Wert für die aktuelle Gesundheit
festlegen Dadurch wird verhindert, dass ihr Gesundheitszustand jemals unter Null fällt Wir können die
Wiederherstellungsfunktion mehrfach verwenden, indem wir dem
Parameter einen Standardwert geben. Wenn wir diese
Wiederherstellungsfunktion ohne Argumente aufrufen, gehen
wir davon aus, dass dies bedeutet, dass
sie ihre gesamte Gesundheit bis zu
ihrer maximalen
Einstellung für aktuelle
Gesundheit auf maximale Gesundheit wiederherstellen sollten Gesundheit bis zu
ihrer maximalen . Wenn der Wiederherstellungsfunktion ein Argument übergeben
wurde, addieren
Sie diesen Betrag zur aktuellen Gesundheit
des Charakters und verwenden die MIN-Funktion,
um entweder
dieses Ergebnis oder Max Health zurückzugeben ,
je nachdem, welcher Wert niedriger ist. Die aktuelle Gesundheit wird also niemals die maximale Gesundheit
überschreiten. In beiden Fällen
wird der Wert der aktuellen Gesundheit geändert und diese Änderung muss im
Zähler auf dem HUD
wiedergegeben werden Zähler auf dem HUD
wiedergegeben Aber die Hurt-Box befindet sich in der Charakterszene und der Symbolzähler
in der Spielszene In den meisten Fällen ist es am besten,
wenn Informationen
zwischen Knoten und
verschiedenen Szenen
ausgetauscht werden müssen Informationen , Signale
zu verwenden und ihre
Verbindung über
ihren engsten gemeinsamen Vorfahren In der Spielszene
ist
der
Stammknoten der Spielszene, der Spielmanager, der engste gemeinsame Vorfahr
zwischen dem Charakter und dem Gesundheitszähler und dem Geben wir dem
Gesundheitszähler einen eindeutigen Namen. Schnappen Sie sich dann
im Game Manager-Skript einen Verweis darauf. Wir könnten versuchen,
dem Gesundheitszähler
mitzuteilen , dass er die Hurt-Box des
Charakters überwachen soll. Wir können die Funktion Get Node verwenden , um die Hurt-Box des
Charakters abzurufen. Aber dann stützt sich unser
Icon-Counter-Skript auf bestimmte Funktionen oder Variablen die in der Entität
vorhanden sind, die
es überwacht. Es wäre also im Grunde nur als Gesundheitszähler nützlich
, der nicht
als Skript zum Zählen
anderer Dinge wiederverwendet werden kann. diese Logik umzukehren,
wäre es besser,
der Hurt-Box mitzuteilen , dass sie
von diesem Symbolzähler überwacht werden soll Rufen Sie dann eine Funktion auf, die wir
noch nicht geschrieben haben, wie set counter, und übergeben sie
als Argument an den Gesundheitszähler Denken Sie daran, dass diese Funktion zum Abrufen von
Knoten fehlschlägt,
wenn Sie den Namen
Ihres Hurt-Box-Knotens ändern oder die Struktur
Ihres Szenenbaums
neu anordnen , sodass er
kein direktes untergeordnetes Element mehr ist Ich bevorzuge diese Abhängigkeit
dem
Schreiben einer neuen Funktion im Charakterskript zum Abrufen
des Hurt-Box-Knotens , da dieses Skript
bereits ziemlich lang ist Zurück im Hurt Box-Skript schreiben
wir diese neue Funktion akzeptieren einen Symbolzähler als
Parameter der Typsteuerung, da wir ihr keinen
bestimmten Klassennamen gegeben haben. Jetzt haben wir die Hurt-Box und den Gesundheitszähler
im selben Skript, sodass wir problemlos zwischen ihnen
kommunizieren können. Noch wichtiger ist, dass das
Icon-Counter-Skript immer noch für
alles verwendet werden
kann, was wir wollen, und jede Hurt-Box in unserem Spiel die nicht durch einen Zähler
überwacht werden muss, kann
diese eine Funktion einfach ignorieren. Wir könnten die
Icon-Counter-Funktionen direkt aufrufen, aber das würde dazu führen, dass jede
Hurt-Box im Spiel ständig überprüft, ob sie über
einen Icon-Counter verfügt sie
überwacht, bevor sie diese Funktionen
aufruft Es wäre besser,
Signale zu verwenden , um
diese Änderungen zu kommunizieren,
eines für den Zeitpunkt, an dem sich die
maximale Gesundheit ändert und ein anderes, wenn sich die
aktuelle Gesundheit ändert Beide benötigen
Integer-Parameter für ihre neuen Werte. Möglicherweise möchten wir auch einen anderen für den Fall, dass der
Zustand Null erreicht
, für den
keine Parameter erforderlich sind. Wenn sich ihre aktuelle
Gesundheit nun ändert, weil entweder
Schaden erleiden oder ihre Gesundheit wiedererlangt
haben, können wir dieses Signal
aussenden, indem haben, können wir dieses Signal
aussenden wir ihre neue aktuelle
Gesundheit als Argument angeben. Wenn die aktuelle Gesundheit
nach dem erlittenen Schaden Null ist, sollten
wir das
eingefärbte Signal Zwei ausgeben Wenn wir nun einen Zähler
zur Überwachung dieser Hurt-Box einrichten, können
wir
diese Signale einfach mit den Sollwertfunktionen
der
Icon-Counter verbinden , da die von den Signalen
übergebenen Parameter sowohl
in der Menge als auch in der Art mit
den Parametern der
Icon-Counter-Funktionen übereinstimmen den Parametern der
Icon-Counter-Funktionen sowohl
in der Menge als auch in Es wäre auch eine gute
Idee, diese Signale
sofort auszugeben, damit der Symbolzähler seine Werte so einstellen
kann, dass sie
mit der Hurt-Box übereinstimmen. Um dies zu testen, können wir
eine einfache Eingabefunktion
in dieses Skript schreiben . Wenn ich die Taste nach oben drücke,
erhält der Charakter eine Gesundheit zurück. Wenn ich nach unten drücke, erleidet der Charakter
einen Schaden, und wenn ich springe, erhält der Charakter
seine volle Gesundheit zurück. du das Spiel
startest und nach unten drückst , erleidet
der Charakter bei jedem Tastendruck einen
Schaden. Schaden bei null
Lebenspunkten zu erleiden, wird ignoriert. Wenn Sie nach oben drücken, wird eine Gesundheit wiederhergestellt, und die Wiederherstellung von
Lebenspunkten bei Max wird ignoriert zuerst auf einen
niedrigeren Wert zurückgehe, springe
ich dann und stelle alle
Lebenspunkte wieder her Denken Sie daran, diese Eingabefunktion
nach dem Testen zu entfernen oder
auszukommentieren . Wir haben unseren Charakter jetzt in der Lage, Schaden
zu erleiden und seine Gesundheit
wiederherzustellen, aber seine Gesundheit wird
nicht gerettet. Wir sehen uns
im nächsten Video.
41. 5-6 Daten: Hallo Freunde. In diesem Video erstellen
wir eine benutzerdefinierte Ressource, mit der Sie
die Statistiken und
den Fortschritt des Spielers
zwischen
den Spielsitzungen verfolgen können Statistiken und
den Fortschritt des Spielers . Wenn wir möchten, dass der Spieler maximale Gesundheits-Upgrades verdienen kann , dann behält er diese Upgrades, wenn er
das nächste Mal spielt. Das Spiel muss wissen
, was sie im Spiel
gefunden haben und was nicht. Um das zu tun, können wir
unsere eigenen Ressourcen schaffen. Wir haben
in diesem Projekt bereits
mehrere Ressourcen verwendet , wie die
Atlas-Textur-Ressource für Charaktere
oder die
Animation-Tree-State-Machine-Ressource oder die
Animation-Tree-State-Machine-Ressource Und das Thema. Diese
Ressourcen sind alle Typen die von der
Godot-Game-Engine
definiert wurden, um spezifische Funktionen
für die Knoten
bereitzustellen, die sie verwenden. Aber wir können auch unsere
eigenen erstellen , um unseren eigenen
spezifischen Bedürfnissen gerecht zu werden. Lassen Sie uns einen neuen Ordner innerhalb
des Ordners mit dem Namen resources erstellen . Wir können dann in diesem Ordner ein neues
Skript mit dem Namen
data erstellen , anstatt
es vom Knoten
zu erben .
Dieses Skript erbt von Ressourcen werden im Szenenbaum nicht
als Knoten dargestellt. Das Erste, was wir beim Erstellen
einer benutzerdefinierten Ressource tun
möchten , ist
sicherzustellen, dass wir ihr einen Klassennamen geben. Andernfalls können
wir keine Instanzen davon erstellen. Da
der Zweck dieser Ressource besteht,
den Überblick über die Spielerdaten zu behalten, können
wir so viele
Variablen hinzufügen, wie wir
für alles benötigen , was wir
zwischen den Spielsitzungen speichern möchten. Vorerst benötige ich Variablen
für die Charaktere Max Health und Current
Health als Ganzzahlen Ich füge auch ihre
maximale Magie
und ihre aktuelle Magie als Floats All diese Variablen werden andere Skripte
öffentlich
zugänglich Wir können auch
Zeichenketten für Dinge wie ihren Namen oder boolesche Werte hinzufügen, um zu verfolgen, ob etwas ein- oder ausgeschaltet
ist Arrays können verwendet werden, um Gruppen
verwandter Informationen zu speichern, z. B. eine Reihe von
booleschen Werten, um zu wissen , welche Upgrades vom Spieler
gefunden wurden vom Spieler
gefunden Wörterbücher sind sehr nützlich, um ganze Informationsklassen
zu
speichern, da wir
Attributnamen als Schlüssel im Wörterbuch
mit
ihren entsprechenden Werten verwenden können Schlüssel im Wörterbuch
mit
ihren entsprechenden Werten ganze Informationsklassen
zu
speichern,
da wir
Attributnamen als Schlüssel im Wörterbuch
mit
ihren entsprechenden Werten verwenden können. Neben den grundlegenden Variablentypen können
wir auch
andere in
Godot integrierte Klassen wie Vektoren zum
Speichern von zwei D-Koordinaten,
Farben oder sogar anderen benutzerdefinierten
Klassen, die wir erstellen, einbeziehen Godot integrierte Klassen wie Vektoren zum
Speichern von zwei D-Koordinaten, Farben oder sogar anderen benutzerdefinierten
Klassen, die wir erstellen, Jede Variable, die Sie zwischen den
Spielsitzungen speichern
möchten , muss das Export-Tag haben Andere Variablen
, die nicht über
das Export-Tag verfügen , können dennoch nützlich
sein, wenn
du zum Beispiel nicht die aktuelle Gesundheit des
Charakters speichern möchtest, sondern nur seine maximale Gesundheit
und der Spieler
jedes
Mal, wenn er sein Spiel lädt, mit voller Gesundheit starten möchtest. Diese nicht exportierten
Variablen bleiben jedoch erhalten wenn dein Spiel während der
Spielsitzung die
Szene wechselt ,
wenn dein Spiel während der
Spielsitzung die
Szene wechselt. Wenn Sie
aus
irgendeinem Grund die Spielszene verlassen, um
eine Zwischensequenz abzuspielen, dann wieder zur
Spielszene zurückkehren, behalten
diese Variablen ihren Wert. Wir können zwar auch Funktionen
in dieses Skript schreiben, aber das
ist normalerweise nicht notwendig. Wenn Sie eine
automatisierte Initialisierung
Ihrer Ressource durchführen möchten , können
wir
die Init-Funktion überschreiben Diese Innit-Funktion wird automatisch von Godot
aufgerufen wenn wir über ein Skript eine neue Instanz
dieser Ressource
erstellen dieser Ressource So können wir den Variablen
einige Standardwerte geben, die Längen von Arrays
festlegen
oder unseren Wörterbüchern einige Schlüssel hinzufügen Stellen Sie sicher, dass Sie dieses Skript mit
dem definierten Klassennamen speichern dem definierten Klassennamen bevor Sie versuchen, es in irgendeiner
Weise zu verwenden Godot wird
diesen Klassennamen also erkennen. Wir benötigen ein weiteres Skript , um auf unsere benutzerdefinierte Ressource zuzugreifen, die wir
im nächsten Video behandeln werden Vorerst können wir
unsere benutzerdefinierte Ressource testen, indem wir eine auf
der Registerkarte Dateisystem erstellen. Wir klicken, wählen Neue Ressource
erstellen aus und geben
dann den Klassennamen ein oder
wählen ihn aus der Liste aus. Dann gib ihr einen Namen.
Wenn wir diese Ressource erstellen, öffnen wir sie automatisch
im Inspektor, wo wir alle
unsere exportierten Variablen sehen und bearbeiten können. Beim Erstellen einer Ressource auf diese Weise nicht die Funktion nit verwendet,
sondern es werden Werte verwendet, die für
Variablen bereitgestellt werden, die in
ihren Deklarationen zugewiesen wurden. Wenn Sie etwas anderes auswählen und zur
Bearbeitung dieser Ressource zurückkehren möchten, können
Sie auf der Registerkarte Dateisystem darauf
doppelklicken. Ich werde schnell testen, wie
eine Datenressource im
Game Manager-Skript erstellt wird. Wir können eine
Instanz unserer Ressource erstellen indem wir zuerst eine Variable
mit dem Klassennamen als Typ deklarieren mit dem Klassennamen als Typ Weisen Sie dann den Wert
dieser Variablen dem Klassennamen
zu ,
gefolgt vom Punkt Nu Wir können dann auf alle Variablen zugreifen ,
die wir in dieser Klasse
deklariert haben, sowohl exportiert als auch nicht exportiert, ihre Werte
überschreiben und sie
beim Spielen nach Bedarf
verwenden Denken Sie daran,
diesen Testcode zu entfernen
oder auszukommentieren und
die Testdatenressourcendatei zu löschen Wir haben jetzt eine Datenressource, die die maximale
Gesundheit und die aktuelle Gesundheit unserer Charaktere
enthält, aber sie wird noch nicht gespeichert. Wir sehen uns im nächsten Video.
42. 5-7-Datei: Hallo Freunde. In diesem Video speichern und laden
wir die Spielerdaten mithilfe
unserer neuen benutzerdefinierten Ressource. Dazu benötigen wir
ein weiteres Skript, das den
Zugriff auf die Ressource verwaltet , die wir im vorherigen Video
erstellt haben. Auf dieses Skript muss von überall
im Projekt aus
zugegriffen werden können. Der Charakter
muss seine Statistiken kennen. Die Räume müssen wissen, ob
der Spieler eine Tür geöffnet, ein Upgrade
gefunden oder einen Boss
besiegt hat . Sogar die Benutzeroberfläche und die Karte benötigen Zugriff
auf die Speicherdaten. Wir können einige Knoten auf diese Weise leicht zugänglich machen,
indem wir sie global machen. Lassen Sie uns im Skriptordner einen neuen Ordner
mit
dem Namen Globals erstellen Skriptordner einen neuen Ordner
mit
dem Namen Globals Erstellen Sie dann
in diesem Ordner ein neues Skript mit dem Namen file. Der Zweck dieses
Skripts besteht darin, schnellen und einfachen Zugriff auf den Spielern
schnellen und einfachen Zugriff auf die Speicherdaten
aller anderen Skripte zu ermöglichen, die wir
im gesamten Projekt schreiben, sowie sie auf dem System
des Spielers zu speichern und auch zu laden. Wir benötigen eine Variable vom
Typ unserer benutzerdefinierten Ressource. Ich nenne sie Daten
mit einem kleinen
D. Wir benötigen dann drei öffentliche Funktionen, um diese Daten
zu verwalten, ein neues Spiel zu
starten, das Spiel zu
speichern
und das Spiel zu laden Ein neues Spiel zu starten ist einfach. Wir müssen nur
den Wert der Daten auf
unseren Klassennamen setzen ,
gefolgt von einem Punkt neu. Dadurch wird eine neue Instanz
der Ressource erstellt und initialisiert Wenn wir bereit sind, unser Spiel
zu speichern, müssen
wir auch wissen, wo
wir es speichern möchten Dafür deklariere ich
eine String-Konstante, da ich
das nie ändern werde, den Pfad zu dem Ort, an dem ich die Datendatei des
Spielers speichern möchte. Godot bietet eine
einfache Abkürzung
, die auf jeder Plattform funktioniert Windows, Mac, Linux, Web und Konsolen können dies alle verwenden Der Benutzer Colon leitet einen Schrägstrich weiter
. Do ersetzt
dies automatisch durch den
entsprechenden Pfad für Plattform als
Speicherort,
der sowohl für den Benutzer
des Systems als auch für das Spiel
spezifisch ist sowohl für den Benutzer
des Systems als auch für das Spiel
spezifisch Wenn ich eine Variable für den
Dateinamen auch als Zeichenfolge deklariere, nenne ich meine Datei save, gefolgt von Punkt TRS, der Abkürzung für Text Resource Um das Spiel zu speichern, können
wir auf eine
Singleton-Klasse des Godot zugreifen,
Resource Saver, die dann
als Speicherfunktion bezeichnet wird Übergeben Sie die Ressource, die
wir speichern möchten, und den Speicherort, an dem wir sie speichern möchten, indem Sie
den Pfad und den
Dateinamen anhängen Wenn wir
mehrere Speicherplätze haben möchten, müssen wir nur
den Dateinamen für jeden Slot ändern Das Laden unseres Spiels
ähnelt dem Speichern. Alles was wir tun müssen, ist
Godot Loader Singleton zu verwenden. Die Ladefunktion
benötigt nur den Standort der
Ressource, die wir Und sie gibt die Ressource zurück. Also weisen wir es
unserer Datenvariablen zu. Da unser Spiel
keine Titelszene hat, gehe
ich einfach automatisch davon aus ,
dass
ich eine Speicherdatei laden möchte, falls sie existiert , oder wenn
sie kein neues Spiel startet. In der REDI-Funktion verwende
ich also den Resource Loader, um zu überprüfen, ob eine
Datendatei zum Laden vorhanden ist, und wenn ja, lade ich sie Andernfalls starte ein neues Spiel. Selbst bei einer Titelszene ist
es hilfreich, dein Spiel direkt
von der Spielszene aus starten zu können dein Spiel direkt
von der Spielszene aus ohne
jedes Mal den
Titelbildschirm aufrufen zu müssen , während du
entwickelst und testest. Wir haben unsere Datenressource hier. Wir können sie erstellen,
speichern und laden. Jetzt müssen wir nur noch dafür sorgen,
dass dieses Skript von
überall in unserem Projekt aus
leicht zugänglich ist. Öffnen Sie die Projekteinstellungen und wechseln Sie zur Registerkarte Globals Klicken Sie auf die Ordnerschaltfläche
, um einen Browser zu öffnen und zu dem Dateiskript zu
navigieren, das wir gerade erstellt haben. Klicken Sie dann auf Öffnen. Wir können einen
anderen Namen für
diesen globalen Knoten angeben , wenn wir möchten,
oder den angegebenen verwenden. Klicken Sie dann auf
Hinzufügen, um das Skript zur
Liste der globalen Knoten hinzuzufügen. Jetzt kann jedes Skript, das wir schreiben nur
mit seinem Namen
auf dieses Dateiskript zugreifen. Ähnlich wie wir die Singletons Input,
Resource Saver und Resource
Loader verwendet
haben Singletons Input,
Resource Saver und Resource
Loader Um das zu testen, stelle ich die maximale
Gesundheit des Charakters so ein, dass sie dem entspricht, was
im Safle steht , anstatt sie
ganz oben im Skript zu platzieren Also füge ich
diesem Skript eine
initialisierte Funktion hinzu, nachdem ich
einen neuen Maximalwertparameter akzeptiert den alten Maximalwert
auf den neuen Maximalwert
setze Dann setze ich den aktuellen Wert
auf den Maximalwert und gebe beide geänderten Signale Jetzt
kann der Spielmanager,
nachdem er
die Hurt-Box des Charakters erhalten die Hurt-Box des Charakters hat, sie mit
dem maximalen Gesundheitswert
aus der Datendatei des Spielers initialisieren dem maximalen Gesundheitswert
aus der Datendatei des Spielers Ich werde auch eine Eingabefunktion hinzufügen, die beim Drücken der
Aufwärts- oder Abwärtspfeiltasten erhöht oder verringert maximale Gesundheit
des Charakters in der Datendatei erhöht oder verringert und die Hurt-Box entsprechend
neu initialisiert Speichere dann das Spiel, indem du file dot save game
aufrufst. Ich muss
die Reihenfolge
dieser Operationen umkehren , um
die richtigen Werte anzuzeigen. Beim Ausführen des Spiels
beginnt der Charakter mit fünf maximalen Lebenspunkten, aber ich kann diesen Wert ändern,
indem ich die
Aufwärts- oder Abwärtspfeiltasten drücke. Ich schließe dann das
Spiel und starte es erneut, um zu überprüfen, ob
seine maximale Gesundheit gespeichert und geladen
wurde. Um die Datendatei, die wir
gespeichert haben, im Projektmenü zu finden, wähle Benutzerdatenordner öffnen. Dadurch wird ein
Dateibrowserfenster geöffnet, und wir können unsere dotTRS-Datei zum
Speichern sehen Klicken Sie mit der rechten Maustaste auf diese Datei und öffnen Sie sie mit einem beliebigen Texteditor Wir können sehen, dass nur die
maximale Gesundheit gespeichert wurde. Godot verfolgt, welche
Variablen vom Spiel verwendet werden und speichert nur die Variablen, die wir
tatsächlich verwenden und ändern Behalte das also im Hinterkopf. Wir können diese Datei hier
tatsächlich bearbeiten, und das Spiel lädt sie
tatsächlich mit den bearbeiteten Werten,
solange die Formatierung übereinstimmt. Das ist großartig für uns, während wir unser Spiel entwickeln und
testen. Aber vielleicht möchtest du es deinen Spielern nicht
einfach ermöglichen, ihre sichere Datei
zu bearbeiten,
wenn du bereit bist, sie zu veröffentlichen. Ändern
Sie im Dateiskript einfach die TRS-Erweiterung im
Dateinamen in den Punkt RES. Anstatt als Textressource wird
diese nun
als binäre Ressource gespeichert,
die nicht in einem Texteditor geöffnet und
bearbeitet werden kann. Wenn ich das Spiel erneut starte,
öffne ich die
Datei mit den Speicherpunkten, die ich gerade erstellt habe. Es ist
für mich jetzt unmöglich, das zu bearbeiten. Wir haben jetzt die
Möglichkeit,
Daten über den
Fortschritt des Spielers in unserem Spiel zu speichern und zu laden . Im nächsten Abschnitt werden
wir unsere
freischaltbaren Fähigkeiten hinzufügen Wir sehen uns im nächsten
Abschnitt.
43. 6-1 Doppelsprung: Hallo Freunde. In diesem Video geben
wir unserem Charakter
die Fähigkeit, doppelt zu springen. Während viele Charaktere
in unserem Spiel möglicherweise
die Fähigkeit benötigen , zu gehen, zu rennen, zu springen und zu fallen,
sind die
freischaltbaren Fähigkeiten normalerweise nur
dem Spielercharakter vorbehalten Im
Charakterskript können
wir, anstatt diesem Skript,
das schon ziemlich lang ist, weitere Variablen und
Funktionen
hinzuzufügen , diesem Skript,
das schon ziemlich lang ist, weitere Variablen und
Funktionen
hinzuzufügen, ein neues Skript erstellen, das nur vom
Spielercharakter verwendet
wird Vergewissere dich, dass dein
Charakterskript
einen Klassennamen hat und
gespeichert ist, bevor du fortfährst. der Charakterszene Klicke in der Charakterszene mit der
rechten Maustaste auf den Stammknoten des
Charakters und wähle Skript anhängen. Anstatt
von CharacterBody zwei D zu erben, können
wir vom Klassennamen
unseres ursprünglichen
Skriptcharakters erben, können
wir vom Klassennamen
unseres ursprünglichen
Skriptcharakters unseres ursprünglichen Geben Sie diesem neuen Skript dann einen Namen und speichern Sie es
im entsprechenden Ordner Da dieses neue Skript von Character
erbt, hat
es Zugriff auf dieselben Variablen und Funktionen , die wir für diese Klasse erstellt haben, und alle Werte für
die exportierten Variablen und Signalverbindungen werden ebenfalls dieses neue Skript
kopiert Aber wir können jetzt weitere hinzufügen, die nur für
den Spielercharakter nützlich
sind Nach diesem
Vererbungsmuster wird
der
Charakter als Superklasse bezeichnet und unser Spielercharakter
ist eine Unterklasse Zunächst benötigen wir eine Variable, die uns sagt
, ob
dieser Charakter die Fähigkeit zum Doppelsprung freigeschaltet
hat oder nicht dieser Charakter die Fähigkeit zum Doppelsprung freigeschaltet
hat Und um
den Charakter darauf zu beschränken , nur einmal
doppelt zu springen, benötigen
wir eine weitere Variable, um zu wissen, ob sein
Doppelsprung bereit ist. Es könnte auch hilfreich sein,
ein Signal zu haben, das ausgegeben wird, wenn wir erfolgreich
einen Doppelsprung ausgeführt um einen
Partikeleffekt zu erzeugen, wenn Sie möchten, genau wie wir es
beim anderen Sprung getan haben. Da beim Doppelspringen normalerweise dieselbe Taste
wie beim normalen Springen
verwendet wird, müssen
wir keine zusätzliche
Arbeit mit der Eingabemap in den Projekteinstellungen vornehmen oder
das Player-Skript bearbeiten , um neue Funktionen
aufzurufen. Wir können die
Jump-Funktionsdeklaration einfach überschreiben. Beim Überschreiben einer
Funktionsdeklaration muss
die Funktionssignatur gleich bleiben Der Name der Funktion,
ihre Parameter, Menge, Reihenfolge und Typen sowie der Rückgabetyp Da die ursprüngliche
Sprungfunktion
im Zeichenskript
keine Parameter akzeptierte und einen booleschen Wert
zurückgab, darf
diese Sprungüberschreibung auch keine Parameter
haben
und einen booleschen Wert zurückgeben Wir wollen immer noch, dass die gesamte ursprüngliche
Funktionalität
des Sprungs zur Verfügung steht Dieser Charakter
kann also
springen, wenn die richtigen
Bedingungen erfüllt sind. Wir können
mit dem Schlüsselwort super auf die Funktionen der
Superklasse zugreifen und
dann einen Punkt,
den Funktionsnamen und
Klammern verwenden , genau wie wir eine
Funktion auf jede andere Weise aufrufen
würden Da die
Sprungfunktion der Superklasse einen booleschen Wert zurückgibt, können
wir auch das Ergebnis zurückgeben, um die Anforderung zu erfüllen Wenn der Spieler die Sprungtaste drückt, ruft
das Spielerskript diese Funktion zum Sprung des Spielercharakters auf,
die dann die allgemeinere Funktion zum
Sprung von Charakteren
aufruft diese Funktion zum Sprung des Spielercharakters auf,
die dann die allgemeinere Funktion zum
Sprung von Charakteren
aufruft. Diese Struktur ermöglicht es
uns,
den Vorgang abzufangen , indem wir zusätzlichen
Code über der Rücklaufzeile hinzufügen, sodass wir überprüfen
können, ob
dieser Spielercharakter als Antwort auf die Aufforderung, zuerst
zu springen, doppelt springen kann, danach nur mit
dem
Standard-Sprungverhalten fortfahren dem
Standard-Sprungverhalten Wenn dieser Spielercharakter also einen Doppelsprung machen
kann und der Doppelsprung bereit ist und sich der Charakter
nicht auf dem Boden befindet, dann sollten wir
ihm erlauben,
einen Doppelsprung auszuführen und „Wahr“ zurückgeben Wenn eine dieser
Bedingungen falsch ist, müssen wir mit der Sprungfunktion kann normalen Bedingungen der
Charakter-Superklasse
prüfen, ob dieser Charakter unter
normalen Bedingungen
springen Wir können so ziemlich einfach die Codezeilen
kopieren , die bei einem Doppelsprung einen
Sprung implementieren, aber ein anderes Signal ausgeben Und wir müssen
die Variable Doppelsprung ist
bereit auf
Stürze setzen , um zu verhindern, dass der
Spielercharakter mehr
als einen Doppelsprung ausführt. In den meisten Spielen mit
einem Doppelsprung
wird
die Fähigkeit, den Doppelsprung auszuführen , nach der
Landung auf dem Boden wiederhergestellt. Da die
Charakterklasse bereits über
eine Funktion verfügt , die aufgerufen wird,
wenn der Charakter landet, können
wir diese Funktion auch überschreiben. Jedes Mal,
wenn dieser Charakter landet und sein
Doppelsprung noch nicht bereit ist, können
wir die Variable wieder
auf true setzen, um sie bereit zu machen. Rufen Sie dann die
Superklassenfunktion auf. In diesem Fall spielt die Reihenfolge
, ob wir
die Superklassenfunktion davor
oder danach ausführen möchten , keine Rolle Um das zu testen, füge ich eine Print-Anweisung hinzu,
wenn der
Doppelsprung des Zeichens erfolgreich ist. Und noch eine, wenn der
Doppelsprung wiederhergestellt ist. Setzen Sie dann den Standardwert
von C double jump auf true. Wenn wir das Spiel starten, können wir die Sprungtaste
drücken, um
doppelt zu springen. Wenn Sie die Taste
dreimal oder öfter drücken, werden keine Sprünge mehr
erzeugt, und die Fähigkeit zum Doppelsprung
wird bei der Landung wiederhergestellt Jetzt müssen wir nur noch diese Fähigkeit
zum Doppelsprung sperren und freischalten Also setze ich den Standardwert von C double jump wieder auf False. In den Speicherdaten des Players entferne
ich all diese
unnötigen Variablen. Wir benötigen Variablen,
die uns sagen , welche Fähigkeiten der
Spieler freigeschaltet hat, die wir in
einer Reihe von Booleschen Werten speichern können Arrays werden
mit Ganzzahlen indexiert Jeder unserer Fähigkeiten muss nacheinander eine
Zahl
zugewiesen werden,
beginnend bei Null, bis sie als ihre
Indizes für dieses Array dienen Wenn Sie sich nicht viele ganze Zahlen merken möchten, können
wir
eine
Aufzählung erstellen, um
jeder Ganzzahl einen Namen zu geben, der für uns einfacher zu verwenden
ist Ich füge diese
Aufzählungen gerne in ein separates Skript mit dem Namen enums ein Während Godot uns zwingt,
bei der Erstellung des Skripts
von einer vorhandenen Klasse zu erben , können
wir diese Zeile nach der Erstellung aus
unserem Skript entfernen unserem Skript Geben Sie diesem Skript dann
einen Klassennamen, damit wir
in anderen Skripten darauf verweisen können Normalerweise verwende ich
dasselbe Skript, um jede Aufzählung
für das gesamte Projekt zu speichern Wir können eine
Aufzählung mit
dem Schlüsselwort num,
gefolgt von geschweiften Klammern, deklarieren dem Schlüsselwort num,
gefolgt von geschweiften Klammern, Innerhalb der geschweiften Klammern
können wir die Namen
jeder unserer Fähigkeiten in
eine durch Kommas getrennte Liste schreiben jeder unserer Fähigkeiten in
eine durch Kommas Ich habe bereits
einen Doppelsprung
als meine erste freischaltbare Fähigkeit erstellt ,
und ich werde einen Wall Jump, einen
Dash, einen Hut und
das Abfeuern eines Projektils erstellen Dash, einen Hut und
das Abfeuern eines Projektils Aufzählungen werden
üblicherweise in
Pascal-Groß- und Kleinschreibung benannt, während die
Aufzählungseinträge in Schlangengroßbuchstaben geschrieben werden. Die Aufzählung
weist dem ersten Eintrag
den Wert Null, dann
Eins,
Zwei usw. zu, was bedeutet, dass wir
diese ganz einfach als Indizes für unser Array verwenden können diese ganz einfach als Indizes Diese
müssen nicht in der Reihenfolge sein,
in der sie vom Spieler
freigeschaltet werden Die Reihenfolge ist willkürlich und
dient nur dazu, jeder
Fähigkeit eine eindeutige Nummer zuzuweisen. Bei der Initialisierung der Speicherdaten des
Spielers können
wir die Größe des Arrays an die Größe der Aufzählung
anpassen. Dadurch erhalten wir
automatisch
die richtige Anzahl von Booleschen Werten und setzen sie standardmäßig Denken Sie daran, dass
Variablen das Export-Tag haben
müssen , um gespeichert zu werden. Zurück im Player-Skript können
wir auf das Array mit den freigeschalteten
Fähigkeiten verweisen und es mit
dem Tag on ready in einer Variablen mit
demselben Namen
speichern . Beachten Sie, dass
dadurch nicht nur eine Kopie des Arrays
in seinem aktuellen Zustand erstellt wird. Dadurch wird ein Verweis
auf das Array erstellt, sodass sich alle Änderungen auf beide auswirken. Das bedeutet, dass
wir, um eine Fähigkeit für
den Charakter
freizuschalten, eine Fähigkeit für
den Charakter
freizuschalten, nur ihren Wert
in der Speicherdatenressource angeben müssen. Wir können jetzt die
C-Doppelsprung-Variable ersetzen , indem wir das Array mit
den freigeschalteten Fähigkeiten
mit dem Punkt Enums
Dot Double Jump indexieren Array mit
den freigeschalteten Fähigkeiten mit dem Punkt Enums
Dot Double Dieses
Array mit freigeschalteten Fähigkeiten kann jetzt
im gesamten
Skript für jede Fähigkeit verwendet werden im gesamten
Skript für jede Im Game Manager-Skript verwende
ich die
Eingabefunktion, um zu testen, ob die Doppelsprungfähigkeit freigeschaltet wenn ich die Aufwärtspfeiltaste drücke Einstellung von Dateipunktdaten,
Punktfähigkeiten freigeschaltet, Indexpunkt-Aufzählungen, Punkt-Fähigkeiten
Punkt Double Jump auf True Wir können das Spiel dann speichern
, um es dauerhaft zu machen. Beim Ausführen des Spiels kann mein
Charakter nicht doppelt springen. Zurück im Godot-Editor wechsle
ich zum
Remote-Tab, um mir
den Szenenbaum des Spiels anzusehen , das gerade läuft Hier sehe ich den globalen
Dateiknoten
, der über eine Datenressource verfügt Innerhalb dieser Datenressource enthält das Array mit
den freigeschalteten Fähigkeiten fünf Boolesche Werte, die alle
falsch sind Der Spielercharakterknoten enthält
auch einen Verweis
auf dasselbe Array Sie zur Simulation zurückkehren und nach oben
drücken, wird die
Doppelsprungfähigkeit freigeschaltet Im Remote-Szenenbaum kann
ich sehen, dass der boolesche Wert
im Array sowohl in der
Datenressource als auch in der Figur auf
true gesetzt wurde sowohl in der
Datenressource als auch in der Figur auf
true Schließe das Spiel und starte
es erneut. Der Doppelsprung ist seit dem Speichern bereits
freigeschaltet. Wir können die
Druckanweisungen jetzt entfernen, da
bestätigt wurde, dass der Doppelsprung funktioniert. Wir haben jetzt eine freischaltbare
Doppelsprungfähigkeit, aber wir müssen noch einige weitere
freischaltbare Wir sehen uns im nächsten Video.
44. 6-2 Wandfolie: Hallo Freunde. In diesem Video lassen
wir den Charakter
eine Wand hinunterrutschen, wodurch Reibung entsteht
, um den Abstieg zu
verlangsamen. Zunächst müssen wir entscheiden, was diese Fähigkeit bewirken soll und
wann sie eingesetzt werden soll. Wenn Sie eine
neue Funktion wie diese implementieren, ist
es eine gute Idee, zuerst
Tests einzurichten , die Sie bestehen
möchten. Ich fange mit der
Rauminhaltsszene und verstecke die Bäume,
damit ich besser sehen kann. Um eine Mechanik zum
Verschieben von Wänden zu erstellen, erstelle
ich zwei
Wände in meinem Zimmer Ich betrachte meine
Mechanik als abgeschlossen
, wenn der
Charakter springen und
dann mit reduzierter Fallgeschwindigkeit eine der beiden Wände
hinunterrutschen kann dann mit reduzierter Fallgeschwindigkeit eine der beiden Wände
hinunterrutschen Ich würde auch gerne
eine andere Animation abspielen ,
während das passiert Die Wandrutsche sollte enden, wenn die Figur keinen Kontakt
mehr mit der Wand hat, wenn sie den Boden
berührt oder wir die Bewegungsrichtung
drücken, um die Figur von der Wand
wegzubewegen. wir das umsetzen, wird also Luftphysik des Charakters
verändert Im Spielercharakter-Skript überschreiben
wir den Prozess der
Luftphysik des Charakters Rufen Sie dann den
Air Physics-Prozess der Superklasse aus dem Charakterskript Hier können wir unseren Code
in drei separate Blöcke unterteilen. Wenn der Charakter eine Wall Slide
ausführt,
prüft er, wann er mit der
Ausführung einer Wall Slide beginnen kann, und jedes andere Mal rufen wir den
Superclass-Airphysics-Prozess Wir müssen wissen,
wann die Figur
gerade eine Wall Slide ausführt, also sollten wir das
als boolesche Variable deklarieren Es wäre auch hilfreich, ein Float zu
exportieren, um es als
Multiplikator für die Schwerkraft des
Charakters zu verwenden Multiplikator für die Schwerkraft des
Charakters zu während wir eine Wall Slide ausführen Ich werde 10% verwenden. Zurück zum Prozess der
Luftphysik:
Wir können nun
anhand dessen verzweigen, ob die
Variable Is Wall Sliding wahr oder falsch ist oder
nicht. Wenn der Charakter
bereits durch die Wand rutscht, können
wir entweder
den Vorgang fortsetzen oder beenden, je nachdem, ob
andere Bedingungen erfüllt sind. Wenn der Charakter
nicht durch die Wand rutscht, müssen wir prüfen,
ob er die Wand rutschen kann, und wenn die Bedingungen erfüllt sind, um
mit dem Wandrutschen zu beginnen, dann tun wir das. Und zu guter Letzt, wenn all
das falsch ist, dann sollten wir mit der
Oberklasse Air Physics
als Standard weitermachen Oberklasse Air Physics
als Standard weitermachen Wenn Sie Ihren Algorithmus
in Pseudocode-Kommentaren wie diesem
aufschreiben in Pseudocode-Kommentaren wie diesem ist es viel einfacher, ihn
danach auszufüllen und bei Bedarf neu anzuordnen Außerdem wird das
Endergebnis bereits kommentiert. Beginnen wir mit dem
Starten einer Wall Slide indem wir überprüfen, ob die
Fähigkeit Wall Jump freigeschaltet wurde. Füge dann auch die Bedingung , dass sich dieser Charakter an einer Wand befinden
muss. Die
Körperklasse des Charakters bietet diese Funktion,
die sich genauso verhält wie auf dem Boden. Ich möchte auch
weitere Bedingungen hinzufügen, dass ihre Y-Geschwindigkeit
größer oder gleich Null sein muss. Ich möchte nicht, dass der Charakter
anfängt, die Wand zu rutschen,
wenn er sich nach oben bewegt, und der Spieler muss
die
eingegebene Bewegungsrichtung in Richtung Wand drücken . Der Körper des Charakters mit zwei Bezeichnungen gibt uns noch eine weitere Funktion Mach Wall normal. Dies gibt einen Vektor zurück, der von der Wand weg
zeigt. Wenn wir also den
X-Teil dieses Vektors verwenden, dieser immer negativ
, wenn sich die Wand rechts
der Figur befindet ,
oder positiv wenn sich die Wand links von der
Figur befindet. Wenn ich das mit der Bewegungsrichtung des
Charakters vergleiche, multipliziere
ich beide
Seiten mit minus eins und setze voraus, dass
die Ergebnisse gleich sind. Dadurch kann die
Bewegungsrichtung nicht Null sein. Diese I-Anweisung enthält mehrere Bedingungen
, und sie passen nicht
in mein Skriptfenster. Wenn Sie die Bedingungen Ihrer
if-Anweisung
über mehrere Zeilen schreiben möchten , können
Sie
sie in Klammern setzen. Dies kann das
Lesen und Debuggen Ihres
Codes erleichtern , wenn Sie dieses Format
bevorzugen Meine Wände sind zwar
perfekt vertikal, verwenden wenn
Ihre Wände abgewinkelt sind, müssen
Sie möglicherweise
den Sinus der Wände als Normalwert X Wenn all dies zutrifft, erlaube
ich der
Figur,
eine Wandrutsche zu starten , indem
ich I Wall Sliding auf True setze und ihre Y-Geschwindigkeit
mithilfe der Min-Funktion auf Null begrenze Dadurch wird die
Fallgeschwindigkeit kurzzeitig zurückgesetzt , sodass sich
die Wandrutsche langsamer anfühlt Ich werde auch eine Erklärung zu
Testzwecken ausdrucken. Jetzt gehen wir davon aus
, dass der Charakter bereits
einen Wandrutsch ausführt, und wir wollen
seine Schwerkraft außer Kraft setzen , um seinen Abstieg zu
verlangsamen. Dazu addieren wir einfach die Y-Geschwindigkeit des
Charakters, Schwerkraft mal Delta mal den
Schwerkraftmultiplikator Wall Slide
, den ich auf
10% der normalen Schwerkraft gesetzt habe Aus physikalischer Sicht ist das
so,
als würde man sagen, dass
zwischen
der Figur und
der Wand ein Reibungskoeffizient von 0,9 Und zuletzt können wir darüber nachdenken,
wann wir die Wall Slide beenden sollen. Wenn sich der Charakter
nicht mehr an der Wand befindet oder wenn der Spieler die entgegengesetzte
Bewegungsrichtung
von der Wand weg
drückt . Wenn also nicht an der
Wand ist oder wenn das Zeichen der Bewegungsrichtung mit den
Wandnormalen X
übereinstimmt, setze ich Ist die Wand gleitet auf falsch und drucke
eine Erklärung aus , dass die
Wandrutsche beendet wurde Es wäre einfacher
, die Wandfolie als den anderen
Block zu dieser I-Anweisung
weiterführen zu lassen , also schneide ich sie aus und füge sie hier Es gibt noch eine weitere Bedingung
, die besagt, dass
eine Wandrutsche beendet werden muss , wenn die
Figur den Boden berührt. Da wir bereits
eine Funktion haben, die
automatisch aufgerufen wird , wenn
der Charakter landet, füge
ich hier einfach eine weitere
I-Anweisung hinzu, die die Wall Slide
beendet. Wenn es sich bei der Figur um Wall Sliding
handelt, setze I Wall Sliding auf False und drucke
dann
eine weitere Anweisung aus. Es ist hilfreich, wenn diese beiden
Aussagen unterschiedlich sind, damit wir während unserer Tests sehen
können
, wann sie tatsächlich vorkommen. Dies funktioniert für die Tastatur, aber nicht für einen Controller, da die Bewegungsrichtung ein Dezimalwert
sein kann. Also muss ich
die Zeichenfunktion auf diese
beiden Prüfungen anwenden, um
mit der Controller-Eingabe zu arbeiten. Als letztes
muss ich dem Animations-Player des
Charakters
eine Wall
Slide-Animation hinzufügen eine Wall
Slide-Animation . Also werde ich
ihre Laufanimation duplizieren. Ändern Sie die Y-Position des Bereichs
der
Tabelle, der gerade
verwendet wird, und löschen Sie die
Schrittspur Diese Animation wird
der State-Machine-Ressource hinzugefügt. Ich lasse zu, dass der Charakter vom Springen
oder Fallen in diesen Zustand
übergeht , wenn I
Wall Sliding auf true gesetzt ist. Wall Sliding“ auf „
Stürzen“ gesetzt ist, dann
von einer
Wandrutsche in einen Sturzmodus übergehen Wenn „I Wall Sliding“ auf „
Stürzen“ gesetzt ist, dann
von einer
Wandrutsche in einen Sturzmodus übergehen. Oder zur Fortbewegung, wenn
sie den Boden berühren. Im Game Manager-Skript ändere ich das Freischalten
des Doppelsprungs in das Entsperren des Wall Jump Entsperren des Das sollte
ausreichen, um
meinen Test zu bestehen , also führe ich das Spiel aus Der Charakter kann
immer noch normal springen, und wenn er gegen die
Wand springt, rutscht die Wand nicht , da die
Fähigkeit immer noch gesperrt ist. Aber wenn ich nach oben drücke, um den Wandsprung
freizuschalten Wenn ich
jetzt springe, während ich mich zur Wand
bewege, rutschen
sie die Wand hinunter und hören auf,
wenn sie den Boden berühren. das an der anderen Wand versuchen, endet
die Rutsche, wenn sie den
Boden der Wand erreichen. Und bei einem weiteren Versuch gegen
die erste Wand startet
die Wandrutsche erst, die Wandrutsche erst wenn die Figur zu fallen
beginnt,
und ich kann die Wandrutsche
vorzeitig beenden, indem ich mich von der Wand
entferne und ich kann die Wandrutsche
vorzeitig beenden . Das normale
Sprungverhalten des Charakters wird durch die Ausführung
einer dieser Aktionen
nicht beeinträchtigt. , die Druckaussagen
auszukommentieren, nachdem alle Tests bestanden Denken Sie daran, die Druckaussagen
auszukommentieren, nachdem alle Tests bestanden wurden. Wir haben jetzt unseren Charakter
in der Lage, einen Wall Slide auszuführen, aber wir müssen noch den Wall Jump
implementieren. Wir sehen uns im nächsten Video.
45. 6-3 Wandsprung: Hallo Freunde. In diesem Video lassen
wir den
Charakter
von der Wand wegspringen , während er eine Wandrutsche
ausführt. Im Zeichenskript haben
wir die Sprungfunktion bereits überschrieben
,
um einen Doppelsprung auszuführen Wenn wir wollen, dass der
Charakter von der Wand springt, können
all diese Bedingungen auch
beim Doppelsprung erfüllt sein Wir müssen also zuerst
den Mauersprung
als Möglichkeit in Betracht ziehen und ihn ausschließen bevor wir nach
dem Doppelsprung suchen, da die Bedingungen für den
Mauersprung spezifischer sind. Wir müssen nur überprüfen, ob die Fähigkeit Wall Jump
freigeschaltet wurde und ob
der Charakter gerade
einen Wall Slide ausführt. Wenn diese Bedingungen nicht erfüllt sind, können wir überprüfen,
ob der Charakter stattdessen doppelt springen
kann. Dadurch
kann der Charakter jedoch erst dann einen Wandsprung
ausführen, wenn
die Wall Slide gestartet wurde. Diese wartet
, bis
der Charakter den Scheitelpunkt seines Sprungs
erreicht hat den Scheitelpunkt seines Sprungs
erreicht Wenn du vor dem Start
der Wall Slide
Wandspringen zulassen möchtest , wenn die
Y-Geschwindigkeit des Charakters negativ ist, können wir auch
weitere Bedingungen hinzufügen Entweder führen die Figuren eine Wandrutsche durch oder sie befinden sich nicht auf dem Boden
, sondern an einer Wand, und die Bewegungsrichtung
ist zur Wand gerichtet. Bei der Reihenfolge der logischen
Operationen müssen
wir das
oder in Klammern setzen damit es
vor dem ersten und geprüft wird. Wir können mehrere
Ebenen von Klammern
und Einrückungen verwenden , um
die Reihenfolge
der Operationen einer komplexen Logik
wie dieser
visuell darzustellen um
die Reihenfolge
der Operationen einer komplexen Logik , damit sie bei Bedarf leichter
zu verstehen Jetzt, wo wir
bereit sind, einen Wandsprung durchzuführen, können
wir all die gleichen Dinge tun wie wir es auch bei
jedem anderen Sprung tun würden Sie dann true zurück, sodass
der Eingabe-Handler weiß, dass das
Drücken der Sprungtaste erfolgreich war. Was die Geschwindigkeit des
Charakterkörpers angeht, so wollen
wir, dass er sich nicht nur nach oben bewegt,
sondern sich auch von der Wand weg bewegt. Anstatt also nur die Y-Geschwindigkeit
des Charakters festzulegen, legen
wir den gesamten
Geschwindigkeitsvektor erstellen damit auch einen neuen Vektor. Für das X können wir den normalen Vektorpunkt X der
Wände verwenden, und für Y können wir einen verwenden. Dadurch erhalten wir einen Vektor, der nach
oben und von der Wand weg zeigt , sodass wir die
richtige Richtung haben. dies
mit der Sprungkraft multiplizieren, erhalten
wir einen Vektor mit
einer Größe, die größer ist als unser normaler Sprung, da der ursprüngliche Vektor bereits eine Länge von mehr als eins
hatte Wir können diesen
Richtungsvektor normalisieren, wenn wir wollen, aber die Art und Weise, wie er jetzt funktioniert ,
wird meiner Meinung nach tatsächlich zu
einem besseren Ergebnis führen , wenn die
volle Höhe des Sprungs plus die zusätzliche Kraft von der Wand weg
aufgebracht wird Da die Sprungkraft jedoch eine negative Zahl
ist, wird
dadurch
die Wand senkrecht umgekehrt, sodass sie zur Wand zeigt und
nicht von ihr weg. Also füge ich ein Negativ
an der Vorderseite der Wand hinzu (normal X), um daraus ein
doppeltes Minus zu machen , das Um den Wall Jump zu animieren, benötigt
die Zustandsmaschine
der Figur einen Übergang von Wall Slide zu
Jump , sofern
die Figur Dies steht im Konflikt mit dem
Übergang zum Fallen da die Figur
nicht mehr gleichzeitig durch die Wand rutscht Für den Übergang zum
Springen ist also
ein niedrigerer Prioritätswert erforderlich , um zuerst berücksichtigt zu werden. Anstatt dass der Doppelsprung bereit ist, müssen
wir bei der
Ausführung des Wandsprungs die Einstellung Ist die Wand rutschen auf Stürze setzen. Wenn wir das Spiel starten,
können wir
den Wandsprung bereits ausführen , da er im vorherigen Video
freigeschaltet wurde . Wenn wir gegen die Wand springen, können
wir von ihr springen. Die Größe der
Seitengeschwindigkeit von
der Wand weg entspricht der
ausgeübten vertikalen Kraft. Da die Schwerkraft
den Charakter jedoch ständig
nach unten zieht, ist den Charakter jedoch ständig
nach unten zieht, dies viel weniger auffällig als die Kraft, die
von der Wand weggeht, die nur durch
die
Luftregelung des Charakters oder durch Luftbremsen reduziert wird Luftregelung des Charakters oder durch Luftbremsen Ich würde es vorziehen, wenn auf
meinen Charakter
viel weniger
Seitenkraft ausgeübt würde und er viel weniger
Seitenkraft ausgeübt würde und könnte einem Wandsprung zur
gleichen Wand zurückkehren und
weiter nach
oben klettern Das erfordert mehrere
verschiedene Änderungen
der Physik, um richtig
zu funktionieren. Zum einen wird die
Seitenkraft reduziert, die
Seitenkraft reduziert die
auf den
Wandsprung von der Wand ausgeübt wird , erhält der
Charakter mehr Luftkontrolle um
in größerer Höhe zur
Wand zurückzukehren Beschäftigen wir uns zunächst mit
der Seitenkraft. Anstatt einen Wert fest zu codieren, ist
es immer besser,
exportierte Variablen zu verwenden , damit sie verdreht und optimiert werden
können Ich exportiere einen zweiten Vektor
mit dem Namen Wall Jump Force Multiplikator und gebe ihm einen Standardwert von
minus eins positiv Wir können dann
den resultierenden Geschwindigkeitsvektor mit den resultierenden Geschwindigkeitsvektor diesem neuen Wall
Jump-Kraftmultiplikator multiplizieren Dieser negative Wert macht es
überflüssig, das Negativ auf den Wandnormalenvektor
anzuwenden, was ich
intuitiver finde, da ich das Negativ als etwas
außerhalb der Wand betrachte Wenn zwei Vektoren multipliziert
werden, ist
das Ergebnis das Produkt von beiden Xs und das
Produkt von beiden Ys Mit diesen Werten funktioniert das genauso
wie derzeit Aber da der Wert exportiert wird, kann
ich ihn in meiner
Charakterszene auf minus 0,5 ändern und
so die X-Geschwindigkeit um die Hälfte reduzieren. Wenn Sie sich selbst daran
erinnern möchten , wie
Ihre Variablen funktionieren, Hinzufügen eines zusätzlichen
Nummernzeichens vor einem Kommentar über der
Variablendeklaration erstellt das
Hinzufügen eines zusätzlichen
Nummernzeichens vor
einem Kommentar über der
Variablendeklaration einen Tooltip, der angezeigt
wird, wenn Sie im Inspektor mit der
Maus über die
Variable Wenn ich das Spiel
erneut durchführe,
hat mein Charakter die volle
Aufwärtskraft des Sprungs, aber nur die Hälfte der Sprungkraft wird in X-Richtung angewendet Aber ich kann immer noch nicht an einem höheren Punkt
zur Wand zurückkehren , um noch höher
zu klettern. Dafür muss ich
meinem Charakter viel
mehr Luftkontrolle geben , aber ich möchte nicht, dass
der Charakter zu einem anderen Zeitpunkt mehr Luftkontrolle
hat. Deshalb muss ich
den Luftkontrollwert
speziell nur bei einem
Wandsprung überschreiben den Luftkontrollwert speziell nur bei einem
Wandsprung ihn
dann auf
seinen normalen Wert zurücksetzen. In den
für das Wandspringen exportierten Variablen exportiere ich einen neuen Float für Wall Jump Air Control und setze ihn auf einen
sehr hohen Wert, z. B. vier. Dadurch
beschleunigt der Charakter viermal
schneller als am Boden und
achtmal schneller als bei einem normalen Sprung , bei dem meine Luftkontrolle
standardmäßig auf Ich werde das auch in
einer anderen Variablen
mit dem Ready-Tag speichern einer anderen Variablen
mit dem Ready-Tag Wenn ich es also auf
seinen normalen Wert zurücksetzen möchte ,
weiß ich, was das ist. Da ich nicht weiß,
ob der Spieler von
der Wand weg oder zurück zur Wand springt oder was auch immer er sonst tun möchte, die einzig zuverlässige Methode
, die Luftregelung wäre
die einzig zuverlässige Methode
, die Luftregelung auf die Standardeinstellung
zurückzusetzen, die Verwendung eines Timers. der Szene einen
Timer-Knoten hinzufüge, ich ihn Wall Jump, gebe ihm einen eindeutigen Namen erhalte
dann einen Verweis darauf
mit dem Tag on ready 2. Ich nenne diese Übersteuerung der
Luftregelung Wall Jump
, um das in diesem Zusammenhang etwas
übersichtlicher zu machen. Wenn wir nun
den Wall Jump ausführen, können
wir den Wert der
Luftregelung auf
Wall Jump Air Control ändern und den Timer zur Wall Jump Air Control ändern und Übersteuerung der Wall
Jump-Luftregelung
starten. den Timer-Knoten auswählen, können
wir seine
One-Shot-Eigenschaft auf
true setzen und ihm eine
kurze Wartezeit einräumen. Ich nehme eine halbe Sekunde. Dann verbinde das
Timeout-Signal des Timers mit dem Skript. Wenn der Timer abgelaufen ist, können
wir die
Luftregelung des Charakters auf den Standardwert zurücksetzen das teste, ist es näher, aber ich
komme immer noch nicht auf die Wand. Also muss ich
meinen Wall
Jump-Kraftmultiplikator und die Wall
Jump-Luftsteuerungswerte anpassen Jump-Kraftmultiplikator und die Wall
Jump-Luftsteuerungswerte , bis es funktioniert das Spiel erneut durchführe, hat
mein Charakter jetzt,
wenn ich einen Wall Jump ausführe,
genug Beschleunigung um an einem höheren Punkt zur gleichen
Wand zurückzukehren, sodass ich die Mauer
hochklettern Unser
Charakter ist jetzt in der Lage, von Wänden zu springen, um
vertikale Oberflächen hochzuklettern. Als Nächstes fügen wir eine rasante
Fähigkeit mit
Unbesiegbarkeitsrahmen Wir sehen uns im nächsten Video.
46. 6-4 Strich: Hallo Freunde. In diesem Video geben
wir dem Charakter eine
freischaltbare Dash-Fähigkeit Ab den
Projekteinstellungen der Karten-Eingabe-Tab benötigt
der Karten-Eingabe-Tab eine Schaltfläche, die zum Sprinten verwendet
werden kann Ich verwende die D-Taste oder die rechte
Schultertaste auf meinem Controller dann im Player-Skript
in der Eingabefunktion die Dash-Taste gedrückt wurde, Wenn dann im Player-Skript
in der Eingabefunktion die Dash-Taste gedrückt wurde,
versuche zu sprinten, und
falls das nicht klappt,
puffern Sie die Dash-Eingabe so, dass sie im nächsten Frame wieder
trocken ist, genau wie wir es beim Sprung getan haben. Der Strich benötigt eine Richtung, die wir mit
der Eingabe Singleton,
get axis, move left, move right ermitteln können get axis, move left, move right Um Argumente für ein Callable bereitzustellen, verwenden
wir die Bind-Funktion übergeben die Argumente
dann stattdessen
an diese Funktion Es wäre also besser
, die Funktion input
get axis nur einmal aufzurufen und das Ergebnis zu speichern Da dies
nur während
Frames passiert , wenn der Dash
Button gedrückt wird, ist es nicht so schlimm, hier eine Variable zu
deklarieren. Wenn die gepufferte
Eingabe aufgerufen wird, übergibt
sie die
gebundenen Argumente Wenn der Strich ursprünglich
gedrückt wurde , während der
linke Stick geneigt war, wird
er mit
derselben Richtungseingabe gepuffert Jetzt können wir
diese Strich-Funktion
in unser Zeichenskript für Spieler schreiben , indem wir die
Richtung für den Strich als Parameter akzeptieren und
einen booleschen Wert
zurückgeben, false
zurückgegeben Bevor wir diese Funktion schreiben, benötigen
wir einige Variablen Die Entfernung, zwischen
der das Zeichen gestrichelt werden soll, setze
ich auf 128 Pixel. Die Kraft, die
erforderlich ist, um
diese Entfernung zu erreichen , wird
mit dem Tag on ready berechnet Wir können dieselbe Formel verwenden wie bei der Berechnung der Sprunghöhe, die Quadratwurzel der Entfernung multipliziert mit der
negativen Kraft, was in diesem Fall
Verzögerung mal zwei ist Ich würde auch gerne die
Schwerkraft aussetzen, während der Sprung läuft
. Deshalb speichere ich auch die
Standardgravitation des Charakters in einer Variablen mit
dem Tag on ready. Nun zur Dash-Funktion Wenn die Fähigkeit Strich freigeschaltet
wurde, wollen wir, dass der Charakter Richtung des Strichs zeigt, was wir tun können, indem wir die
Bewegungsrichtung auf diesen Wert setzen. Stellen Sie dann die Geschwindigkeit des
Charakters auf einen neuen Vektor zwei ein, wobei
die Strichrichtung mit der
Strichstärke multipliziert wird , X
und Null für das Y ist. Da der linke
Analogstick gekippt werden kann, würde
dies bedeuten, dass der
Spieler langsamer oder
schneller sprinten kann , je nachdem, wie weit er den Analogstick
auf dem Controller
neigt. Ich möchte nicht, dass das passiert, also verwende ich die Sinusfunktion, um die Neigung
aus der Gleichung
zu entfernen Wir können die Schwerkraft unterbrechen, während
der Dash läuft, den Wert
der Schwerkraft auf Null
setzen und
dann „true“ zurückgeben, weil der Strich erfolgreich war und
nicht zwischengespeichert werden muss Was die Richtung des Sprintens angeht, gibt es mehrere
Fälle, die berücksichtigt werden müssen, nicht nur, wenn der Spieler Richtungseingaben
gibt, sondern auch, ob dies nicht der Fall ist und ob der Charakter gerade eine Wandrutsche
ausführt Da das der
speziellste Fall ist, werde
ich diesen zuerst überprüfen. Wenn der Charakter
durch die Wand gleitet, überschreibe
ich den
Wert von direction, sodass er ein Zeichen für WallNrMaltx Wenn sie nicht
von der Wand
rutschen und der Spieler Richtungseingaben gibt , wenn auf den Dash Button drückt,
dann verwende ich die Richtungssünde als
Richtungsangabe.
Dabei
entferne ich jegliche analoge Neigung aus
dem Eingang, sodass ich
sie dann verwende ich die Richtungssünde als
Richtungsangabe.
Dabei
entferne ich jegliche analoge Neigung aus
dem Eingang, entferne ich jegliche analoge Neigung aus aus der Zeile darunter entfernen kann Wenn der Spieler beim Drücken der Dash-Taste
keine Richtungseingabe macht, gehe
ich davon aus,
dass er vorwärts sprinten
möchte. Ich verwende einen Ternär, wenn die Richtung negativ
eingestellt
werden soll, wenn der Charakter nach links schaut,
oder positiv, wenn die
Schwerkraft
nicht wieder normalisiert.
Wir benötigen eine weitere Funktion
, Wir benötigen eine weitere Funktion die am Ende des Strichs aufgerufen Das benötigt keine
Parameter und gibt auch keinen Wert zurück. Wir setzen einfach die
Schwerkraft des Charakters auf die Standardwerte zurück. In der Charakterszene benötigt der Strich eine Animation
im Animation-Player-Knoten. die Frames pro
Sekunde festlege und heranzoome, füge
ich meine Keyframes hinzu, um den
Strich zu animieren Wir müssen
dieser Spur eine Spur für die
Aufrufmethode und einen Keyframe hinzufügen, um am Ende
der Animation die Funktion
„Bindestrich beenden“ aufzurufen beenden Oder welchen Frame auch immer du möchtest , um die Schwerkraft des
Charakters wiederherzustellen Wenn es mit diesem Verfahren
möglich ist, diese
Animation aus irgendeinem Grund zu unterbrechen, müssen
wir trotzdem die Funktion End Dash aufrufen, um die Schwerkraft des Charakters wiederherzustellen,
im Gegensatz zu
dem Timer, den wir
für die Wiederherstellung der Fehlerkontrolle des
Charakters verwendet haben für die Wiederherstellung der Fehlerkontrolle des
Charakters Behalte das also im Hinterkopf und mache einen Kommentar, um
dich später daran zu erinnern diese Animation
zur Zustandsmaschine hinzufügen, sollte
es möglich sein,
einen Strich von jedem unserer
bestehenden Bewegungszustände aus auszuführen . Daher wäre es besser, diese Animation
auf eine neue Ebene zu legen. Wenn ich die aktuelle
Zustandsmaschine als Projektressource
speichere, nenne ich sie Bewegung und lege sie in den Ordner mit den
Charakterszenen. Erstellen Sie dann eine neue
State-Machine-Ressource für
den Animationsbaum. die
Bewegungszustandsmaschine
als Knoten in dieser
neuen Zustandsmaschine hinzufüge , benenne
ich sie in
Bewegung um und erstelle einen Übergang vom Start zur Bewegung, sodass dies die Standardeinstellung
ist. Wenn wir dieser Zustandsmaschine eine neue Strichanimation
hinzufügen, können
wir einen Übergang von Bewegung zu Armaturenbrett und
zurück zur Bewegung hinzufügen. Um eine
Animation einmal abzuspielen,
sollte
der Übergang, der zu ihr führt, aktiviert sein
und für den Übergang, der aus
der Animation heraus
führt , sollte
der Wechselmodus
auf „Ende“ gesetzt sein , sodass der
erweiterte Modus automatisch bleibt. Wir können diese Animation testen indem wir im Status auf die
Play-Schaltfläche klicken. Bei jedem Klick wird sie
einmal vollständig abgespielt und kehrt zum
Bewegungsstatus zurück, wenn
sie fertig ist Da der Übergang,
der zur Animation führt , nicht automatisch erfolgt, liegt es an uns,
diese Animation manuell
über unser Skript auszulösen diese Animation manuell
über unser Skript eine neue Variable
deklariere, wird diese für
mehrere verschiedene Fähigkeiten verwendet, also werde ich sie ganz oben platzieren und sie kurz
Animation nennen Der Typ dieser
Variablen wird eine
maschinelle Wiedergabe
eines Animationsknotens sein maschinelle Wiedergabe
eines Animationsknotens Dies ist es, was Godot verwendet, um in der Zustandsmaschine zu navigieren
und Animationen abzuspielen den Knoten
im Szenenbaum auswählen, können
wir diese
Wiedergaberessource
unter den Parametern Wiedergabe sehen unter den Parametern Wiedergabe Wir können diese
Ressource abrufen, indem wir auf den
Animationsbaum-Knoten klicken und ihn
ziehen, um seinen Knotenpfad Verwenden Sie dann eckige Klammern , um eine Ressource
von diesem Knoten diese Ressource klicken und sie
aus dem Inspektor in
die eckigen Klammern ziehen aus dem Inspektor in , erhalten wir
den Pfad zur Ressource Wenn wir Bewegung
und Fortbewegung erweitern, können
Sie sehen, dass jede Ebene
der Zustandsmaschine über eine
eigene Wiedergabe-Ressource verfügt Aktuell benötigen wir diese
nur,
um den Dash manuell
auszulösen, aber um den Dash manuell
auszulösen, wir werden bald
weitere Fähigkeiten hinzufügen Dieser Pfad wird sich ebenfalls ändern wenn wir
der Zustandsmaschine weitere Ebenen hinzufügen, sodass sie aktualisiert werden muss Um die Strichanimation auszulösen, bei erfolgreicher
Ausführung eines Strichs die
Wiedergabe so einstellen, können
wir
bei erfolgreicher
Ausführung eines Strichs die
Wiedergabe so einstellen, dass sie in
den Strichstatus wechselt, indem ihren
Zeichenkettennamen als Argument
angeben. Diese Codezeile
entspricht dem Drücken
der Play-Taste im Animationsbaum,
als wir uns
die Animation in der Vorschau angesehen haben Ich möchte
dem Spieler auch die Möglichkeit nehmen den Charakter
zu kontrollieren,
während der Dash läuft. also den
physikalischen Prozess außer Kraft
setzen, können wir
ihn schnell unterbrechen und mithilfe der Funktion
G Current Node überprüfen,
in welchem Zustand sich
die
Animationszustandsmaschine gerade befindet sich
die Dies gibt den Namen der Zeichenfolge zurück, die wir auf den Knoten im
Animationsbaum
geschrieben haben. Wir können ihn vergleichen
, um festzustellen,
ob es sich um eine Bewegung handelt oder Wenn es etwas
anderes als Bewegung ist, setze ich die Bewegungsrichtung
auf Null, bevor mit dem normalen physikalischen Prozess der
Superklasse
fortfahre Dadurch wird verhindert, dass sich
der Charakter bewegt oder in eine
andere Richtung schaut während er eine der Fähigkeiten auf
der obersten
State-Machine-Ebene ausführt Fähigkeiten auf
der obersten
State-Machine-Ebene Im Game Manager-Skript
ändere ich die Pfeiltaste
nach oben, um die Dashabilität freizuschalten Das Spiel zu starten und
die Dash-Taste zu drücken, bringt nichts. Nachdem wir die Aufwärtspfeiltaste gedrückt um die Dashabilität freizuschalten, können
wir sprinten, wodurch der
Charakter vorwärts sprintet Wenn Sie eine Richtung drücken, springt der Charakter
in diese Und wenn wir
beim Verschieben der Wand sprinten, flitzt
der Charakter von der Wand
weg. Wir haben unseren Spielercharakter jetzt Lage, durch
die Umgebung zu rasen, aber wir müssen einen
Cooldown-Timer hinzufügen , um zu verhindern, dass der
Spieler ihn zu oft benutzt. Wir sehen uns im nächsten Video.
47. 6-5 Abklingzeit: Hallo Freunde. In diesem Video fügen
wir Unbesiegbarkeits-Frames und eine Abkühlung
unserer Sprint-Fähigkeit Bevor wir anfangen, dem Dash
Unbesiegbarkeits-Frames hinzuzufügen, wäre
es hilfreich, eine Trefferbox in
unserer Szene
zu haben , damit wir testen können, wie wir
durch In der ersten
Rauminhaltsszene füge
ich einen Bereich zur Kennzeichnung hinzu
und benenne ihn in Hit Box um Füge dann als Kind eine
Kollisionsform hinzu. Geben Sie ihr als Ressource
eine rechteckige Form und setzen Sie ihre
Debug-Farbe auf Rot Du kannst dir vorstellen, dass es sich
dabei um
einen Feind handelt, der dem
Spielercharakter bei Kontakt Schaden Ich mache es eine Kachel dick, 32 Pixel, und zwei
Kacheln hoch, 64 Pixel. Dann verschiebe es nach links. Ich betrachte meinen Test als bestanden, wenn der Spielercharakter
durch diesen Bereich rasen kann ,
ohne verletzt zu werden Damit dieser
Kollisionsbereich dem Spieler Schaden zufügt, muss er überwacht werden Es muss nicht überwachbar
sein,
obwohl es keinen Unterschied macht
, dieses
Kästchen anzukreuzen Es muss auf keiner Ebene
existieren, muss
aber die Hurt Box-Ebene des
Spielers maskieren Wenn es dir hilft,
Kollisionen besser zu verstehen, ist
es in Ordnung, davon auszugehen, dass
diese Trefferbox auf
einer Ebene der gegnerischen Trefferbox oder einer Ebene mit
Umweltgefahren existiert einer Ebene der gegnerischen Trefferbox oder einer Ebene mit
Umweltgefahren Die einzigen Voraussetzungen
sind, dass sie die Hurt Box des Spielers
überwacht und maskiert ein Script an diesen Node anhängen, verbinden
wir sein
On-Area-Enter-Signal mit dem Nachdem wir überprüft haben, ob es für den Bereich
eine Schadensausfallmethode gibt, rufen
wir diese Methode auf und geben eine Methode als
Schadensbetrag Dadurch wird sichergestellt
, dass der Bereich, der
diesen Bereich betritt , über das
Hurt-Box-Skript verfügt,
das wir zuvor erstellt haben . Dieses hat die Methode Take
Damage, die die
Schadenssumme als Parameter
akzeptiert. Wenn ein anderer Bereich
das Signal ohne
ein Hurt-Box-Skript auslöst , würde das zu einem
Fehler führen, da es keine
Take-Damage-Methode zum Aufrufen
gäbe. Um beim Testen des Spiels unsere
Kollisionsformen sehen zu können , können
wir das Debug-Menü öffnen und sichtbare Kollisionsformen
auswählen Wenn wir das Spiel starten,
können wir die Trefferbox sehen
und der Spielercharakter erleidet jedes Mal, und der Spielercharakter erleidet wenn er diesen Bereich betritt,
einen Schaden Es gibt eine Fehlermeldung weil der
Rauminhalt
geladen wird geladen unser Charakter
einen Kollisionsbereich betritt,
und Godot es nicht mag, während eines Kollisionsereignisses einen
weiteren Kollisionsbereich hinzuzufügen während eines Kollisionsereignisses einen
weiteren Kollisionsbereich Wir werden das vorerst ignorieren ,
da wir nur einen Test
durchführen und dies nicht
Teil unseres endgültigen Spiels sein wird Wählen Sie in der Charakterszene den Animation Player-Knoten
und die Dash-Animation aus. Um Unbesiegbarkeits-Frames
zu unserer Dash-Animation hinzuzufügen, müssen wir
lediglich die überwachbare Eigenschaft
der Hurt-Box mit einem Keyframe der Hurt-Box Wir können den genauen Frame festlegen, wann
die Hurt-Box ausgeschaltet und
wann sie wieder eingeschaltet wird Wenn du möchtest,
kannst du
die Sichtbarkeit deiner
Hurt-Box auch per Keyframe an
ihre überwachbaren
Eigenschaften anpassen , sodass du
sehen kannst , wie sie sich während des Spiels aus- und
wieder einschaltet So kannst du leichter erkennen,
wann dein Charakter tatsächlich unbesiegbar ist Es könnte auch hilfreich sein, die Sichtbarkeit der Kollisionsform
des Charakters
auszuschalten , die Verletzungsbox besser sehen
zu können das Spiel ausführen, können
wir jetzt
durch die Trefferbox rasen,
ohne Schaden zu nehmen Betreten des
Bereichs verursacht immer noch
Schaden, ebenso wie das Beenden des
Sprints innerhalb des Jetzt fügen wir dem Dash eine
Abklingzeit hinzu. Wir beginnen damit, der
Charakterszene einen
Timer-Knoten hinzuzufügen Charakterszene einen
Timer-Knoten hinzuzufügen Ich nenne diesen Timer Dash Cooldown und setze seine
One-Shot-Eigenschaft auf true Ich belasse die
Gewichtungszeit bei 1 Sekunde. Das wird die
Abkühlzeit der Fähigkeit sein. Da es sich um
die zweite Fähigkeit
handelt , der ein Timer-Knoten zugeordnet und wir in Zukunft möglicherweise
weitere hinzufügen möchten, sollten
Sie erwägen,
einen normalen Knoten als zusammenklappbaren
Ordner zu verwenden , um sie zu speichern Es ist jedoch hilfreich,
ihm einen eindeutigen Namen zu geben falls wir den Szenenbaum
umstrukturieren möchten Wir müssen das Signal nicht
mit
dem Skript verbinden, um diesen
Timer-Knoten zur Abkühlung zu verwenden In den Variablendeklarationen
für die Dashability verwende
ich das Tag on ready, um einen Verweis auf
diesen neuen Timer-Knoten zu
erhalten Alles, was wir tun müssen, ist
den Timer entweder beim
Starten oder Beenden oder beim Dash Es liegt an dir, was du
bevorzugst, aber wenn du die
Abklingzeit am Ende des Dash starten möchtest , eine weitere Bedingung
erforderlich, um zu verhindern, dass der Spieler zweimal hintereinander
sprintet Ich starte den
Cooldown-Timer, wenn der Dash vorbei ist. Kehren Sie dann zur
I-Anweisung zurück, wo wir prüfen, ob dieser Charakter mit dem Sprinten beginnen
kann. Wir können überprüfen, ob der
aktuelle Knoten
der Animationszustandsmaschine Bewegung ist Das wird später auch
zusätzliche Vorteile haben, da wir
dem Charakter nicht erlauben werden, zu sprinten während er andere
ähnliche Actionfähigkeiten ausführt. Um den Cooldown-Timer durchzusetzen, müssen
wir nur überprüfen,
ob dieser Timer
gestoppt ist , um zu wissen, ob wir wieder sprinten können
sollten Wenn die Dash-Animation bereits
abgespielt wird oder der
Cooldown-Timer nicht gestoppt ist, bedeutet
das, dass der Dash fehlschlägt du das Spiel jetzt startest und
die Dash-Taste drückst, kann der
Charakter nur einmal sprinten und erzwingt
dann eine
Abklingzeit von 1 Sekunde, erzwingt
dann eine
Abklingzeit von 1 Sekunde bevor er wieder sprinten
kann Das funktioniert, wird
dem
Spieler aber in keiner Weise mitgeteilt. Normalerweise
haben Spiele wie dieses eine diagetische Anzeige,
etwas, das im Spiel
vorhanden ist, nicht auf dem HUD, um dem Spieler mitzuteilen , wann
der
Cooldown Fügen wir also der Charakterszene einen Animated
Sprite Two-D-Node hinzu und nennen
ihn eine
Sprite-Frames-Ressource für diesen Knoten erstellen, können
wir ein Sprite-Sheet importieren Ich lege das
vorerst einfach in
den Dust-Ordner , anstatt
einen neuen Asset-Ordner
für ein Sprite-Sheet zu erstellen einen neuen Asset-Ordner
für ein Sprite-Sheet Und füge die Sprite-Frames
aus dem Sprite-Sheet hinzu. Ich deaktiviere das Looping, setze
die Frames pro Sekunde auf 12 und füge
am Ende der Animation ein leeres Bild hinzu Da die Figur nicht zentriert
ist, verschiebe
ich sie um 12 Pixel nach oben Diese Animation ist
länger als 1 Sekunde, aber ab der 1-Sekunden-Marke
möchte ich , dass der Cooldown als abgeschlossen betrachtet
wird. Ich gebe diesem Knoten
einen eindeutigen Namen. Zurück im Skript
müssen wir nur noch einen Verweis
auf diesen Knoten abrufen. Und sag ihm, er soll spielen
, wenn der Dash endet. Aber da meine Animation
länger ist als der Dash
Cooldown Timer, muss
ich die Animation tatsächlich
beenden bevor ich sie abspiele, falls
sie noch läuft Dadurch wird die
Animation wieder auf den Start zurückgesetzt. A nun Wenn wir
nun das Spiel starten und die Sprint-Fähigkeit
verwenden, die Animation abgespielt, aber sie folgt nicht
dem Charakter. Das liegt daran, dass ein normaler Knoten
keine Transformation besitzt. Daher hat er
keine Position. Dadurch wird die
Vererbungslinie
vom Wurzelknoten des Charakters unterbrochen . Der Animated Sprite
Two-D-Knoten
beginnt jetzt also mit seiner eigenen Abstammung
für zwei D-Transformationen, beginnend an Wir können den Typ
des Fähigkeiten-Ordners
auf zwei D ändern , sodass er eine Reihe von Sequenzen
durch den Szenenbaum
bietet
und das animierte Sprite dem Stammknoten
folgt Dem Spieler ist jetzt klar, dass seine Fähigkeit „Sprinten“
auf Abklingzeit ist, und genau wann er
wieder sprinten kann, ohne zusätzliche
Informationen auf dem HUD
hinzufügen zu müssen ohne zusätzliche
Informationen auf dem HUD
hinzufügen Wir verfügen jetzt über unsere
Fähigkeit, durch Trefferboxen zu rasen,
ohne getroffen zu werden, und abzukühlen, bevor wir sie erneut einsetzen
können Als Nächstes fügen wir eine
passive Fähigkeit , die das Aussehen des
Charakters verändert. Wir sehen uns im nächsten Video.
48. 6-6 Hüte: Hallo Freunde. In diesem Video werden
wir eine
passive Fähigkeit implementieren , die das Aussehen des
Charakters verändert. Ausgehend von der
Rauminhaltsszene werde
ich für diesen Test den
Kollisionsbereich
von zuvor duplizieren . Dieses Mal wird der
Kollisionsbereich speziell die
intensive Hitze
aus dem Inneren eines Vulkans repräsentieren . Ich ändere die Farbe auf Orange,
damit ich weiß, was was ist. Ich möchte, dass der Spieler diesen Bereich erst durchqueren
kann wenn er einen magischen Hut freigeschaltet hat es ihm ermöglicht
, unversehrt
voranzukommen Aber wenn sie den Hut
tragen, können sie
trotzdem Schaden durch
normale Trefferboxen Anstatt also
die
Hurt Box-Ebene für normale Spieler zu maskieren , verwende
ich eine andere Ebene Ich verwende Ebene 14
als Ebene , die diesem Wärmeeffekt in der
Umgebung gewidmet ist kann mir das leicht
merken, da es
direkt unter zehn liegt. In den Projekteinstellungen
nenne ich diese Ebene Heat. Dann werde
ich in der Charakterszene dafür sorgen, dass die Hurt-Box
auch auf dieser Ebene existiert. Das funktioniert jetzt
genauso wie der Kollisionsbereich zuvor und
fügt
dem Spieler jedes Mal, wenn er diesen Bereich betritt, einen Schaden zu . Es sucht nur auf
Ebene 14 und nicht auf Ebene zehn nach Kollisionen Ebene 14 und nicht auf Ebene zehn Alles, was wir tun müssen, um
den Spielercharakter immun gegen Hitzeschaden
zu machen , während er den Hut
trägt, ist, die Ebene
14 aus der
Kollisionsebene der Hurt-Box zu entfernen . Um das Aussehen des
Charakters zu ändern, lege
ich zusätzliche
Sprites über den Charakter Ich importiere neue Spritesheets für drei verschiedene Upgrades einen Edelstein, einen Umhang und einen Hut Dann füge
ich in der Charakterszene für jeden von ihnen einen zusätzlichen Sprite Tu
Di-Knoten Alle mit Atlas-Texturen,
genau wie beim Body-Sprite. Weisen Sie dann jedem Knoten die Spritesheets als Atlas-Eigenschaft
zu So wie diese Objekte gezeichnet wurden, muss
ich sie
speziell in der
Reihenfolge der Katze,
dann des Umhangs, dann des
Hutes und der Marmelade darüber schichten speziell in der
Reihenfolge der Katze,
dann des Umhangs, dann des
Hutes und der Marmelade darüber Ich beginne jeweils mit
dem ersten Sprite an
Position 00 mit einer Größe von 32 mal 36 Pixeln und gebe ihnen den gleichen Offset, um sie um 18 Pixel nach oben zu verschieben Diese Elemente werden so
gezeichnet, dass sie
synchron mit dem
normalen Charakter-Sprite animiert synchron mit dem
normalen Charakter-Sprite animiert Somit sind alle
Regionswerte für jede
Ebene zur gleichen Ich muss nur die
Atlas-Texturregion
jedes Sprites zur Animation hinzufügen Atlas-Texturregion
jedes Sprites zur Animation Kopieren Sie dann
die Keys aus
der Sprite-Hauptspur und fügen Sie sie in
die anderen Spuren Und ändern Sie ihren
Aktualisierungsmodus auf diskret. Jetzt enthält die Animation
auch alle Sprite-Ebenen in
perfekter Synchronisation Ich muss das für
alle meine Animationen tun, aber es wird nicht
so viel Aufwand erfordern Um jedes
dieser Sprites umzudrehen, könnten
wir alle
ihre Flip-H-Eigenschaften
jedes Mal festlegen , wenn sie die Richtung
ändern Aber es gibt einen einfacheren Weg Vererbung des
Szenenbaums zu
nutzen Wenn wir alle anderen Sprites
zu Kindern des Body-Sprites machen , erben
sie ihre
Transformation Und wir können ein Sprite mithilfe
seiner Transformation umkehren , indem wir seine
X-Skala auf einen negativen Wert setzen Beachten Sie, dass dieser Trick nicht
für Dinge verwendet werden
sollte , die mit
Physik oder Kollisionen zu tun Es funktioniert hier gut, weil
wir nur Sprites zeichnen. In der Face-Left-Funktion
in unserem Zeichenskript anstelle von Flip H können
wir
anstelle von Flip H den Skalierungspunkt
X auf einen negativen Wert setzen, wenn er links ist, andernfalls auf einen
positiven Wert Dadurch wird nun
das Umdrehen
aller Sprites synchronisiert das Umdrehen
aller Sprites Wenn die gesamte Einrichtung
der Sprites abgeschlossen ist, ich die Sichtbarkeit
der anderen Sprites standardmäßig
aus und schalte sie
dann ein, sobald Fähigkeiten freigeschaltet Im Spielercharakter-Skript benötigen
wir eine Funktion, mit der wir festlegen können, welche
Sprite-Ebenen
sichtbar sind , je nachdem, welche Fähigkeiten
der Spieler Ich nenne es Update
Sprite visibility. Geben Sie dann jedem der Sprites einen eindeutigen Namen und stellen Sie ihre Sichtbarkeit so ein, dass Wert
der freigeschalteten Fähigkeiten
für die entsprechende Fähigkeit entspricht Durch den Doppelsprung
wird der Umhang hinzugefügt. Der Hut ist offensichtlich. Und die Fähigkeit,
Projektile abzuschießen, wird den Edelstein hinzufügen. im Game Manager-Skript Wenn wir im Game Manager-Skript das Spiel zum ersten Mal
spielen, können
wir diese Funktion aufrufen, um die
Sprite-Sichtbarkeit des Charakters
sofort zu aktualisieren , falls wir
ein Safe-Ale mit
bereits freigeschalteten Fähigkeiten geladen haben ein Safe-Ale mit
bereits freigeschalteten Fähigkeiten Während des Spiels möchten
wir
diese Funktion auch immer dann aufrufen, wenn der
Spieler eine neue Fähigkeit freischaltet Deshalb fügen wir diesem Skript
ein Signal
hinzu, wenn eine Fähigkeit freigeschaltet
wurde, mit der
Ganzzahl der Fähigkeiten als Parameter Schreiben Sie dann eine öffentliche Funktion,
um eine neue Fähigkeit freizuschalten Dabei wird dieselbe
Fähigkeitsnummer akzeptiert und das Signal weggelassen Dieses Signal können wir dann mit dem
Spielercharakter verbinden. Wir haben die
Sprite-Sichtbarkeitsfunktion zum Aktualisieren jedoch nicht so
geschrieben , dass sie irgendwelche Parameter akzeptiert Wenn wir also das Signal verbinden, sollten
wir die Bindung eines Arguments aufheben , um Fehler zu vermeiden Dadurch wird das Aussehen
des Charakters verändert, aber er wird trotzdem
Hitzeschaden erleiden , wenn er den Hut
trägt Bei der Aktualisierung der Sichtbarkeit von
Sprites im speziellen Fall, dass
der Hut geschmückt wird, werde
ich auch
die Kollisionsebene
für Hitzeschaden entfernen , um
ihn davor immun zu machen Um eine einzelne
Ebene aus einer Bitmaske zu entfernen, zuerst den Mauszeiger über die Ebene und
notieren Sie sich ihren Wert Ebene 14 hat einen Wert von 8.192, was zwei hoch 13 oder zwei hoch 14 minus
eins Die Kollisionsebene ist
eigentlich eine Ganzzahl, die binär eine
Folge von Nullen und Einsen ist Derzeit sind es nur Nullen, außer dass das zehnte
und das 14. Bit eins sind Alles, was wir tun müssen, ist
das 14. Bit auf Null zu ändern , um es aus dieser Ebene zu
entfernen Wir beginnen damit, einen
Verweis auf die Jetbox zu finden. Da diese Funktion nicht sehr oft aufgerufen
wird, ist
es in Ordnung, einen Knotenpfad zu verwenden Um die Kollisionsebene zu entfernen, könnten
wir
ihren Wert 8.192 subtrahieren Dies hängt jedoch der Kollisionsebene ab, die derzeit auf Ebene 14
vorhanden ist Wenn wir
diese Funktion aus
irgendeinem Grund aufrufen würden , obwohl Layer 14 bereits ausgeschaltet
ist, würde eine
einfache Subtraktion nicht funktionieren mit dem Bit-Operator und auf der
Kollisionsebene unserer Hurt-Box Wenn wir mit dem Bit-Operator
und auf der
Kollisionsebene unserer Hurt-Box eine Sequenz
aller Einsen angeben können , bei
der nur das 14. Bit Null ist, wird das 14. Bit unabhängig von
seinem aktuellen Wert auf
20
gesetzt unabhängig von
seinem aktuellen Wert auf
20 Um diese Zahl zu erhalten,
können wir die Bits von
8.192, dem Ebenenwert, umkehren 8.192, dem Ebenenwert, Dies geschieht mit dem
Bitwise Naught-Operator, in GDScript ein
Tilday Dies ist eine
mathematisch sehr effiziente Methode , Kollisionsebenen zu entfernen. Wenn Sie
eine Kollisionsebene hinzufügen und ihr Bit auf eins
setzen möchten , müssen Sie
lediglich den
Operator oder anstelle von und verwenden und den Knoten entfernen Aber wir sind nicht daran
interessiert, das hier zu tun. Im Game Manager-Skript aktualisiere
ich meine
Eingabefunktion, um
jede neue Fähigkeit nacheinander freizuschalten jede neue Fähigkeit nacheinander wenn ich für meinen Test den
Aufwärtspfeil drücke. deklariere hier eine neue Variable, damit sie mit
meinem Testcode gebündelt wird Ich werde daran denken, dies zusammen mit
der Eingabefunktion zu
löschen , wenn ich sie
nicht mehr zum Testen benötige Ich nenne sie nächste Fähigkeit
als Ganzzahl, die natürlich
standardmäßig Null ist Jedes Mal, wenn ich den Aufwärtspfeil drücke, schalte
ich die nächste Fähigkeit und drucke den
Namen dieser Fähigkeit aus Wir können die Tastenfunktion für eine
Aufzählung verwenden , um eine Reihe von
Zeichenketten zu erhalten , die mit denen
identisch sind, die wir als
Aufzählungseinträge geschrieben haben wir also das Schlüssel-Array mit
der Fähigkeitsnummer indizieren , erhalten wir
den Namen dieser Fähigkeit Ich inkrementiere dann die
nächste Fähigkeit, halte sie
aber auf einen Wert
zwischen Null und der Größe der Fähigkeitsaufzählung minus
Eins Fähigkeitsaufzählung minus gedrückt, um Fehler zu vermeiden Ich lösche die
aktuelle sichere Datei ,
sodass meine Fähigkeiten zunächst
gesperrt sind und
sichtbare Kollisionsformen aktiviert werden gesperrt sind und
sichtbare Kollisionsformen aktiviert das Spiel ausführen, beginnen
wir
ohne freigeschaltete Fähigkeiten und mit dem
Standardcharakter Sprite Ich öffne den
Remote-Szenenbaum und wähle die Charaktere Hurt Box aus, um zu überprüfen, ob sie
sich auf den Ebenen 10 und 14 befinden Sie den Aufwärtspfeil einmal drücken, ist
die Fähigkeit Doppelsprung jetzt freigeschaltet, sodass der Charakter einen Umhang
trägt erneut den Aufwärtspfeil drücken, wird
der Wandsprung freigeschaltet, aber das Aussehen des Charakters
bleibt unverändert
, da diese Fähigkeit nicht
mit einer kosmetischen Änderung verbunden war einen der Kollisionsbereiche
berühren Sie einen der Kollisionsbereiche
berühren
, erleidet der Charakter Schaden. Wenn Sie erneut nach oben drücken, ist
jetzt
auch das Armaturenbrett freigeschaltet und der
Charakter sieht immer noch genauso aus. Wieder hoch, um
den magischen Hut freizuschalten, und wir können sehen, dass sich die Hurt-Box des
Charakters nicht mehr auf Ebene 14,
sondern immer noch auf Ebene zehn
befindet . Das Berühren der normalen
Trefferbox verursacht Schaden, aber das Betreten der neuen Trefferbox mit vulkanischer
Hitze nicht,
was bedeutet, dass der Charakter dagegen
immun ist , solange er den Hut trägt. ein letztes Mal nach oben drücken, schalten
wir die
Schussfähigkeit frei und fügen den Edelstein hinzu, aber das haben wir noch nicht
implementiert. Wir lassen unsere
Charaktere jetzt ihre
Outfits wechseln , um sie an ihre
Fortschritte im Spiel anzupassen Die letzte Fähigkeit, die wir hinzufügen werden,
ist das Abfeuern eines Projektils. Wir sehen uns im nächsten Video.
49. 6-7 Geschoss: Hallo Freunde. In diesem Video fügen
wir einen
Projektilzauber hinzu, den der Spieler abfeuern kann, indem er seine
magischen Punkte Zuerst müssen wir
diesem Charakter magische
Punkte geben , die er ausgeben kann Im Spielercharakter-Skript werde
ich eine neue
Exportkategorie für Zaubersprüche hinzufügen Dann zwei Variablen für ihre maximale Magie und ihre aktuelle Magie,
beide als Floats Wir benötigen außerdem Signale, die Änderung dieser
Werte ausgegeben werden müssen,
damit wir das HUD aktualisieren können Indem wir die Bereitschaftsfunktion außer Kraft setzen, können
wir den maximalen Magiewert auf den Wert aus den Speicherdaten des
Spielers Dann starte ich den
Player einfach mit voller Magie, setze den aktuellen Wert auf den Maximalwert und gebe
die geänderten Signale
aus, um das
HUD zu aktualisieren Von der Spielszene aus können wir verbinden Signale der
Spielercharaktere
einfach mit der Magieanzeige da sie
in derselben Szene existieren Der Magieanzeige ist
kein Skript angehängt, aber
sie benötigt auch keins. Da der Fortschrittsbalken bereits die Funktionen
bereitstellt, die
wir benötigen, müssen wir nur die Skriptmethoden
ausschalten Die Range-Klasse gibt uns die Funktion set max, die einen Float-Parameter
akzeptiert Ebenso wie die
Set-Value-Funktion, auch einen
Float-Parameter akzeptiert. Jetzt
aktualisiert sich die Magieanzeige
automatisch mit den magischen Variablen des
Spielercharakters. In den Projekteinstellungen benötigt
der Karten-Eingabe-Tab
eine Taste , die vom
Spieler gedrückt werden kann, um einen Zauberspruch zu sprechen. Ich verwende die C-Taste oder die obere Gesichtstaste
auf meinem Controller. Dann können
wir im Spielerskript das gleiche
Format wie beim Sprung kopieren, um zu
versuchen, einen Zauberspruch
zu wirken. Falls das nicht gelingt, können wir die Eingabe
zwischenspeichern, um
es im nächsten Frame erneut zu versuchen. Zurück im
Player-Charakter-Skript können
wir die Cast-Funktion schreiben, die keine Parameter
akzeptiert
und einen booleschen Wert zurückgibt Alles, was wir hier wirklich tun müssen,
ist zu überprüfen, ob die Fähigkeit
freigeschaltet wurde und ob der Charakter gerade
keine anderen Aktionen ausführt, ob der
aktuelle Knoten der Animation Bewegung ist Dann weisen Sie die Animation an,
zur Besetzungsanimation zu wechseln und true zurückzugeben, wenn die Eingabe erfolgreich
war, oder
false, wenn dies nicht der Fall war. Falls wir nicht möchten unser Zauberspruch
sofort ausgeführt wird, muss
alles andere in einer separaten Funktion
geschehen Wir werden dieses eine
Schießprojektil nennen. Es benötigt keine Argumente
oder muss irgendeinen Wert zurückgeben, und wir haben noch keine Informationen, um
diese Funktion zu schreiben, aber wir müssen diese
Funktion deklarieren und speichern, bevor wir
sie in die Casting-Animation aufnehmen können zur
Charakterszene wechseln, wir zunächst
ein animiertes Sprite
zu Dende hinzu ,
das wir als Casting-Effekt verwenden können Dazu wird eine
Sprite-Frames-Ressource benötigt. Bevor ich meine
Spritesheets für Spell Casting importiere, erstelle
ich einen neuen Ordner
für magische Sprites und verschiebe den Dash
Cooldown-Effekt Importiere dann Sprites für das Casting, das Projektil Hinzufügen der
Casting-Animations-Sprites
zur Sprite-Frames-Ressource zur Sprite-Frames-Ressource Y Ich stelle es auf 12 Bilder pro
Sekunde ein, kein Und ich füge
am Ende der Animation ein leeres Bild hinzu und verschiebe es
dann
mit dem Y-Offset um 18 Pixel nach oben Das sieht gut aus, aber wenn
wir es auf die
Figur Sprite ausrichten, wird sie ebenfalls in
dieselbe Richtung gedreht
wie die Figur den
Animation Player-Knoten auswählen, können
wir jede
der vorhandenen Animationen duplizieren , um eine Casting-Animation zu
erstellen Nachdem wir
nicht benötigte Spuren entfernt und alle
Sprite-Region-Keyframes aktualisiert
haben, fügen wir Callmethoden-Tracks
sowohl zum Stammknoten des Charakters Casting-Effekt
Animiertes Sprite auf zwei D hinzu. Für den Casting-Effekt müssen wir ihm
lediglich sagen, dass er
abgespielt werden soll Für den Charakter fügen wir einen Keyframe Diese Keyframes können
einfach so angepasst werden sie jederzeit während
der Casting-Animation auftreten Ich starte den Cast-Effekt
im zweiten Frame und
feuere das Projektil
im dritten Der Rest der Animation
dient als Wiederherstellung. Im Animationsbaum müssen
wir nur
den gleichen Vorgang wiederholen, müssen
wir nur
den gleichen Vorgang wiederholen den wir mit dem Strich
verwendet haben. Übergang zur
Besetzung ist aktiviert, und am Ende
der Animation kehren wir zur
Bewegung zurück am Ende
der Animation kehren wir zur
Bewegung Als Nächstes bauen wir
das eigentliche Projektil zusammen. Sie der
Charakterszene zunächst eine D-Note für den Bereich
zwei hinzu Charakterszene zunächst eine D-Note für den Bereich
zwei Geben Sie ihr dann eine
Kollisionsform und eine Formressource. Ich verwende einen Kreis, reduziere aber
seinen Radius auf acht Pixel und ändere seine
Debug-Farbe in eine Farbe, ich noch nicht verwendet habe, wie Lila Fügen Sie dann ein animiertes Sprite als
Denode hinzu und geben Sie ihm eine
Sprite-Frames-Ressource Zuerst fügen wir
die Sprite-Frames
für das Projektil so hinzu, wie
es starten soll , und verwenden diese als Das Ganze wird wiederholt und ich stelle meine Bildrate auf 12
Bilder pro Sekunde ein Dann klicken wir auf die Schaltfläche „
Animation hinzufügen“, um
eine zweite Sprite-Animation zu erstellen eine zweite Sprite-Animation und nennen diese
etwa Impact Jetzt können wir weitere
Sprite-Frames für
eine Impact-Animation hinzufügen , die
von demselben Projektil abgespielt wird , wenn
es mit etwas kollidiert Möglicherweise möchten Sie am Ende
dieser Animation auch ein
leeres Bild hinzufügen , damit das letzte Bild während seiner gesamten Dauer gezeichnet Denken Sie daran, die
Standardanimation auf Autoplay einzustellen, damit wir
diese Animation abspielen, wenn das Projektil automatisch erzeugt das
Projektil immer noch innerhalb der
Charakterszene Sie das
Projektil immer noch innerhalb der
Charakterszene an der
Stelle, an es im
Verhältnis zum Charakter beginnen soll Du kannst das
einfacher machen, indem du
das Projektil und den Szenenbaum
auswählst und
die Alt-Taste gedrückt hältst,
während du Meins befindet sich 12 Pixel
weiter rechts und oben vom Ursprung
des Charakters Als Nächstes fügen Sie eine Markierung mit zwei D-Knoten als untergeordnetes Objekt des Projektils Dadurch wird sichergestellt
, dass seine Position exakt mit dem Projektil übereinstimmt Die Markierung zum D-Knoten entspricht exakt
der eines zweiten D-Nodes, mit der
Ausnahme, dass im
Editor
ein kleines Gizmo gezeichnet wird, sodass wir
genau sehen können, wo Das gibt uns die Position,
an der wir das Projektil
beim Wirken
des Zauberspruchs in unsere Szene spawnen wollen Projektil
beim Wirken
des Zauberspruchs in unsere Szene So können wir den Marker
Tutti-Knoten entsprechend benennen. Dann ordnen Sie den Marker
Tutti-Knoten dem Charakter Sprite neu zu Da es sich um ein untergeordnetes Element
des Charakters Sprite
handelt, kehrt er seine Ausrichtung um, wenn
der Charakter seine Blickrichtung automatisch ändert . Speichern Sie den Projektilzweig als eigene Szene und speichern Sie ihn in einem neuen Szenenordner Lösche ihn dann aus
der Charakterszene. Wir haben jetzt ein Projektil und wir wissen, wo wir es spawnen
wollen, also kehren wir zum
Spielercharakter-Skript Wir können das Projektil als
gepackte Szene exportieren und
es in den Inspektor einfügen Wir können uns auch einen Verweis auf
die Spawn-Markierung holen. Es wäre besser, wenn
es einen eindeutigen Namen hätte. Und wir müssen die magischen Kosten für das Abfeuern
dieses Projektils angeben magischen Kosten für das Abfeuern
dieses Projektils Ich setze meins auf
16 magische Punkte. Bevor der Spieler mit dem
Wirken des Zauberspruchs beginnen kann, sollten
wir auch
überprüfen, ob er
genug Magiepunkte hat, indem wir überprüfen, ob seine aktuelle Magie
höher oder gleich den Magiekosten ist . Wenn dann die Zauberanimation die Funktion
Projektil abschießen
aufruft, da zwischen dem Aufruf dieser
beiden Funktionen ein
sehr kurzes
Zeitfenster liegt , ist
es keine schlechte Idee,
auch noch zu überprüfen, ob
der Charakter noch genug Magie hat um
den
Zauber hier erneut Prüft man also, ob die aktuelle Magie geringer
ist als die Kosten, wird das Projektil beim Verlassen dieser Funktion nicht abgefeuert wissen, dass das nicht der Fall
ist, können
wir die Kosten
von unserer aktuellen Magie abziehen
und das aktuelle Magie-Signal ausgeben , um
das HUD zu
aktualisieren Dann erstellen wir
ein neues Projektil indem wir die gepackte Szene
instanziieren Wir wollen nicht, dass es
dem Charakter als
Kind folgt , sondern als
Geschwisterkind innerhalb der Welt, sodass er sich selbstständig bewegen kann Also holen wir uns zuerst den Elternteil bevor wir als Kind dieses
Projektil hinzufügen Stellen Sie dann seine Position
innerhalb der Welt so ein, dass sie der globalen des
Projektil-Spawn-Markers entspricht Wir müssen hier die globale
Position verwenden, da sich
die lokale Position des Markers auf die Position des
Charakters bezieht, aber das Projektil
wird
zum Weltknoten hinzugefügt ,
nicht zum Wir wollen also die Position
des Markers im Verhältnis
zur Welt Und zum Schluss sagen wir
diesem Projektil, in welche
Richtung es abgefeuert wird Wir können ein Argument
als Vector mit zwei Punkten
links übergeben , wenn der Charakter nach
links oder rechts zeigt, andernfalls Jetzt müssen wir diese
Funktion für unser Projektil schreiben, die Projektilszene öffnen dann ein Skript
zu ihrem Stammknoten hinzufügen, wir nennen es Projectile
und speichern es im Es ist hilfreich, diesem Skript
einen Klassennamen zu geben , damit wir später darauf
verweisen können. Dieses Projektil benötigt
einige exportierte Variablen,
wie die Geschwindigkeit, mit der es sich bewegt, und die Höhe des
Schadens, den es verursacht, wenn
es auf etwas trifft Ich nenne diesen
Standardschaden, damit er überschrieben
werden kann , und gebe
ihm den Wert eins Wir benötigen außerdem einen Verweis auf den Knoten Animated Sprite Tu Di um ihm mitzuteilen, welche
Animation Es muss wissen, in welche
Richtung es
abgefeuert wird und wie viel Schaden
es tatsächlich anrichten wird, wenn nicht die Standardeinstellung, und ob es sich
gerade bewegt oder nicht Wenn wir aufgefordert werden, zu feuern, können wir die Richtung als Vektor
zwei und die Höhe des Schadens
als Ganzzahl mit einem
Standardwert von Null
akzeptieren zwei und die Höhe des Schadens , was ihn zu einem optionalen Parameter macht. Wir setzen die Richtung auf
den Richtungsparameter und drehen das Sprite um, wenn der
Richtungspunkt X kleiner als
Null
ist, also links Setzen Sie dann Schaden auf Schaden wenn ein
Schadenswert angegeben wurde, andernfalls verwenden Sie den Standardwert für
Schaden, und schließlich wird
der Wert auf „Wahr“ gesetzt Überschreiben der Prozessfunktion. Wenn sich dieses Projektil bewegt, können wir seine
Position
so einstellen, dass plus
gleich Richtung mal
Geschwindigkeit mal Delta ist können wir seine
Position
so einstellen, dass plus
gleich Richtung mal
Geschwindigkeit mal Delta Dieses Projektil
muss sowohl
mit Körpern als auch mit Bereichen kollidieren sowohl
mit Körpern als auch mit Also müssen wir sowohl die
Signale für den
eingegebenen Bereich als auch für den Körper mit dem Skript
verbinden Signale für den
eingegebenen Bereich als auch für den Körper mit dem den Körpern, mit denen dieses Projektil kollidieren
wird , handelt es sich um das Gelände, während es sich bei den Bereichen
um verletzte Boxen handelt Beide werden im Großen und Ganzen das Gleiche tun
. Also rufen wir
von beiden eine separate
private Funktion auf und benennen sie beim Aufprall. Wenn das Projektil
auf etwas trifft, lassen wir es aufhören, sich zu bewegen, deaktivieren
dann weitere Kollisionen,
indem wir seine
Kollisionsmaske auf Null setzen Dadurch werden alle Ebenen
der Kollisionsmaske ausgeschaltet. Spielen Sie dann die
Aufprallanimation ab und verbinden Sie das Signal „Animation abgeschlossen der Viertelfunktion, um den
Knoten
automatisch aus der Szene zu entfernen. Wenn das Projektil eine Verletzungskiste
trifft, können
wir diese
Verletzungsbox anweisen,
den Schaden zu nehmen, bevor sie den
Aufprall auslöst wir den
Körperparameter nicht verwenden, können
wir ihn mit einem Unterstrich als
unbenutzt markieren Wenn das Projektil
nichts trifft, müssen
wir es trotzdem reinigen Eine einfache Möglichkeit besteht darin, dass der Raum automatisch zerstört, wenn
es den Raum verlässt, in dem
es gespawnt wurde , wäre
es einfacher, dies über das Raumskript Anstatt
dieses Signal jedes
Mal für jeden Raum über
den Inspektor zu verbinden , wäre
es einfacher, dies über das Raumskript zu tun Also schreiben wir eine Funktion, bei der ein
Bereich verlassen wird, einen Bereich als ein
D ohne zwei
akzeptiert und keinen Wert zurückgibt Falls es sich bei dem Bereich, der
diesen Raum verlassen hat, um ein Projektil handelt, stellen
wir es in die Warteschlange, bis es
vom Szenenbaum befreit wird Verbinden Sie dann das Signal, das das Gebiet verlassen hat, mit
der Bereitschaftsfunktion Wir können dies auch tun
, um die vom Körper
eingegebenen Signale automatisch miteinander zu verbinden Denken Sie nur daran, dass
Sie, falls in einer Ihrer Raumszenen
diese Signale bereits angeschlossen sind, Ihrer Raumszenen
diese Signale bereits angeschlossen sind,
diese trennen sollten, um Fehler zu vermeiden. Da wir jedoch
Hunderte von Räumen einrichten, diese
Signalverbindungen automatisch sparen wir
viel mehr Zeit und Mühe,
wenn wir diese
Signalverbindungen automatisch per Skript Damit der Collider des Raums ein aus ihm
austretendes
Projektil erkennen kann,
muss er die Kollisionsschicht maskieren, auf
der das
Projektil Wenn ich das Spiel starte,
beginne ich bereits mit allen Fähigkeiten die im vorherigen Video
freigeschaltet und meine Magieleiste Ich öffne den
Remote-Szenenbaum, damit ich
sehen kann , wie mein Projektil erscheint
und wie es aufgeräumt wird ich zum Spiel zurückkehre, drücke den Schießknopf und wirf einen Zauberspruch aus, der
das Projektil abfeuert Das Projektil kollidiert mit der Wand und explodiert Meine Magieanzeige wird um die Kosten
des Zauberspruchs reduziert. das Projektil in
die andere Richtung zielt , kann es
nichts treffen und verlässt daher
den aktuellen Raum Aber anstatt weiter in die Unendlichkeit
zu fliegen, wird
es zerstört, sobald es die Grenzen dieses
Raums
verlässt Wir haben jetzt all unsere freischaltbaren
Fähigkeiten im Spiel
und sind bereit, Feinde
hinzuzufügen Wir sehen uns im nächsten
Abschnitt.
50. 7-1 Tempo: Hallo, Freunde. In diesem Abschnitt werden
wir unserem Spiel einige
Feinde hinzufügen. Ich beginne damit,
einen neuen Ordner für
meine feindlichen Sprites zu erstellen und ein Spritesheet von
meinem ersten Feind, der blinden Maus, zu
importieren meinem ersten Feind, der blinden Maus, Wir benötigen auch einen neuen
Szenenordner für Feinde. Wir können es
einfacher machen, wenn wir
unseren bestehenden Spielercharakter duplizieren unseren bestehenden Spielercharakter , um ihn als Vorlage
zu verwenden, um uns zum Feind zu machen. Verschiebe ihn dann in
den Ordner des Feindes. Wenn ich die neue Szene öffne,
benenne ich den Stammknoten so um, dass er dem Namen der Szene
entspricht. Gehen Sie dann die
Szenenhierarchie durch und entscheiden Sie, welche Knoten für den Feind
benötigt werden
und welche nicht. Wir benötigen immer noch
eine Kollisionsform um mit dem Gelände zu kollidieren,
eine Hurt-Box , um Schaden zu erleiden, und einen Sprite, um den Charakter zu
zeichnen Aber die Kinder des
Sprites sind nicht notwendig, da dieser Feind weder andere Sprites
noch die
Fähigkeit besitzt, Projektile abzuschießen Wir behalten die Knoten
Animation Player, Baum und Soundeffekt bei, obwohl du vielleicht die Sounds ändern
möchtest Der Coyote-Timer wird
nicht benötigt. Ob du
möchtest, dass deine Feinde auf der Karte gezeichnet
werden, liegt
ganz bei dir, aber du
musst natürlich
die Textur ändern , wenn du dich dafür entscheidest, das
Kartensymbol beizubehalten Und wir können auch
alle Fähigkeitsknoten löschen. An den Stammknoten ist das
Spielercharakterskript angehängt. Wir müssen es durch
das normale Charakterskript ersetzen , da dies nicht der
Spielercharakter ist und sie keine der Fähigkeiten des
Spielercharakters haben. den Sprite Toti-Knoten auswählen, können
wir die Atlas-Eigenschaft
Atlas-Texturen durch ein Sprite-Blatt
für unseren Feind ersetzen ein Sprite-Blatt
für Da sich das Spritesheet von dem
für meinen Spielercharakter
unterscheidet, muss
ich jede
meiner Animationen in meinem Animation
Player-Knoten durchgehen und überprüfen
, ob sie die
richtige Anzahl von
Frames und die richtigen Frames und die richtigen Dieser Feind hat weniger Animationen als der
Spielercharakter, sodass ich alles
löschen kann, bis auf Idle und Walk Die Animation im Leerlauf funktioniert einwandfrei, da die eingegebenen
Regionswerte exakt übereinstimmen, die Walk-Animation
aber
nicht. Deshalb muss ich sie korrigieren, damit sie mit
den Regionswerten für
das Spritesheet übereinstimmt den Regionswerten für
das Spritesheet Ich aktualisiere schnell auf die Werte der eingegebenen Y-Region,
damit diese Animation funktioniert Wir werden die
Hit-and-Dead-Animationen
vorerst ignorieren , da wir sie noch nicht testen
können Der Animationsbaum wird
eine viel einfachere
Zustandsmaschine für diesen Feind benötigen , nicht dieselbe, die der
Spielercharakter benutzt. Also werden wir eine neue
Zustandsmaschinen-Ressource erstellen. Fügen Sie dann die Animationen „Idle“
und „Walk standardmäßig vom
Start zum Leerlauf
übergehen , wenn die
X-Geschwindigkeit nicht Null ist, dann zurück zu Idle, wenn die
X-Geschwindigkeit Null ist Das ist alles, was dieser Feind vorerst tun
muss. Wenn wir uns das
Charakterskript für einen Moment ansehen, das Drehbuch
bereits alles, was wir brauchen, um einen Charakter hin
und her bewegen zu können. Da ich allerdings nicht möchte, dass meine Gegner Kojotenzeit haben, muss
ich entweder jeglichen Code, der sich darauf bezieht
, so
verschieben er nur im Charakterskript des
Spielers enthalten ist,
oder ich kann einfach
sicherstellen, dass der Code, der sich auf
die Kojotenzeit
bezieht, nicht ausgeführt wird,
wenn es keine Coyote-Zeit oder keinen
Coyote-Knoten gibt Da ich bereits
die Funktion get node oder null verwendet habe die Funktion get node oder null um nach dem
Coyote-Timer-Knoten zu suchen, diese Variable Null,
wenn kein solcher Knoten existiert. Das einzige Mal, dass wir
den Coyote-Timer-Knoten verwenden , ist
der Physikprozess,
und wir können einfach
überprüfen, ob es
einen Coyote-Timer-Knoten gibt ,
bevor wir versuchen ihn als Startfunktion aufzurufen
, um Fehler zu Derselbe Prozess könnte auch
verwendet werden , wenn du
nicht alle exakt gleichen Knoten in
deine verschiedenen Charakter- und
Feindeszenen für Dinge wie
Sounds oder Partikeleffekte einbauen exakt gleichen Knoten in
deine verschiedenen Charakter- und möchtest Lasst uns zu einer
unserer bestehenden Rauminhaltsszenen wechseln unserer bestehenden Rauminhaltsszenen und diesen neuen
Feind zum Raum hinzufügen. Mein Plan für diesen Feind ist , ihn hin und
her bewegen zu lassen. Wenn sie gegen eine Wand stoßen,
möchte ich, dass sie sich umdrehen, eine Sekunde
warten und dann
in die entgegengesetzte Richtung gehen. Also bearbeite ich mein
Terrain, um
eine einfache Plattform mit
Wänden auf beiden Seiten zu erstellen . Also wird dieser Feind hier
hin und her rennen. Ich werde auch eine weitere
Plattform ohne Wände hinzufügen, und der Feind sollte in diesem Fall
vom Felsvorsprung weggehen Vielleicht möchtest du
ein anderes Skript schreiben, wie das vom Charakter
erbte Spielercharakterskript, das auch
dieses Verhalten beinhaltet Es ist jedoch besser, sich
dieses Verhalten als
Alternative zum
Spielerknoten in der Spielszene vorzustellen ,
über den der Spieler den Spielercharakter
steuern kann den Spielercharakter
steuern Stattdessen schreiben wir ein Skript das das Verhalten dieses
Feindes kontrolliert. Also werden wir
als Kind des Feindes einen neuen Knoten erstellen. Ich nenne diesen Knoten Pace. Auf diese Weise
kann dasselbe
Verhaltensskript für mehrere
verschiedene Gegner verwendet werden,
und derselbe Feindtyp könnte auch mehrere
verschiedene Verhaltensskripte haben. Wenn dieser Knoten in die eigene Szene des
Feindes aufgenommen wird, wird er automatisch auf
alle Gegner desselben Typs angewendet. Wenn man ihn in die
Rauminhaltsszene einfügt,
kann es sein , dass sich dieselben Gegner möglicherweise
unterschiedlich verhalten. Wir werden ein Skript
an diesen Knoten anhängen und es in einem neuen
Skriptordner für Feinde
ablegen. Um einem
Feind zu sagen, was er tun soll, benötigen
wir einen Verweis auf den Feind selbst, der in einer Variablen
gespeichert ist. Wir können die
Funktion G parent aufrufen , um das direkte Elternteil dieses Knotens zu ermitteln und es
der Variablen mithilfe
des Ready-Tags zuzuweisen . Beachten Sie, dass dies nur funktioniert, wenn der Verhaltensknoten ein
direktes Kind des Feindes ist. Wir sollten auch eine Variable
exportieren, um anzugeben , in welche Richtung sich dieser
Feind zuerst bewegen wird. Also nenne ich sie
Richtung und gebe ihr den Standardwert Eins,
also nach rechts. wir die Prozessfunktion außer Kraft setzen, müssen wir nur die Bewegungsrichtung
des Feindes in
diese Richtung setzen , damit er anfängt
zu laufen Wenn sich der Feind an einer Wand befindet, können
wir dem
Charakter sagen, dass er nach links schauen und seine Bewegungsrichtung
auf Null setzen, sodass er stoppt Um eine kurze
Zeit zu warten, benötigen wir einen Timer. Da dieser Knoten
keinen Typ hat, können
wir diesen Knoten selbst als
Timer verwenden , indem wir seinen Typ
ändern. Der Typ, den dieses Skript erweitert,
muss ebenfalls in
Timer geändert werden, um auf einen
der Timer-Knoten,
Eigenschaften oder Funktionen zugreifen zu können. Wir müssen
das Timeout-Signal nicht verbinden, da wir nur wissen
müssen ob der
Timer gestoppt ist oder nicht Wenn der Timer gestoppt ist, setzen
wir die
Bewegungsrichtung des Feindes in die richtige Richtung Andernfalls können wir ihn auf
Null setzen , da dieser Feind gerade
wartet. Wenn der Charakter auf eine Wand trifft, stellen
wir den
Richtungswert so ein, dass er dem Sinus der Wände X normal ist,
und starten den Timer. Damit der Charakter nach
rechts schaut, wenn er gegen eine
Wand zu seiner Linken
stößt, müssen wir dies auch vom Sinus
der Wände als Normalwert
abhängig machen . Außerdem wollen wir
den Charakter nur anhalten und ihn
umdrehen, wenn seine
aktuelle Bewegungsrichtung nicht der normalen Richtung
der Wände entspricht Wir rufen diese Funktion get Wall normal mehrmals auf, daher wäre es effizienter sie in einer lokalen Variablen
zu speichern Lassen Sie uns hier etwas leichtes
Refactoring durchführen. In der Rauminhaltsszene können
wir die
Wartezeit anpassen und die
One-Shot-Eigenschaft auf true setzen Ich dupliziere den Tempoknoten und füge ihn
dem anderen Feind hinzu. Dann gebe ich meinen beiden Feinden unterschiedliche Werte für ihre
anfängliche Temporichtung Wenn wir nun das Spiel
mit Hilfe unseres
Verhaltensskripts starten , bewegen sich die Gegner, einer nach links und der
andere nach rechts Der zweite Feind verlässt
die Kante,
aber der erste trifft auf die Wand, dreht sich um und
wartet eine Sekunde bevor er sich umdreht und in die andere
Richtung geht Und beide wiederholen
dieses Verhalten. Aber Sie haben vielleicht bemerkt, dass ihre Animationen nicht
immer ihrer Geschwindigkeit entsprechen. Beide Charaktere
animieren tatsächlich synchron Das liegt daran, dass
sie, genau
wie die Gesundheitssymbole, eine Ressource gemeinsam nutzen In der feindlichen Szene müssen
wir den
Sprite Two D-Knoten auswählen und die Atlas-Texturressource
lokal für diese Szene einrichten Jetzt hat jede Instanz
dieses Feindes
ihre eigene Atlas-Textur und wir können
unabhängig voneinander animieren Wenn jedoch eine
Ihrer Animationen die Textureigenschaft
des Sprite-Two-D-Knotens
ändert, kann
dies dazu führen, dass die Animationen, die darauf verweisen
, beschädigt werden Ich lösche diesen Track
aus meiner Reset-Animation. Wir benötigen auch nicht die
Signalverbindung, die aus der
Spielercharakterszene kopiert wurde, die zum
Spielen von Jump Efforts verwendet wird. das Spiel erneut ausführen, können
wir jetzt sehen, dass sie ihre Animationen im Leerlauf und
beim Gehen korrekt abspielen
können. Wir haben jetzt einen Feind, der hin und her laufen und sich an Wänden
umdrehen
kann , aber wir müssen auch sicherstellen, dass
er den Raum nicht verlassen kann. Wir sehen uns
im nächsten Video.
51. 7-2 Unsichtbare Wände: Hallo Freunde. In diesem Video werden
wir verhindern, dass unsere Feinde den Raum
verlassen, in dem sie
erschienen sind Dazu müssen unsere
Feinde
mit unsichtbaren Wänden kollidieren, die den
Spielercharakter nicht beeinträchtigen Wir haben den Körper des
Spielercharakters auf Kollisionsebene neun maskiert das Terrain
auf Ebene eins In unserer Feindeszene setzen
wir die
Körperkollisionsebene auf etwas anderes
wie Ebene 17. Sie müssen immer noch
die Terrainebene maskieren, aber wir werden auch
eine zweite Ebene maskieren lassen , die wir für unsichtbare Wände
verwenden werden. Ich werde Ebene fünf verwenden. Wenn ich die Projekteinstellungen öffne, benenne ich die
Ebene Physik zwei D. Ich nenne Ebene 17 für Feind und Ebene
fünf für unsichtbare Wände. In meiner Raumszene kopiere ich
den Ebenenknoten „Kachelkarte“, der die Karte zeichnet, da dieser bereits die
Grenzen des Raums enthält. Fügen Sie ihn dann in die Inhaltsszene ein und benennen Sie
ihn in Unsichtbare Wände um. die
Layer-Notiz „Kachelkarte“ ausgewählt auf die Ressource „
Kachelset“
klicken, müssen
wir diesem Kachelsatz eine
Physik-Ebene hinzufügen, sich auf Ebene fünf
für unsichtbare Wände befindet. Im Bereich „Kachelset“ können
wir diese
Physikebene auf die Kachel malen. dem Malwerkzeug
und der ausgewählten Kachel zum Bereich „Kachelkarte“ wechseln mit dem Malwerkzeug
und der ausgewählten Kachel zum Bereich „Kachelkarte“ wechseln, können
wir die Türen dieses
Raums schließen und den
Raum auf allen Seiten
vollständig versiegeln, wobei eine Physikebene
nur
von Feinden und nicht
vom Spielercharakter maskiert von Feinden und nicht
vom Spielercharakter Wir wollen nicht, dass diese unsichtbaren Wände auf der Karte gezeichnet werden, also sollten sie sich auch nicht auf
Sichtbarkeitsebene zwei befinden, und wir wollen
sie sehen können, während wir testen Lassen Sie uns sie auf
Sichtbarkeitsebene eins platzieren. Ich bearbeite das Terrain und bewege meine Gegner so, dass sie
sich frei
im gesamten Raum bewegen können . Wenn wir jetzt das Spiel starten, laufen die Gegner
zum Rand
des Raums, werden aber von den Wänden
umgedreht. Während unser Spielercharakter sie direkt durchqueren
kann. Ich würde es vorziehen, wenn sich
diese Wände
außerhalb des sichtbaren
Bereichs des Raums befinden würden , also schiebe ich sie jeweils
um ein weiteres Feld heraus. Alles, was wir tun müssen, um die
Wände für den Spieler komplett unsichtbar
zu machen , ist
ihre sichtbare Eigenschaft auszuschalten, entweder im Szenenbaum
oder im Inspektor Jetzt müssen wir dafür sorgen, dass dieser Feind den Spieler
tatsächlich bedroht, was wir bereits zuvor getan haben Alles, was wir tun müssen,
ist ein Gebiet zum
D-Knoten hinzuzufügen und es Hit Box zu nennen. Geben Sie ihm als Kind dem D-Knoten
eine
Kollisionsform und geben Sie dem
Tut-Knoten der Kollisionsform eine Shape-Ressource. Stellen Sie das Trefferfeld so ein, dass es
die Verletzungsbox des Spielers maskiert. Und es muss überwacht werden. Hängen Sie dann das Hit-Box-Skript an
und verbinden Sie das Signal
im eingegebenen Bereich. A Wenn wir
jetzt das Spiel starten, der physische Kontakt mit verursacht
der physische Kontakt mit
einem Feind, dass der
Spielercharakter Schaden erleidet. Wir werden uns im nächsten Abschnitt
damit befassen,
den Kampf spannender zu gestalten. Lassen Sie uns zunächst mit
diesen Fehlermeldungen umgehen. Diese Fehlermeldungen treten , wenn wir den Inhalt eines Raums laden. Das liegt daran, dass wir
den Rauminhalt
als Reaktion auf
ein Kollisionsereignis laden den Rauminhalt
als Reaktion auf , wenn der
Körper des Spielercharakters einen Raum betritt. Und Godot mag es nicht, wenn wir
weitere Kollisionsbereiche oder Objekte hinzufügen weitere Kollisionsbereiche oder Objekte während er bereits damit beschäftigt ist Kollisionen
für diesen aktuellen Frame zu
lösen Wenn wir also den
Hinweis in den Fehlermeldungen befolgen und
den Befehl „Deferred“
verwenden, wird die Game-Engine
angewiesen, den Inhalt des Raums
zu laden,
nachdem die Kollisionsauflösung
für den aktuellen Frame abgeschlossen ist nachdem die Kollisionsauflösung
für den aktuellen Frame abgeschlossen für den Godot-Zyklus beginnt mit Eingabeverarbeitung,
gefolgt von der Physik, die Kollisionen einschließt,
verarbeitet und endet
mit verzögerten verarbeitet und endet Wir können dies also verwenden, um jede beliebige
Aktion als letztes
vor dem Ende eines Frames Wenn das Spiel erneut ausgeführt wird,
gibt es keine Fehlermeldungen mehr. Unser Feind bleibt jetzt in diesem Raum und kann
den Spielercharakter verletzen. Aber wir müssen unserem Spiel mehr
Feindvielfalt verleihen. Wir sehen uns im nächsten Video.
52. 7-3 Kantenerkennung: Hallo Freunde. In diesem Video fügen
wir einen weiteren
Feind hinzu, der
Keile erkennen und sich umdrehen kann , anstatt
von ihnen wegzulaufen. Wir werden damit beginnen,
unseren bestehenden Feind zu duplizieren. öffnen die feindliche Szene und Wir öffnen die feindliche Szene und ändern den
Namen des Stammknotens so, dass er dem Feind entspricht Importieren Sie ihr Spritesheet und legen Sie es
im Inspektor als Atlas Alle Sprites
für das Spritesheet sind dieselben wie beim ersten Feind, es gibt
also nichts zu korrigieren
, was die Animationen angeht In meiner Rauminhaltsszene entferne
ich die beiden
Gegner und füge diesen neuen Feind hinzu. Dann bearbeite ich das Terrain so, dass sie sich auf
einer erhöhten Terrasse mit
einem Felsvorsprung auf beiden Seiten befinden einer erhöhten Terrasse mit
einem ,
der Ich möchte, dass dieser Feind
am höheren Felsvorsprung anhält, einen Moment
wartet, sich dann
umdreht und in
die andere Richtung läuft Aber dann sollten sie von der kürzeren Kante
weggehen. Was die Mauern angeht, sollten
sie sich
genauso verhalten wie der vorherige Feind Da dieses Verhalten so ähnlich
ist, wäre
es gut, dasselbe Skript zu
verwenden. Also füge ich
als Kind des Feindes eine Timer-Notiz hinzu. Benennen Sie es um, hängen Sie das
Temposkript und setzen Sie seine
One-Shot-Eigenschaft auf true. Dieser Feind sollte sich also
genau wie die blinde Maus verhalten. Jetzt
müssen wir nur noch herausfinden, wann der Feind
auf einen Felsvorsprung zugeht können wir mit
einem neuen Knotentyp tun, einem Cast Two-D-Knoten Wir werden diesen
Knotenkantendetektor nennen. Bewege es dann ein kurzes Stück zur Rechten des Charakters und dann nach oben. Der Strahl hat eine
Kollisionsmaske, die bereits auf
Ebene eins für das Terrain eingestellt
ist. den
Kollisionsbereich erweitern, ist
unser Terrain ein physischer Körper, der Strahl wird
also mit diesem kollidieren Wenn Sie einen
Ray-Cast-Knoten verwenden, um Bereiche zu erkennen müssen
Sie die Bereiche
hier überprüfen, bevor es funktioniert Der Strahlwurf wird
im Editor als Pfeil dargestellt, aber unsichtbar,
während das Spiel läuft, genau wie unsere
Kollisionsbereichsknoten. Er feuert einen Strahl
ab,
der von seiner Position in Pfeilrichtung ausgeht und meldet, ob er auf etwas trifft oder
nicht. In diesem Fall, ob er auf Gelände trifft
oder nicht. Wenn es also auf Gelände trifft, sich
der
Feind weiter vorwärts, und wenn nicht, muss der
Charakter anhalten. Die Entfernung rechts
vom Charakter
bestimmt , wie weit er nach dem Felsvorsprung Ausschau
hält Die Entfernung vom
Boden hat keine große Wirkung solange sie sich über dem Boden
und unter der Körpergröße
des Charakters Die Zielposition sollte
nach unten zeigen , um den Boden zu
erkennen, aber wie weit
der Strahl schießt, beeinflusst was er als
Felsvorsprung betrachtet und was nicht Ich stelle meinen auf eine Tiefe von 64
Pixeln oder zwei Kacheln ein. Das heißt, wenn
der Feind auf
einen Felsvorsprung trifft , der
nur ein Kachel hoch ist, wird
er trotzdem davonlaufen Aber wenn er zwei oder
mehr Steine hoch ist, trifft
der Strahl kein Terrain und der
Feind hält daher Im Gegensatz zu Kollisionsgebieten sendet
der Ray-Cast-Knoten jedoch keine Signale aus, auf die
wir reagieren können. Also müssen wir unser
eigenes Skript an diesen Knoten anhängen. Ich lege es in den Ordner
Enemy Scripts. Wir können damit beginnen,
unser eigenes Signal zu deklarieren, das wir zulassen wollen,
wenn ein Felsvorsprung entdeckt wird, und weiterleiten als
Ganzzahl die
Richtung des Felsvorsprungs
im Verhältnis zum
Feind Es ist allerdings nicht ganz so
einfach, ob der Strahl auf
etwas trifft
oder nicht Ähnlich wie wir dafür gesorgt haben, dass
der Coyote-Timer nur genau dem Frame
startet wenn der Charakter von einem Felsvorsprung
weggeht, wollen
wir eine Kante nur einmal während des exakten Frames erkennen
, wenn der Strahl aufhört, mit
dem Gelände zu
kollidieren exakten Frames erkennen
, wenn der Strahl aufhört, mit
dem Gelände zu
kollidieren Wir benötigen also eine boolesche Variable dafür, ob der Strahl im letzten Frame auf das
Terrain traf oder nicht, und
weitere vier, wenn er in diesem Frame auf Terrain trifft letzten Frame auf das
Terrain traf oder nicht, und
weitere vier, wenn er in diesem Frame auf Terrain weitere vier Während des physikalischen Prozesses setzen
wir was colliding auf
den vorherigen Wert
von is colliding und
dann I colliding auf
den aktuellen Wert, der durch den Strahlwurf
zurückgegeben Wenn der Strahl im
letzten Bild kollidiert , aber nicht mit diesem Bild
kollidiert, ist
dies genau der
Moment, in dem wir eine Kante
erkannt haben und Die Richtung der
Kante kann nur das Zeichen für die
Position
des Knotens sein Zeichen für die
Position
des Knotens Lassen Sie uns unser von der Leiste
erkanntes Signal mit
dem Pace-Skript verbinden und eine Funktion namens
wait and turnaround
aufrufen Wir können diese drei
Zeilen von oben kopieren,
die dem Feind sagen, dass er anhalten soll, die Temporichtung
ändern
und den Timer starten Ersetzen Sie sie dann durch
einen Aufruf unserer Funktion. Aber wir müssen
das Gegenteil der
Wandnormalen X als
Richtungsargument angeben, damit es dem entspricht, was vom Kantendetektor
passiert wird. Der Leistendetektor sendet die
Richtung zur Kante. Hier müssen wir also die
Richtung zur Wand angeben. Die neue
Schrittrichtung ist daher das Gegenteil des
Richtungsparameters Das funktioniert,
solange sich der Feind nach rechts
bewegt,
aber wir müssen den Einsatzknoten
links des
Feindes neu positionieren , wenn er sich umdreht Zum Glück haben wir
bereits jedes Mal
ein Signal ausgegeben , wenn ein
Charakter die Richtung ändert Wir müssen
dieses Signal also nur mit dem
Kantendetektor verbinden , um darauf zu reagieren. Benennen wir es um, wenn der Feind die Richtung
geändert hat. Da wir dadurch
ihre neue Richtung erhalten, setzen
wir die Position des
Knotens einfach auf den absoluten Wert seiner Position,
multipliziert mit minus Eins, falls Richtung kleiner als Null ist,
andernfalls positiv Rückverfolgung dieser
Richtungsänderung signalisiert, dass das Auslassen bis zum
Zeichenskript zurückgeht Ich habe
das ursprünglich geschrieben, indem ich
die Bewegungsrichtungsvariable
als Signalparameter übergeben die Bewegungsrichtungsvariable
als Signalparameter Dies funktioniert jedoch nicht in
dem Kontext, in dem wir diesen feindlichen Charakter
verwenden, da der Wert der
Bewegungsrichtung nicht
unbedingt der Richtung entspricht, in die wir ihnen sagen, dass sie zuschauen sollen. Anstatt die
Bewegungsrichtung zu übergeben, ist
es genauer, eine negative Richtung zu
übergeben, wenn der Charakter
angewiesen wird, nach
links zu schauen, oder eine positive Richtung für rechts. Jetzt befindet sich der
Strahl immer vor
dem Charakter, egal ob er
nach links oder rechts schaut. Lassen Sie uns die sichtbaren
Kollisionsformen einschalten, damit wir den Strahlwurf
sehen können , während das
Spiel läuft, und drücken Sie auf Play. Der Strahlwurf wird
rot dargestellt , wenn er
mit etwas kollidiert Unser Feind nähert sich
dem ersten Felsvorsprung. Der Strahl färbt sich blau, um anzuzeigen,
dass er nichts
trifft Der Feind hält
für kurze Zeit an, dreht sich
dann um und
geht in die andere Richtung Nähert man sich
dem kürzeren Felsvorsprung, ist
der Strahlwurf
so lang , dass er immer noch das Terrain
trifft, sodass der Feind davonläuft und in
dieselbe Richtung weitergeht Schließlich treffen sie auf die
unsichtbare Wand am äußersten Rand des Raums und drehen sich
wie der vorherige Feind um. Wir haben jetzt einen zweiten Feindtyp , der sich
anders verhält als der erste, aber wir brauchen viel mehr Abwechslung,
damit unser Spiel Spaß macht Wir sehen uns im nächsten Video.
53. 7-4 Fliegen: Hallo Freunde. In diesem Video fügen
wir einen fliegenden Feind hinzu
, der durch einen Raum springt Beginnen wir mit dem Import eines neuen Spritesheets
für den fliegenden Feind Dann duplizieren Sie eine
der vorhandenen feindlichen Szenen. Nachdem wir die
neue feindliche Szene geöffnet
haben, benennen wir den Stammknoten
entsprechend um und tauschen
den Atlas durch das
richtige Spritesheet aus den Atlas durch das
richtige Spritesheet Diese Sprites haben
im Gegensatz zu den anderen Gegnern bisher eine Größe von
32 Pixeln im Quadrat im Gegensatz zu den anderen Gegnern bisher eine Größe von
32 Pixeln im Deshalb passe ich jetzt die Y-Position des Sprites an, um sie etwas
abzusenken Dieser Feind hat keine separaten Animationen im Leerlauf und
beim Gehen Deshalb entferne ich die
Walk-Animation und bearbeite die Idle-Animation , sodass sie die richtige
Anzahl von Frames hat Bearbeiten Sie dann die eingegebenen Werte für die Animation im Leerlauf so, dass sie
die richtige Pixelhöhe Jetzt
sieht die Animation im Leerlauf korrekt aus. Wenn ich die Sichtbarkeit
der Kollisionsform des Charakters aktiviere, drehe
ich sie um 90 Grad, sodass
die Kapsel waagerecht ist, drehe
ich sie um 90 Grad, sodass
die Kapsel waagerecht ist,
was der Form
dieses Feindes besser
entspricht , und passe
Radius und Höhe nach Bedarf an. Machen Sie dann dasselbe
mit der Hurt-Box. Und die Trefferbox mit Kontaktschaden. Achten Sie darauf, dass sie der
Größe und Form des Feindes entspricht, damit sich jeder Schaden,
der dem Spieler zugefügt wird, fair anfühlt Was die
Animationsbaum-Zustandsmaschine
angeht, da es momentan nur eine
Animation gibt, braucht
sie nur einen
Ruhezustand, der
von Start zu Inaktivität übergeht von Start das Skript angeht, das an den Wurzelknoten dieses
Feindes
angehängt ist, so brauchen
wir diesen
Feind nicht, um zu laufen oder zu springen, aber wir brauchen trotzdem, dass dieser Feind in der Lage ist, nach
links oder rechts zu schauen, beschleunigen
und zu bremsen, von der Schwerkraft und der
Endgeschwindigkeit beeinflusst zu
werden usw. Es hat also genug
Vorteile, hier immer noch
das gleiche Zeichenskript zu verwenden hier immer noch
das gleiche Zeichenskript anstatt bei Null anzufangen Aber das Verhalten
eines Feindes ,
der
fliegen kann, ist so unterschiedlich, dass wir
eine neue Unterklasse schreiben sollten , die vom Charakter
erbt Lassen Sie uns also ein neues
Skript namens Flying Enemy erstellen, vom Charakter
erbt, und speichern wir es im Ordner Enemy Unser fliegender Feind
braucht eine Richtung, um fliegen zu können. Im Gegensatz zum Gehen oder Laufen, das als Schwebe dargestellt wird, da es sich nur um die X-Achse
kümmern muss, kann
eine Flugrichtung eine
beliebige Richtung bis zum D-Raum sein, also speichern wir sie
in einem Vektor zwei. Wir benötigen außerdem eine
boolesche Variable, um zu wissen, ob dieser
Feind gerade fliegt oder nicht Wir können dann
den physikalischen Prozess überschreiben eine
neue Prüfung hinzufügen, um zu sehen,
ob der Feind fliegt, und wenn ja, eine fliegende
Physikfunktion aufrufen Wenn der Feind nicht fliegt, können wir die
Superklassen-Definition
des physikalischen
Prozesses als normal bezeichnen . Vielleicht möchtest du auch
eine Fluggeschwindigkeit als Float exportieren,
wenn du
einen Feind haben möchtest, der
unterschiedliche Geh
- und Fluggeschwindigkeiten hat . Ich gebe ihm einen Standardwert
von 100 Pixeln pro Sekunde. Ich halte die Strg- oder Befehlstaste gedrückt und klicke auf
diesen Funktionsaufruf des
Superclass-Physikprozesses, um direkt zu
seiner Deklaration zu gelangen , sodass wir uns ansehen
können,
was er enthält Beachten Sie, dass sich der Funktionsaufruf von move and
slide
innerhalb der Superklassendefinition
unseres physikalischen Prozesses befindet innerhalb der Superklassendefinition
unseres physikalischen Prozesses Diese Funktion muss aufgerufen
werden, um den Körper
des Charakters auf die Geschwindigkeit von Dnode
anzuwenden und Kollisionen zu prüfen Wir wollen auch weiterhin, dass
unser fliegender Feind in die Richtung schaut, in die
er Also müssen wir das in
der Flugphysik-Funktion machen. Ich kopiere diesen Codeblock
und kehre zum Flying Enemy-Skript zurück und füge ihn in meine Flugphysik ein. Anstatt den
Wert der Bewegungsrichtung zu überprüfen, müssen
wir den Wert
von Flugrichtungspunkt X überprüfen Außerdem müssen
wir
weiterhin die Bewegungs- und
Gleitfunktion aufrufen , wenn
der Feind fliegt. Wir können dann eine ähnliche
Logik, die wir für die
Luftkontrolle verwendet haben, auf unsere
nicht fliegenden Charaktere anwenden Luftkontrolle verwendet haben, auf unsere
nicht fliegenden Charaktere , um unseren fliegenden Feind zum Fliegen zu bringen. Wenn die Flugrichtung einen Wert hat, bewegen
wir die Geschwindigkeit des
Feindes
in Richtung der Flugrichtung
multipliziert mit der Fluggeschwindigkeit in Richtung der Flugrichtung
multipliziert mit der Fluggeschwindigkeit zwar bei einer
Beschleunigungsrate multipliziert mit
der Beschleunigungsrate multipliziert mit Luftkontrolle
multipliziert mit Delta Oder wenn keine
Flugrichtung angegeben ist, können
wir ihre Geschwindigkeit mit
einer Geschwindigkeit von Verzögerung multipliziert mit Luftbremsen
multipliziert mit Delta in
Richtung Vektor zwei Punkt Null bewegen einer Geschwindigkeit von Verzögerung multipliziert mit Luftbremsen multipliziert O. Als wir
nur Velocity Punkt X bearbeitet haben, was ein Float ist, ein
primitiver Datentyp, mussten
wir Godot move
toward function aufrufen, um toward function Aber da ein Vektor
Zwei eine Klasse ist, kann
er seine eigenen Funktionen haben - oder Befehlstaste gedrückt halten und auf
den
Klassennamen
klicken , gelangen
wir
zur Dokumentation für diese Klasse, in
der wir bei Bedarf alle ihre Eigenschaften
und Funktionen einsehen können . Hier haben wir also die Möglichkeit velocity
dot move toward
aufzurufen, was sich von der
Godot-Funktion move
toward dadurch unterscheidet , dass der
erste Parameter bereits als
der Vektor selbst bekannt
ist Möglicherweise möchtest du auch verschiedene Werte
für Flugbeschleunigung,
Verzögerung,
Luftsteuerung und Luftbremsen
für deine fliegenden Gegner
exportieren für Flugbeschleunigung,
Verzögerung, , wenn du möchtest, dass sie unterschiedliche Werte
verwenden, während sie Außerdem benötigen wir eine
öffentliche Funktion , die diesem Feind mitteilt, dass er fliegen soll ein Vektor-Zwei-Parameter
für die Flugrichtung
akzeptiert für die Flugrichtung Und noch einen für den Zeitpunkt,
an dem wir aufhören sollen zu fliegen. Dadurch wird die
Flugvariable gesteuert und gleichzeitig die
Flugrichtung festgelegt. Denken Sie daran, dieses
fliegende Feind-Skript
an den Wurzelknoten des
Feindes in seiner eigenen Szene anzuhängen . In der Rauminhaltsszene unserem neuen fliegenden Feind tun,
genauso wie unsere bestehenden Feinde einen separaten Knoten
haben, der ihnen
sagt, wie sie sich verhalten sollen werden
wir dasselbe
mit unserem neuen fliegenden Feind tun,
genauso wie unsere bestehenden Feinde einen separaten Knoten
haben, der ihnen
sagt, wie sie sich verhalten sollen. Ich lösche diesen
Feind aus der Szene und füge zwei dieser
neuen fliegenden Feinde hinzu. Dann bearbeite ich das Terrain so
, dass es einen von ihnen
in eine Geländebox einschließt , damit wir sehen können, wie es
sich etwas einfacher verhält Ich möchte, dass diese Fledermäuse in
diagonaler Richtung fliegen und von jeder Wand,
Decke oder jedem Boden
abprallen , mit denen sie in
Kontakt kommen also beiden einen
Basisknoten anhänge, nenne ich ihn Ricochet Hängen Sie dann ein Skript an diesen Knoten an und speichern Sie es im
Ordner Enemy Dieses Skript benötigt
eine exportierte Variable für die anfängliche Flugrichtung. Ich verwende den Vektor 21
, der sich unten rechts befindet. Wir benötigen außerdem einen
Verweis auf den Feind , dessen Verhalten wir
kontrollieren, auf diesen Knoten gesetzt, Elternteil den Tag on ready verwendet. die Bereitschaftsfunktion außer Kraft zu
setzen, wäre es eine gute Idee, die Flugrichtung zu
normalisieren Durch die Normalisierung eines Vektors wird
sichergestellt , dass er eine
Länge von genau eins hat Da ein Vektor mit einem Wert
von 11 länger als eins ist, würde
dies dazu führen, dass die Fledermaus schneller als
ihre Fluggeschwindigkeit fliegt Aber wenn wir den Vektor normalisieren, verwenden
wir nur die
Richtung des Vektors, nicht seine Länge. Indem wir die Prozessfunktion außer Kraft
setzen, können wir dem Feind sagen, dass er in die gewünschte
Flugrichtung fliegen soll in die gewünschte
Flugrichtung fliegen Aber bevor wir das tun,
müssen wir überprüfen, ob dieser Feind
gerade Kontakt mit einer
Wand, Decke oder einem Boden In jedem dieser Fälle können wir dann den Punkt X oder
Punkt und Y für die
Flugrichtung auf den entsprechenden
Wert setzen. Für die Decke entspricht
der Wert dem absoluten Wert des
Flugrichtungspunktes Y, sodass er immer
positiv ist, also nach unten. Beim Boden ist das Gegenteil der Fall, der absolute Wert
mit dem negativen Wert multipliziert wird, also
nach oben Bei Wänden können wir einfach den absoluten Wert des Punktes X in
Flugrichtung mit dem
Vorzeichen des Wandnormalpunkts X
multiplizieren , der von der Wand weg zeigt Ich hänge das
Ricochet-Skript
auch dem anderen Feind an und drücke dann auf Play Wenn wir das Spiel ausführen, können wir sehen, dass die Fledermaus herumspringt und von
allen Wänden
, Decken
und Böden abprallt, die sie berührt, wodurch
ein interessantes Hindernis
entsteht, ein interessantes Hindernis Wir haben jetzt einen fliegenden
Feind, den wir bekämpfen müssen, aber wir sollten mindestens
einen weiteren Feindtyp haben , mit dem sich unsere
Spieler auseinandersetzen Wir sehen uns im
nächsten Video.
54. 7-5 Kriecheln: Hallo Freunde. In diesem Video machen
wir uns einen Feind, der auf jeder Oberfläche
kriechen kann, auch an Wänden und Decken Beginnen wir mit dem Import eines
Spritesheets für diesen Feind. Dann duplizieren Sie den fliegenden Feind. Nachdem ich die
neue feindliche Szene geöffnet
habe, benenne ich den Stammknoten um. Tauschen Sie dann die Atlas-Textur
des Sprite-Atlas mit zwei
D-Knoten gegen das entsprechende
Sprite-Blatt Im Animation Player des Feindes aktualisiere
ich die Animation im Leerlauf
, sodass sie
die korrekte Anzahl
von Frames enthält, die das
Spritesheet zur Verfügung
stellt Aktualisierung der eingegebenen
Regionswerte nach Bedarf. Da wir wollen, dass dieser
Feind
nicht nur auf dem Boden, sondern auch auf den Wänden und
der Decke kriecht , wäre
es hilfreich, wenn
wir den Feind rotieren Da der Feind seinen
Ursprung zu Füßen hat, so wie wir
jeden anderen Feind geschaffen haben, wird seine
Rotation
alles um diesen Punkt Um die Sache ein wenig einfacher zu machen, wäre
es besser, den Ausgangspunkt kriechender Gegner in ihrer Mitte zu platzieren, damit
diese Rotationen flüssiger aussehen Also werde ich das
Sprite und alle Kollisionsformen so
zentrieren , dass sie am Ausgangspunkt
zentriert sind Wenn wir diesen Feind nun drehen, bleibt
er in
derselben relativen Position Ich werde die Hurt-Box und
die
Trefferbox schnell anpassen , damit sie besser
zur Form dieses Feindes passen. Für die Kollisionsform des Charakters verwende ich
jedoch
eher einen Kreis als eine Kapsel. Da dieser Feind rotieren kann, die Kollisionsform, dass
es bedeutet
die Kollisionsform, dass
es sich bei der Kollisionsform um
einen Kreis , bewirkt handelt,
keine Änderung der Art und
Weise, mit der der Feind
kollidiert Wenn du strikte
90-Grad-Drehungen verwendest, würde auch
eine quadratische
Kollisionsform funktionieren, aber
bei konvexen Ecken wären
einige zusätzliche Schritte erforderlich bei Also bleibe ich bei der Verwendung eines Kreises. In der Szene mit dem Rauminhalt entferne
ich die Fledermäuse und
ersetze sie durch zwei Schnecken Das Ziel ist, dass diese
Schnecken
sowohl auf der Innen- als auch auf der
Außenseite dieser Kiste herumkrabbeln sowohl auf der Innen- als auch auf der
Außenseite So wie wir
ein neues Skript erstellt haben, das vom Charakter
für fliegende Feinde übernommen wurde, schreiben
wir ein anderes für kriechende Feinde und speichern es im Ordner Feindliche
Skripte Ersetze dann das an den Feind
angehängte Skript durch dieses neue Ich werde meine
Schnecke verlangsamen, indem ihre Gehgeschwindigkeit auf nur
32 Pixel pro Sekunde setze Zuerst müssen wir
die Richtung zur Oberfläche, auf
der
dieser Feind gerade
kriecht, als Vektor zwei kennen die Richtung zur Oberfläche, auf
der
dieser Feind gerade
kriecht, als Vektor Dann auch die
Vorwärtskriechrichtung als weiterer Vektor zwei Wir müssen hier auch unsere eigenen Kollisionen regeln,
anstatt uns
darauf zu verlassen , dass die Bewegungs- und Gleitfunktion
des Charakters die gesamte Physik für uns erledigt Wir können also
Kollisionsdaten in einer anderen Variablen
vom Typ kinematische Kollision zwei
D speichern vom Typ kinematische Kollision zwei . Indem wir den
physikalischen Prozess außer Kraft
setzen, prüfen wir, ob dieser Feind gerade an einer Oberfläche feststeckt,
und wenn ja, rufen wir den physikalischen
Prozess für das Wenn sie nicht an einer Oberfläche
haften, können
wir den physikalischen Prozess der Superklasse nennen Das funktioniert, weil ein Vektor zwei mit seinen Standardwerten Null, Null
von der if-Anweisung
als falsch und jeder
andere Wert als wahr behandelt wird als falsch und jeder
andere Wert als wahr Wenn sie nicht an einer Oberfläche
haften, werden
wir auch prüfen wollen, ob dieser Feind auf einer Oberfläche
haften kann. Wenn wir eine etwas andere Funktion als Move und Slide aufrufen, rufen
wir Move and Collide Diese Funktion akzeptiert die Bewegung der Figur als
ersten Parameter, h. ihre Geschwindigkeit
multipliziert mit Delta Die Funktion gibt eine
kinematische Kollision zwei D zurück, die wir unserer Variablen
zuweisen können Ähnlich wie unser Vektor zwei in
einer if-Anweisung verwendet werden kann, können
auch diese Kollisionsdaten Wenn keine Kollision aufgetreten
ist, wird sie als falsch betrachtet. Und wenn es zu einer Kollision gekommen
ist, wird sie als wahr angesehen. Wenn dieser Feind mit etwas
kollidiert ist, gehen wir davon aus, dass
er
sich daran halten möchte, und legen den Wert „An
der Oberfläche kleben “ fest Wir können auf
normale Kollisionen zugreifen , indem wir die Funktion
get normal aufrufen Das ist ein Vektor, der von der Oberfläche
wegzeigt, mit
der der Charakter
am Kollisionspunkt kollidiert Da wir möchten, dass der Wert dieser Variablen zur Oberfläche
zeigt nicht von ihr weg,
können wir sie einfach um 180 Grad drehen und
die gedrehte Funktion aufrufen Aber Rotationen in Godot verwenden
keine Grade. Sie verwenden Radiant, und 180 Grad
entspricht Pi-Radiant Oh, wenn der Feind mit keiner Oberfläche
kollidiert ist, dann sprechen wir von einem physikalischen Prozess der
Superklasse Aber der
physikalische Prozess der Superklasse
wendet auch die Geschwindigkeit des
Charakters wenn er Move und Slide aufruft Gemäß diesem Code wird die Geschwindigkeit der
Figur zweimal in jedem Frame
angewendet solange sie keine Oberfläche
berührt Wir können dies beheben, indem wir
einen zweiten optionalen Parameter
an die Funktion Move and
Collide übergeben einen zweiten optionalen Parameter , sich um einen booleschen Test handelt Wenn der Wert wahr ist, sucht
diese Funktion nur
nach Kollisionen, bewegt den Charakter aber nicht
. Jetzt, da unser Feind
automatisch an einer beliebigen Oberfläche haften bleibt, können
wir uns mit der Physik des Krabbelns auf dieser Oberfläche befassen Zuerst wenden wir die Schwerkraft auf die Oberfläche an, an
der der Feind feststeckt, da wir das vorher nicht für
den Kollisionstest gemacht haben. Das hilft auch, den Feind auf der Oberfläche
zu halten , auf der er kriecht bewegen und kollidieren aufrufen, die
Richtung zur Oberfläche wechseln,
multipliziert mit der Schwerkraft,
multipliziert mit Delta, unsere Kollisionsdaten nun die Kollision enthalten
unsere Kollisionsdaten nun die Kollision mit der Wir können uns dann danach verzweigen,
ob eine
Kollision stattgefunden hat oder nicht Falls sich der Winkel
der Oberfläche geändert hat, können
wir die
Richtung zur kriechenden Oberfläche aktualisieren und
dann die Vorwärtsrichtung berechnen handelt es sich lediglich um die um 90 Grad gedrehte
Richtung zur Oberfläche Wenn Pi 180 Grad beträgt, dann ergibt Pi geteilt durch
zwei 90 Grad. Die Drehrichtung
hängt jedoch
davon ab , ob der Feind
nach links oder rechts schaut. Wenn sie nach links zeigen, müssen wir uns im Uhrzeigersinn
drehen Wenn sie nach
rechts zeigen, drehen wir Uhrzeigersinn, um ihre
Vorwärtsrichtung als Vektor zwei Und wenn sich diese Werte seit dem
vorherigen Frame
geändert haben , müssen
wir auch
die Rotation des Feindes aktualisieren, um sie in die richtige Richtung
zu zeichnen Da der Feind in seiner Szene
mit einer Drehung um
Null nach rechts schaut, müssen wir nur
die Vorwärtsrichtung verwenden und dann die Winkelfunktion
aufrufen. Die Winkelfunktion
gibt den Winkel zwischen einem
beliebigen Vektor zwei und
der positiven X-Achse zurück . Aber da wir die
negative X-Skalierung verwenden um den Charakter umzudrehen,
wenn er nach links zeigt, müssen
wir das auch bei der Drehung korrigieren
,
indem wir ihn um weitere 180 Grad oder Pi-Radiant drehen, wenn der
Feind nach links schaut Jetzt, wo der Feind an der Oberfläche
feststeckt
und wir wissen, in welche Richtung er
kriechen will, können
wir, wenn dem Feind gesagt
wird, dass er sich bewegen soll, wenn dem Feind gesagt
wird, dass er sich bewegen soll, endlich
wieder die
Bewegungs- und Kollisionsfunktion verwenden , um ihn in
seine Vorwärtsrichtung zu bewegen, multipliziert mit der
Bewegungsgeschwindigkeit, multipliziert mit Delta. Falls es aufgrund dieser Bewegung zu
einer Kollision kommt, bedeutet das, dass er mit einer konkaven Ecke kollidiert Alles, was wir hier tun müssen, ist Richtung
zur
neuen Oberfläche neu zu berechnen Der nächste Physik-Frame
erledigt den Rest. Wenn es keine Kollision gab, kriecht der Feind
sanft über eine ebene oder konvexe Oberfläche Wenn keine
Bewegungsrichtung angegeben wurde, bleiben
sie still Gehen wir zurück zur ersten WF-Aussage:
Wenn
die Schwerkraft zur Oberfläche nicht zu einer Kollision geführt hat, bedeutet
das, dass der Feind irgendwie den Kontakt zu der Oberfläche
verloren hat , auf der
er gekrochen Also sollten wir eine
Funktion aufrufen, die sie wieder auf eine
normale Ausrichtung
zurücksetzt Ich nenne es Unstick und mache es öffentlich, damit
andere Skripte es aufrufen können Diese Funktion setzt
die Richtung zur
Oberfläche zurück Vektor 20 und die
Drehung auf Null, sie
wieder in einen
Verhaltenszustand versetzt werden, der genau
wie bei jedem anderen Feind ist In unserer kriechenden
Physik
fehlt jedoch immer noch eine Sache , nämlich
dem Feind zu sagen, dass er in die Richtung
schauen soll , in die er
sich bewegt, da das im Prozess
der Superklassenphysik gemacht wurde der Superklassenphysik Anstatt den gleichen Code hier
zu kopieren und einzufügen, verschieben
wir ihn in
eine private Funktion in der Dann können wir diese Funktion sowohl
in diesem Zeichenskript als auch im Crawling
Enemy-Skript aufrufen sowohl
in diesem Zeichenskript als auch im Crawling
Enemy-Skript auch im Crawling
Enemy-Skript Anstatt
einen separaten Knoten
und ein separates Skript zu erstellen , um
diesem Feind einfach mitzuteilen, dass er kriechen soll, exportiere
ich eine Integer-Variable
für die Krall-Richtung Dann überschreiben Sie die
Prozessfunktion und machen Sie es hier. Zu Testzwecken überschreibe ich
auch die
Eingabefunktion, überschreibe ich
auch die
Eingabefunktion sie mit
dem Abwärtspfeil gezwungen werden, sich von der
Oberfläche zu lösen, auf der sie kriechen Wenn wir das Spiel ausführen, kriecht die
Schnecke um diese Kiste herum
und
dreht sich sowohl an den konkaven als auch an den konvexen Ecken, dreht sich sowohl an den konkaven als auch an den konvexen um an die Wände zu klettern und wieder an der Decke den Abwärtspfeil drücken
, lösen sie sich von der Oberfläche und fallen der Schwerkraft
zu Wir haben jetzt unseren
letzten Feindtyp,
einen, der an
Wänden und Decken kriechen kann Aber unsere Feinde sollten
aggressiver gegenüber
dem Spielercharakter Wir sehen uns im nächsten Video.
55. 7-6 Sehkraft: Hallo Freunde. In diesem Video geben
wir einigen unserer
Feinde die Möglichkeit, die Präsenz des wahrzunehmen und darauf zu
reagieren Spielercharakters
wahrzunehmen und darauf zu
reagieren. In der Szene mit dem Rauminhalt entferne
ich die Schnecken
und die Kiste mit dem Gelände Ersetze es durch einen
Block auf zwei Seiten füge dann eine Mausnotiz ein , die zwischen ihnen hin und
her wechselt. Ich füge den Timer-Knoten hinzu, hänge das Pace-Skript an und setze dessen
One-Shot-Eigenschaft auf true. Damit dieser Feind
aggressiv auf
den Spielercharakter reagieren kann, muss
er ihn aufspüren können. Um dies zu erreichen, müssen wir mehrere
Tools verwenden. Zuerst fügen wir unserem Feind einen D-Node der
zweiten Zone hinzu. Und einen
Kollisionsformknoten für das Gebiet. Dieser Bereich repräsentiert den gesamten Sichtbereich des
Feindes. Vielleicht möchtest du
ein um
45 Grad gedrehtes Quadrat, eine
Kapsel oder einen Kreis verwenden 45 Grad gedrehtes Quadrat, eine . Wenn Sie ein Kollisionspolygon mit
zwei D-Knoten anstelle eines
Kollisionspolygons mit zwei D-Knoten verwenden , können
Sie tatsächlich
ein benutzerdefiniertes Polygon erstellen,
anstatt voreingestellte Formen können
Sie tatsächlich
ein benutzerdefiniertes Polygon erstellen zu verwenden Klicken Sie einfach in den Editor, um jeden Scheitelpunkt
der gewünschten Form zu zeichnen Auf diese Weise können wir
ein Dreieck oder einen Fächer erstellen, wodurch ein Sichtfeld besser dargestellt
wird die
Polygoneigenschaft im Inspektor erweitern, können
wir die Positionen
der einzelnen Scheitelpunkte sehen, sie
bearbeiten und bei Bedarf neu anordnen. Für welche Form Sie sich auch
entscheiden, achten Sie
darauf, dass Ihre Form nur konvexe
Winkel hat Wenn Ihr Polygon konkav ist, teilt
Godot es in mehrere kleinere
konvexe Formen auf und verdoppelt dadurch die Kosten für
Kollisionsberechnungen Wenn Sie sich
jedoch für
eine normale symmetrische
Kollisionsform entscheiden , ist es viel einfacher, den Feind nach
links und rechts umzudrehen ,
da Sie einfach dieselbe Methode
verwenden können, die wir beim
Kantendetektor-Cast verwendet haben, und seine Positionseigenschaft
jedes Mal
einstellen, wenn der seine Positionseigenschaft
jedes Mal
einstellen jedes Mal Beim
Kollisionspolygon mit zwei D-Knoten ist der Vorgang
jedoch
etwas komplizierter Wir können seine Position nicht einfach verschieben, und wir sollten auch
seine Skalierungseigenschaft nicht ändern Wenn wir die Dokumentation
für diesen Knoten öffnen, ausdrücklich
davor
gewarnt angegeben, dass er sich
wahrscheinlich nicht wie erwartet verhalten wird. Wenn wir uns dafür entscheiden,
diese Kollisionspolygone für
unsymmetrische Formen zu verwenden diese Kollisionspolygone für ,
die
wir umdrehen müssen, müssen wir
die Positionen
der einzelnen Scheitelpunkte in unserem Skript manuell bearbeiten die Positionen
der einzelnen Scheitelpunkte in Das Sichtfeld allein wird
jedoch nicht
ausreichen, da
nichts es daran hindert, Wände zu
durchdringen Wenn wir wollen, dass der Feind
den Spieler mit
ungehinderter Sichtlinie entdeckt , benötigen
wir einen weiteren Knoten, um zu überprüfen
, ob ein Strahl zwei D-Knoten wirft Du solltest ihn in der Nähe der Augen des
Feindes
positionieren, von wo aus er eigentlich
zuschauen Augen des
Feindes
positionieren, von wo würde, aber ihn horizontal zentriert
halten Ich benenne das
in Sichtlinie um. Die Sichtlinie
wird
sowohl mit dem Gelände als auch mit dem Körper des
Spielercharakters kollidieren , die
beide Körper sind Dadurch kann das Gelände
ihre Sichtlinie blockieren, selbst wenn sich der Spielercharakter in ihrem Sichtfeld
befindet Wenn das Sichtfeld ausgewählt ist, benötigen
wir es nur zur Überwachung und
zum Maskieren des Körpers des Spielers Ich entferne den Formknoten und verwende das Polygon
einfach
als Kollisionsbereich Dann gib ihm und
dem Darsteller eindeutige Namen. ein Skript an den
Sichtfeldbereich anhängen, speichern wir es
im Ordner Enemy Scripts Lassen Sie uns mithilfe des
Ready-Tags Verweise auf die Form oder den
Polygonknoten und den
Sichtlinienknoten abrufen den
Polygonknoten und den
Sichtlinienknoten Ready-Tags Verweise auf die Form oder den
Polygonknoten und den
Sichtlinienknoten Ich wünsche mir von diesem
Aufbau, dass der Feind auf den
Spielercharakter reagiert, nachdem beide das Sichtfeld betreten
haben und der Feind eine direkte
Sichtlinie zum Spieler hat Wenn der
Spielercharakter beide
das Sichtfeld verlässt und die
Sichtlinie unterbrochen
wird, möchte ich, dass der Feind zu seinem normalen Verhalten
zurückkehrt Überlegen Sie, wie wir
wollen, dass dieser Knoten über Signale mit anderen
Knoten
kommuniziert Wir benötigen diesen Knoten
, um zwei Dinge zu melden , wenn der Feind
ein Ziel erreicht hat und wenn er sein Ziel verloren
hat. Das werden genau die Momente sein denen wir
ihr Verhalten von
ihrem voreingestellten Hin
- und Her-Tempo ändern und
ihnen stattdessen sagen wollen ihrem voreingestellten Hin
- und Her-Tempo ändern und
ihnen stattdessen sagen , dass sie
aggressiver handeln sollen oder umgekehrt Wir können die Signale, die der
Körper betreten hat, und die vom Körper
ausgehenden Signale aus dem
Sichtfeld mit dem Drehbuch verbinden ausgehenden Signale aus dem
Sichtfeld Und das
sagt uns ganz einfach , wann der
Spielercharakter das Sichtfeld betritt und verlässt Wir müssen das in
einer Variablen namens target speichern. Da der Parameter ein D ohne zwei
ist, setzen
wir den Variablentyp
auch auf ein D ohne zwei, um die Dinge einfach zu
halten. Wir benötigen außerdem eine
boolesche Variable dafür ob der Feind
gerade anvisiert oder nicht, ob sich das Ziel
gerade im
Sichtfeld befindet und ob der Feind derzeit
Sichtlinie zum Ziel hat Wenn ein Körper
das Sichtfeld betritt, dann setzt man sein Sichtfeld auf true und setzt das Ziel auf Wenn der Körper
das Sichtfeld verlässt, können
wir ihn wieder auf Falsch setzen. Denken Sie daran, dass wir nur den Spielercharakter
maskieren, sodass wir bereits wissen, dass dieser Körper der
Spielercharakter ist den physikalischen Prozess außer Kraft setzen, ,
wenn es noch kein Ziel können
wir einfach zurückkehren,
wenn es noch kein Ziel gibt, da
es nichts zu tun gibt Jetzt können wir davon ausgehen, dass
der Spielercharakter das
Sichtfeld mindestens einmal betreten
hat Als Nächstes richten wir die
Sichtlinie auf das Ziel. Wir können einen Vektor erzeugen, der von A
nach B
zeigt , indem wir A von B subtrahieren Die Zielposition
des Raycasts ist
also die des Ziels
abzüglich unserer globalen Position Dann ist der Wert von ist in Sichtlinie
wahr, wenn das, worauf der Collider trifft, mit dem Ziel
identisch ist Wenn der Strahl auf
Gelände trifft oder gar nichts
trifft,
ist das falsch Beachten Sie, dass
Kollisionen bereits von Godot berechnet
wurden, wenn der
physikalische Prozess stattfindet Kollisionen bereits von Godot berechnet
wurden Wenn wir also die
Sichtlinie auf den
Spielercharakter in der obigen Zeile richten, die resultierenden Kollisionsdaten erst im nächsten Frame verfügbar Was wir hier überprüfen, sind die Kollisionsergebnisse
aus dem vorherigen Frame. Wenn
Sie aus irgendeinem Grund unbedingt sofortige
Aktualisierung eines Casts
benötigen, können
Sie dessen Force-Funktion
RycastuDate aufrufen das Spiel jedoch mit 60 Bildern pro
Sekunde läuft, wird
die Verzögerung nicht spürbar sein und das Spiel wird so wie es ist
einwandfrei funktionieren Jetzt müssen wir nur noch
unsere Signale zur
richtigen Zeit aussenden . Wenn der Feind
gerade nicht
anvisiert, sich das Ziel aber in
seinem Sichtfeld befindet und er
Sichtlinie zum Ziel
hat, dann wurde das Ziel erfasst. Also setzen wir die Zielerfassung auf Wahr“ und senden das
empfangene Zielsignal aus, wobei wir das Ziel
als Argument weitergeben. Und im völlig
gegenteiligen Szenario, wenn sie gerade zielen, aber das Ziel nicht
in ihrem
Sichtfeld ist und sie keine Sichtlinie
haben, dann haben wir das Ziel verloren. In diesem Fall wäre es
auch eine gute Idee, den Wert von
Target wieder auf Null
zu setzen, wodurch der physikalische
Prozess daran gehindert wird, weitere
Überprüfungen vorzunehmen, bis sie
wieder in das Sichtfeld gelangen. Lassen Sie uns auch ausdrucken, wann diese Ereignisse eintreten, damit
wir sie testen können. Das Letzte, was wir tun
müssen, ist
unser Kollisionspolygon umzudrehen , wenn
der Feind die Richtung ändert. Das können wir tun, indem wir
das geänderte
Richtungssignal mit unserem Skript verbinden das geänderte
Richtungssignal mit unserem Skript Wenn du eine
symmetrische Form verwendest, musst du
sie nur auf der anderen Seite
des Charakters neu positionieren sie nur auf der anderen Seite
des Charakters Aber ich verwende ein Polygon,
was bedeutet, dass ich die einzelnen Scheitelpunkte bearbeiten
muss Ich beginne damit,
das bestehende Array
aus dem Polygon abzurufen und es in einer Variablen zu
speichern Der Typ ist ein gepacktes
Vektor-Zwei-Array. Ich kann dann durch
jeden der Scheitelpunkte iterieren und dieselbe Strategie anwenden , um ihre Exposition auf die andere Seite
des Charakters
umzukehren , wenn sie
nach links
zeigen Die Anordnung der
Scheitelpunkte,
die das Polygon hier bietet , ist nur eine Kopie, nicht Wenn wir die Werte bearbeiten,
hat das also keine Auswirkungen auf
das Kollisionspolygon Damit die Änderungen
tatsächlich funktionieren, müssen
wir
das bestehende Array
mit der bearbeiteten Kopie überschreiben das bestehende Array
mit der bearbeiteten Lassen Sie uns sichtbare
Kollisionsformen
im Debug-Menü einschalten und es ausprobieren Wir können sehen, wie unser Feind zwischen den beiden Wänden
hin und her läuft, und
das Kollisionspolygon dreht sich um,
wenn er sich umdreht beiden Wänden
hin und her läuft, und
das Kollisionspolygon dreht sich um,
wenn er sich umdreht Beim Betreten des Sichtfeldes beginnt
der Strahlwurfknoten, unsere Position zu
verfolgen, aber der Feind hat noch
nichts gesehen, da seine Sichtlinie durch das Gelände
blockiert ist Wenn wir nach oben springen, wird die
Sichtlinie nicht mehr behindert und wir erhalten die Nachricht, die das
Ziel erfasst hat, ausgegeben wir das Sichtfeld und auch die
Sichtlinie des Feindes verlassen , erscheint
die
Nachricht „Ziel verloren“ und der Wurf
verfolgt unsere Position nicht mehr Unser Feind ist jetzt in der Lage, die Anwesenheit des
Spielercharakters zu erkennen, aber er muss immer noch
darauf reagieren Wir sehen uns im nächsten Video.
56. 7-7 Aggression: Hallo Freunde. In diesem Video werden
wir den Feind den Spieler verfolgen
und angreifen lassen. Beginnend mit der feindlichen Szene müssen
wir einen
Angriff für diesen Feind hinzufügen. die Animation im Leerlauf dupliziere, erstelle
ich schnell Keyframes
für
die Angriffsanimation des Feindes Diese Angriffsanimation
vermittelt nicht wirklich wie viel von einem Gebiet der
Angriff treffen wird Sie zeigt nur die Bewegung des
Feindes selbst. Dafür brauchen wir ein separates
Sprite. Ich erstelle einen neuen
Sprite-Ordner für Effekt-Sprites und importiere
ein Spritesheet für den Angriffseffekt dieses
Feindes Wir fügen ein animiertes Sprite hinzu, als
untergeordnetes Element des Sprites des
Feindes angezeigt wird. Es wird
also automatisch
horizontal umgedreht, wenn sich der Feind umdreht horizontal Erstellen Sie dann eine neue
Sprite-Frames-Ressource und fügen Sie die Sprites aus dem Sprite-Sheet Wie immer füge ich am Ende der Animation
ein leeres Sprite hinzu, setze dessen Bildrate auf 12 Bilder pro Sekunde Ich füge diese Animation
dem ersten Sprite hinzu, die
Größe und Form des Angriffs genau wiedergibt Dann positioniere es
vor dem Feind. Dies macht es viel einfacher, diesem Angriff eine Trefferbox
hinzuzufügen. Lassen Sie uns also
die bestehende Hitbox duplizieren. Ich benenne die
ursprüngliche Hitbox in
Contact Damage um und belasse
diese neue Hitbox als Hitbox. Jetzt können wir diese Trefferbox so gestalten, dass Kollisionsform
dem Angriffseffekt entspricht. Im Gegensatz zum animierten Sprite sollten
wir den Trick mit der
negativen Skalierung nicht verwenden , um unsere Trefferbox umzudrehen Also müssen wir das geänderte
Richtungssignal
des Feindes mit
dem Hitbox-Skript verbinden geänderte
Richtungssignal
des Feindes mit
dem Hitbox-Skript und es
manuell neu Wie schon zuvor
nehmen wir nur einen Verweis auf
die Kollisionsform Und setzen Sie ihre Position auf ihren
Absolutwert, multipliziert mit minus Eins, wenn die Richtung
kleiner als Null ist , oder auf
positive Eins, andernfalls Im Standardstatus dieses Feindes wird
er nicht angreifen, daher ist diese Trefferbox
nicht aktiv Lassen Sie uns also seine Überwachungsfunktion
und Sichtbarkeit ausschalten. Wechseln Sie dann zurück
zur Angriffsanimation wo wir
diese Eigenschaften per Keyframe
einschalten können , um sie während der Angriffsanimation ein
- und wieder auszuschalten. Dadurch werden auch
beide mit
ihren Standardwerten
zum Reset-Track hinzugefügt . Und wir können
den Angriffseffekt auch so einstellen, dass er gleichzeitig
abgespielt wird. In der Rauminhaltsszene haben
wir derzeit das
normale Verhalten dieses Feindes, das hin und her läuft, und dem Feind die
Möglichkeit,
den Spielercharakter zu sehen Wenn dieser Knoten das vom
Ziel erfasste Signal aussendet, sollten
wir das Verhalten
des Feindes von
Tempo zu aggressiver ändern Verhalten
des Feindes von
Tempo zu Und wenn sie ihr Ziel aus
den Augen verlieren, sollten
sie
ihr ursprüngliches Tempo wieder aufnehmen Aber wir
wollen vielleicht nicht unbedingt, dass dies für
alle Gegner oder andere Charaktere gilt alle Gegner oder andere Charaktere , die das Temposkript verwenden Deshalb sollten wir
einen separaten Knoten für aggressives Verhalten einrichten. Ich werde einen anderen Timer-Knoten verwenden
und ihn Aggression nennen. Hängen Sie dann ein
Skript an diesen Knoten und speichern Sie es im
feindlichen Skriptordner. Genau wie beim Pace-Skript benötigen
wir einen Verweis auf
den Feind, den dieses Script mithilfe
des Ready-Tags kontrolliert. Wir müssen auch einen
Verweis auf das Ziel in
einer Variablen speichern , gegen das sich dieser Feind aggressiv
verhält. Außerdem müssen wir
die Richtung zum
Ziel als Vektor zwei
sowie die Entfernung
zum Ziel als Float kennen die Richtung zum
Ziel als Vektor zwei . der Feind
diese Werte kennt, kann er sich seinem Ziel
nähern, um
in Angriffsreichweite zu gelangen ,
bevor er angreift. Wir müssen aber auch die Angriffsreichweite
dieses Feindes als
exportierte Variable angeben Angriffsreichweite
dieses Feindes als ,
was ein Float wäre. Wenn du möchtest,
kannst du auch
eine minimale Angriffsreichweite angeben . Wenn wir den Typ
der Angriffsreichweite
auf einen Vektor zwei ändern , können
wir den X-Wert als
Mindestbereich und
den Y-Wert als Maximalbereich verwenden . Ich stelle den Standardwert so ein
, dass er mindestens 32 Pixel vom Player und maximal
64 Pixel
entfernt ist. Wenn der Feind also mehr als 64
Pixel vom
Spielercharakter entfernt ist , möchte
ich, dass der Feind auf ihn
zuläuft. Oder wenn der Feind weniger als 32
Pixel vom
Spielercharakter entfernt ist , möchte
ich, dass der Feind vor ihm
wegläuft. Aber innerhalb dieser Reichweite wird
der Feind angreifen. Indem wir die Prozessfunktion außer Kraft
setzen, können wir Delta ignorieren, und wenn es kein Ziel für
diesen Feind gibt, können wir zurückkehren Das sollte nicht passieren, aber es ist nie eine schlechte Idee, einen
Failsafe zu haben Wir können
die Richtung zum Ziel berechnen , indem wir
die Position
unseres Feindes von der Position
des Ziels subtrahieren und dann die Entfernung ermitteln
, indem wir denselben Vektor nehmen und seine Länge
berechnen Wenn die Entfernung zum Ziel
größer ist als unsere
maximale Angriffsreichweite, sollte sich dieser Feind
auf das Ziel zubewegen und
seine Bewegungsrichtung auf das
Richtungszeichen zum Zielpunkt X einstellen zubewegen und
seine Bewegungsrichtung auf das
Richtungszeichen . Wenn die Entfernung zum Ziel
geringer ist als unsere minimale
Angriffsreichweite, sollte
sich dieser Feind vom Ziel entfernen genau das Gegenteil
tun. Wenn beide
Bedingungen falsch waren, befindet sich das Ziel
in Angriffsreichweite. Der Feind sollte
sich also auf einen Angriff vorbereiten. Ich sorge dafür, dass der Feind aufhört sich zu
bewegen, indem ich seine Bewegungsrichtung auf Null setze und auch auf das Ziel zuschaue,
falls er es noch nicht getan hat. Ich möchte nicht, dass der Feind
sofort angreift, da meine Angriffsanimation
sehr kurz ist und
nicht telegraphiert Also starte ich den Timer hier und warte, bis er abgelaufen ist, bevor ich
angreife Die One-Shot-Eigenschaft
dieses Timers sollte auf true gesetzt werden, damit der Countdown
nur einmal erfolgt. Bei der Eigenschaft Wartezeit handelt
es sich um die Zeit, während
der sich der Feind innerhalb
der Angriffsreichweite befindet,
bevor er angreift. das
Timeout-Signal mit dem Skript
verbinde, Wenn ich das
Timeout-Signal mit dem Skript
verbinde, sage ich
meinem Feind, dass er angreifen soll Es ist auch eine gute Idee, erneut
auf das Ziel zuzuschauen falls
sich
seit dem Start des Timers etwas geändert hat seit dem Start des Timers Ich möchte den Timer nur starten
, wenn er gerade gestoppt ist. Ich werde den Timer auch
jedes Mal stoppen , wenn sich das Ziel
außerhalb der Angriffsreichweite befindet. Das sollte
für unser Verhalten ausreichend sein. Jetzt müssen wir nur noch zu den entsprechenden Zeiten zwischen
unseren beiden
Verhaltensskripten
hin und her wechseln . Wir möchten nicht, dass unser
Aggressionsskript aktiv ist, wenn der
Feind zum ersten Mal erscheint, also setzen wir seinen
Prozessmodus auf Deaktiviert das
Sichtfeld im Szenenbaum auswählen, verbinden
wir das vom Ziel erfasste Signal mit dem
Aggressionsskript
und können diese
Funktion umbenennen, wenn wir möchten Um die Konsistenz
zwischen meinen verschiedenen
Verhaltensskripten zu gewährleisten , nenne
ich sie Zoom. Diese Funktion legt
den Wert des Ziels fest, ändert den
Prozessmodus auf „Vererben“
und weist den Feind an, zu rennen,
wodurch er und weist den Feind an, zu rennen, anfängt,
aggressiv gegen das Aber wir müssen auch das
Temposkript pausieren. Also werden wir
dasselbe Signal auch mit dem Tempoknoten verbinden. Und dieses Mal rufen wir eine
Funktion namens Pause auf, aber dieses Signal
liefert ein Argument, und wir brauchen es nicht, um dieses Verhalten
zu unterbrechen. Wir können uns auch ein Szenario vorstellen in dem wir dieses Verhalten
unter anderen Umständen
pausieren möchten und kein
willkürliches und
unnötiges Argument angeben wollen willkürliches und
unnötiges Argument um die Pause-Funktion aufzurufen. Wir werden also das vom Signal
bereitgestellte Argument aufheben, sodass die verbundene Funktion keine Argumente
hat Hier müssen wir nur den Prozessmodus
auf Deaktiviert setzen Prozessmodus
auf Deaktiviert setzen Wenn der Feind ein Ziel sieht, unterbricht
er sein
Tempo und setzt sein
aggressives Verhalten fort Wenn sie also ihr Ziel verlieren, können
wir das Gegenteil tun, das Signal
mit den Skripten verbinden und
die entgegengesetzten Funktionen aufrufen Stellen Sie ihren Prozessmodus
auf Vererben ein, um
sie zu aktivieren, oder auf Deaktiviert, um sie zu
deaktivieren. Wenn wir das
Tempoverhalten aktivieren, wollen
wir dem Gegner auch
sagen, dass er gehen soll Jetzt müssen
wir im Charakterskript die Angriffsanimation auslösen, wenn wir
dem Feind sagen, dass er angreifen soll Dazu
benötigen wir einen Verweis auf Wiedergabe
der
Animations-Tree-Statusmaschine. Dies führt jedoch zu einem Fehler im Charakterskript
des Spielers, wenn wir eine andere Variable
mit demselben Namen
haben, da der Spielercharakter vom Charakter
erbt Es würde also eine
Animationsvariable vom Charakter
übernommen wird, aber auch eine andere, die
im Spielercharakter deklariert ist, was nicht erlaubt ist, aber wir verwenden sie für
den gleichen Zweck, also können wir
diese Variable einfach aus dem
Zeichenskript des Spielers entfernen diese Variable einfach aus dem
Zeichenskript des Spielers Zurück im
Charakterskript, als wir aufgefordert werden, anzugreifen, müssen
wir dieser Wiedergabe nur
sagen sie zur
Angriffsanimation wechselt. Im Animationsbaum fügen
wir die Angriffsanimation hinzu
und wechseln von
Inaktiv mit aktiviertem Advance zu ihr Inaktiv mit aktiviertem Advance und kehren am
Ende der Animation in den Leerlauf zurück. Wenn Sie nicht möchten, dass sich
der Feind beim Angriff bewegen oder die
Richtung ändern kann , können wir
Schnellprüfungen hinzufügen, um zu überprüfen, ob der
aktuelle Knoten der Animationswiedergabe Angriff ist. Und entweder die Bewegungsrichtung auf
Null setzen oder
die Funktion komplett verlassen. Wenn wir jetzt das Spiel starten der Feind uns
sowohl in seinem Sichtfeld als auch in seiner Sichtlinie hat und der Feind uns
sowohl in seinem Sichtfeld als auch in seiner Sichtlinie hat, ändert sein
Verhalten von Tempo zu aggressiver Sie werden uns hinterherjagen und nach einer kurzen Pause
angreifen. Wir haben jetzt einen viel
aggressiveren Feind mit dem sich unser Spielercharakter auseinandersetzen
muss, aber unser Spielercharakter
kann sich nicht wirklich wehren Wir sehen uns im
nächsten Abschnitt.
57. 8-1 Kombi-Gruppe: Hallo Freunde. In diesem Video geben
wir den
Spielercharakteren
eigene Angriffe , damit sie sich gegen unsere Feinde
wehren können. Wir haben den
Mausritter bereits angegriffen, und der Prozess wird sehr ähnlich
sein. Unser Spielercharakter
hat jedoch zwei verschiedene Angriffe. Wir können einige
der Knoten aus
der Mausnachtszene kopieren , um etwas Zeit
zu sparen, die Hitbox und den
Animated Sprite Two D-Knoten Wenn wir
zur Charakterszene wechseln, können
wir diese
Knoten in die Szene einfügen sie
dann nach Bedarf neu organisieren Der Knoten Animated Sprite Two D kann unter dem Sprite des
Charakters angeordnet werden, sodass er automatisch umgedreht wird, je nachdem welche Richtung
der Charakter blickt Ich benenne ihn um, um einen Angriffseffekt zu erzielen. Ich weiß, welcher spezielle
animierte Sprite das ist. Die Hit-Box werde ich als Geschwister generell neben der
Hurt-Box
sortieren Damit die Trefferbox der
Spielercharaktere der
gegnerischen Hurt-Box
Schaden zufügt, müssen
wir sicherstellen, dass die Kollisionsebenen und
Masken entsprechend eingestellt sind Da
sich mein Spielercharakter auf Kollisionsebene neun und seine Verletzungsbox
auf Kollisionsebene zehn befindet, habe ich meine Gegner dann
auf Kollisionsebene 17 und ihre Verletzungsboxen
auf Kollisionsebene 18. Wenn ich die Projekteinstellungen öffne, füge
ich die gegnerische Hurt-Box als Ebene 18 zu meinen beiden
D-Physik-Ebenennamen hinzu. Denke dann daran,
alle meine vorhandenen feindlichen
Szenen so zu bearbeiten , dass auch ihre
Hurt-Boxen auf dieser Ebene platziert werden. Das
Trefferfeld der Spielercharaktere kann dann so eingestellt werden, Ebene 18
maskiert, um ihnen Schaden zuzufügen. Um das Trefferfeld umzudrehen, müssen
wir
das Signal in dieser Szene erneut verbinden, da diese
Signalverbindung nicht
von der anderen Szene übernommen wurde Aber die Funktion, die wir
zuvor im
Hit-Box-Skript geschrieben haben und mit der wir dieses Signal
verbinden wollen, ist nach Feind
benannt, der die Richtung
geändert hat Das spielt keine Rolle,
aber wenn du
konsistent sein willst , wie du Dinge in deinem Spiel
benennst, solltest du
diesen Funktionsnamen vielleicht in „Ein Charakter
hat
die Richtung geändert“ ändern . Dadurch wird dem Skript eine weitere
Funktion hinzugefügt, und wir können
den Code einfach zu dieser neuen Funktion verschieben und die alte löschen, da sie einfach dasselbe
tut. Jetzt müssen wir jedoch in die feindliche Szene
gehen und deren Signalverbindung bearbeiten , um eine Verbindung zur neuen Funktion herzustellen. Je früher
Sie in Ihrem Projekt diese Probleme identifizieren können, desto weniger Zeit und
Mühe
müssen Sie später für das
Refactoring aufwenden Zurück in der
Spielercharakterszene wählen
wir den Animation
Player-Knoten aus
der Szenenhierarchie aus und
fügen eine neue Wir nennen diesen Angriff
eins, da es
zwei verschiedene Angriffsanimationen gibt zwei verschiedene Angriffsanimationen und wir sie
unterscheiden müssen. Nach dem Hinzufügen der Sprite-Frames des
Charakters. Ich kopiere die Keyframes für
die Kleidung des
Charakters in die anderen Tracks Wir können auch die Überwachungsfunktion der
Hitbox einschalten. Und die Sichtbarkeit auch, wenn Sie möchten, dass sie im Debug-Modus ein- und ausgeschaltet Wenn man sich
den Angriffseffekt anschaut, dieser nicht mit
der Angriffsanimation überein Also importiere ich die richtigen
Effekt-Sprites für diesen Angriff. Fügen Sie dann der
Sprite-Frames-Ressource eine neue Animation hinzu. Ich nenne es Attack One, schalte Looping aus,
stelle die Bildrate und füge am Ende ein leeres
Bild Jetzt
kann die Angriffsanimation den Angriffseffekt und den
Animated Sprite Two D Node anweisen, den Attack-One-Effekt
abzuspielen Der
Keyframe-Funktionsaufruf ist einfach abspielen, was
gut funktioniert hat, solange unser Animated Sprite Two-D-Knoten nur eine Animation zum Abspielen hat Aber jetzt haben wir zwei
verschiedene Animationen, und wir müssen angeben
, welche wir abspielen möchten auf den Keyframe klicken, können
wir ihn im Inspektor bearbeiten den Abschnitt mit den Argumenten erweitern, können
wir sehen, dass
die Play-Funktion tatsächlich drei Argumente hat, die
alle optional sind Wir befassen uns nur
mit dem ersten Argument, dem Namen der Animation, wir
in das Textfeld eingeben können. Falls Sie neugierig sind, die anderen
Argumente beziehen sich auf die Anpassung der Animationsgeschwindigkeit oder die Rückwärtswiedergabe
der Animation Die Schreibweise muss exakt mit dem Namen der
Animation Ich benenne die
Standardanimation Attack Two um, damit sie dem entspricht, was
ich in die Animation eingefügt habe. die
Angriffsanimation duplizieren, können
wir auch eine Animation für
Angriff zwei erstellen Nachdem ich die Sprite-Frames des
Charakters geändert
habe, kopiere ich die Keyframes in die
anderen Ändern Sie dann das Argument
, das an
den Angriffseffekt übergeben wird , so, dass
Angriff zwei statt Angriff
eins gespielt Angriff zwei statt Angriff
eins Wenn wir
den Animationsbaumknoten
auswählen, können
wir die erste Attacke hinzufügen
und zwei Animationen angreifen. auswählen den Animationsbaumknoten
auswählen, können
wir die erste Attacke hinzufügen
und zwei Animationen angreifen. Fügen Sie dann einen Übergang von
Bewegung zu Angriff eins und dann von Angriff
eins zu Angriff zwei hinzu. Bei beiden wird der erweiterte Modus aktiviert sein,
was bedeutet, dass wir diese
Übergänge von unserem Skript aus auslösen werden . Wenn Übergänge hinzugefügt werden,
sodass eine
der Angriffsanimationen wieder zur Bewegung
zurückkehrt, werden ihre
Wechselmodi auf „Ende“ gesetzt. Beim Übergang von
Angriff eins zu Angriff zwei wird der
Wechselmodus ebenfalls auf „Ende“ gesetzt. diese Weise können wir
zu
Angriff eins übergehen , wenn die
Angriffstaste gedrückt wird, und dann von Angriff
eins zu Angriff zwei, wenn die Angriffstaste während der ersten
Angriffsanimation ein zweites
Mal gedrückt
wurde . Um unserem Spiel einen
Angriffsknopf hinzuzufügen, müssen
wir in
den Projekteinstellungen der Eingabekarte ein neues
Eingabeereignis für Angriffe
hinzufügen. Ich verwende die X-Taste
auf der Tastatur und
die linke Taste auf meinem
Controller, was auch X ist. Dann können
wir im Spielerskript ein weiteres Ich
blockiere für Angriffe hinzufügen, die Eingabe
genauso
zwischengespeichert wird, wie wir es bei
jeder anderen Aktion getan haben Da die Taste, mit
der der erste Angriff und der
zweite Angriff ausgelöst werden, identisch ist, sollte sich
das Spielerskript nur darauf konzentrieren dem
Charakter mitzuteilen, dass er angreifen soll, und
nicht, welchen spezifischen
Angriff er ausführen soll Im Spielercharakter-Skript können
wir diese Angriffsfunktion hinzufügen, wie
jede andere gepufferte Eingabe einen booleschen Wert
zurückgibt Dies wird nicht gesperrt und
ist
im Gegensatz zur Cast-Funktion kostenlos im Gegensatz zur Wenn sich die
Animationswiedergabe des Charakters gerade im
Bewegungsmodus
befindet, erlaube ich ihm, anzugreifen. Wenn das gelingt, können wir die
Animationswiedergabe so einstellen,
dass sie eine
Animation
zum Angriff zurückfährt und „
true“ zurückgibt oder „false“ zurückgibt wenn die Figur mit etwas anderem beschäftigt
war. Es liegt ein Fehler vor, weil
die Angriffsfunktion die Angriffsfunktion
der Charakterklasse überschreibt, die Signatur
aber
nicht übereinstimmt Das bedeutet, dass entweder
die Parameter oder der Rückgabetyp unterschiedlich sind,
was nicht zulässig ist oder Befehlstaste gedrückt halten - oder Befehlstaste gedrückt halten und auf die
Funktion klicken, gelangen wir zur Oberklassendefinition
dieser Funktion wo wir sehen können, dass sie void und keinen booleschen
Wert zurückgibt Um diese
Vererbungsstruktur
bei unseren Feinden und
unserem Spielercharakter nutzen zu können und
gleichzeitig
gepufferte Eingaben zuzulassen, müssen
wir dafür sorgen, dass die
Superklassen-Angriffsfunktion
auch einen booleschen Wert zurückgibt. diese Anforderung zu
erfüllen, geben wir einfach true zurück und kehren zum
Spielercharakter-Skript zurück,
der der Aber was ist mit dem
zweiten Angriff? Wir können einen
Else-if-Block hinzufügen und prüfen, ob die Animationswiedergabe
gerade in der
Attack One Animation enthalten ist . Sagen Sie ihm dann, dass er stattdessen
zur
Animation „Angriff zwei“ reisen soll . Lassen Sie uns die sichtbaren
Kollisionsformen im Debug-Menü aktivieren, dann auf Abspielen klicken und es ausprobieren Durch Drücken der Angriffstaste spielt
unser Charakter den
Angriff One Animation ab Das Trefferfeld ist aktiviert
und die Effektanimation wird abgespielt. erneutes Drücken der
Angriffstaste während
des ersten Angriffs wird auch der zweite Angriff
abgespielt. zurück zum Editor wechseln, können
wir den Remote-Baum öffnen um zu sehen, wie unser aktuelles Spiel läuft. Wenn wir den Szenenbaum durchforsten, bis
wir die Nacht der Maus gefunden
haben, können wir ihre Hurt-Box auswählen und uns ihre Eigenschaften
im Inspektor ansehen, einschließlich ihrer aktuellen Gesundheit. Zurück im Spiel können wir unseren Feind
angreifen und zusehen, wie jeder Angriff ihn um
eine Lebenspunkte trifft ,
bis er Null erreicht. Komm schon. Wir haben jetzt unseren Charakter in der Lage, Feinde
anzugreifen, aber unsere Charaktere und Feinde reagieren
nicht darauf, getroffen zu werden. Wir sehen uns im nächsten Video.
58. 8:2 Treffer: Hallo Freunde. In diesem Video werden
wir unsere Charaktere dazu bringen, auf Angriffe zu
reagieren. beginnen in der
Spielercharakterszene wählen den
Animations-Player-Knoten Danach müssen
wir eine neue
Animation für Treffer hinzufügen. Um die Sache zu vereinfachen, dupliziere
ich die
Dash-Animation , um die Trefferanimation zu erstellen. Nachdem ich die
Sprite-Keyframes aktualisiert
habe, kopiere ich sie und füge sie in die anderen Tracks ein, um auch die Kleidung
des Charakters zu animieren Da ich
die Dash-Animation dupliziert habe, enthält
diese Trefferanimation jetzt auch Das ist sehr hilfreich,
um
zu
verhindern, dass Charaktere erleiden schnell hintereinander Schaden durch mehrere
Trefferboxen . Das fühlt sich dem Spieler gegenüber oft unfair an und
führt auch dazu, dass der Charakter
wiederholt Schaden durch
anhaltende Trefferboxen erleidet, wie zum Beispiel
Umweltgefahren, weil eine neue Kollision ausgelöst
wird, wenn die Hurt-Box
am Ende des
Animation, wenn sich die Hurt-Box immer noch mit der Hit-Box
überschneidet Wir haben auch die
Methode Track, die
die Funktion End Dash aufruft ,
die, wie Sie sich erinnern, aufgrund der Art und Weise, wie sie
im vorherigen Abschnitt implementiert wurde, aufgerufen werden
muss, wenn der
Strich unterbrochen wurde Es wäre eine gute Idee,
diesen Funktionsaufruf an den
Anfang der Trefferanimation zu verschieben . Schauen wir uns diese Funktion
im Player-Charakterskript an. Je nachdem, in welchen Frames du die Hurt-Box ein- oder
ausschaltest, kann es sein, dass der
Charakter getroffen wird, während die Sprint-Animation abgespielt
wird wodurch
die Sprint-Animation unterbrochen bedeutet, dass die
Funktion „Strich beenden“ niemals aufgerufen würde, die Schwerkraft des Charakters niemals zurückgesetzt
wird und die Abklingzeit für den Dash
nie gestartet Das ist natürlich problematisch, aber wir können es leicht beheben Alles, was wir wirklich tun
müssen, ist nachzuverfolgen, wann der Charakter
mit einer booleschen Variablen stricht Wenn der Gedankenstrich beginnt, setzen
wir ihn auf true. Wenn dann die
Funktion „Bindestrich beenden“ aufgerufen wird, prüfen
wir zuerst, ob der Charakter
stricht, und wenn ja, machen wir alle die gleichen Dinge Danach wird der Wert für „Dash“
auf „False“ gesetzt. Jetzt können wir diese
Funktion jederzeit aufrufen unabhängig davon
, ob das Zeichen gerade schneidet oder
nicht Wenn der Charakter nicht sprintet, die Funktion einfach
nichts Wenn ich den
Animationsbaumknoten auswähle
und mir
die Zustandsmaschine ansehe, möchte
ich, dass die
Trefferanimation jede dieser
vorhandenen Aktionsanimationen
sowie alle Spring- oder
Bewegungsanimationen
unterbrechen kann jede dieser
vorhandenen Aktionsanimationen
sowie alle Spring- oder
Bewegungsanimationen
unterbrechen sowie alle Spring- oder
Bewegungsanimationen Daher
wäre es eine gute Idee, eine andere Zustandsmaschine
zu verwenden Also werde ich diese Zustandsmaschine
wie bei
den vorherigen speichern . Ich nenne es Aktionen und speichere es zusammen mit den anderen
im Ordner meines Charakters. Ersetzen Sie dann diese
Zustandsmaschine durch eine neue und laden Sie die
Zustandsmaschine der Aktionen als Knoten. Okay. Sie können dann die Trefferanimation zu
dieser Zustandsmaschine hinzufügen. Wenn Sie einen Übergang vom Start
zu den Aktionen hinzufügen , wird
dieser zum Standardstatus. Dann erfolgt ein Übergang
von Aktionen zu Treffer, wobei der erweiterte
Modus auf aktiviert gesetzt ist, und ein weiterer Übergang vom Zurückschlagen zu Aktionen, bei denen der
Wechselmodus auf „Ende“ gesetzt ist. Auf diese Weise können wir
die Animation von
einem beliebigen Status aus auslösen , sofort
abspielen und dann zu unseren anderen Zuständen
zurückkehren. im Zeichenskript möchte, Da ich im Zeichenskript möchte, dass dies für alle Charaktere
gilt, nicht nur für meinen Spielercharakter, müssen
wir
eine neue Variable erstellen, um die Wiedergabe für
diese neue Zustandsmaschine zu speichern. Wir können die
bestehende Variable duplizieren und sie in etwas
wie Hurt-Animationen umbenennen. Der Pfad zu dieser
Wiedergabeeigenschaft ist der Parameter Playback, da es sich dabei um das Stammverzeichnis
des Animationsbaums handelt. Wenn wir den
Animationsbaum
im Szenenbaum auswählen und
seinen Parameterbereich erweitern, können
wir die Playbacks für
jeden unserer Zustandsmaschinen sehen Der Eigenschaftspfad für die
Wiedergabe von Action-State-Maschinen
hat sich also geändert, und wir
müssen ihn aktualisieren Um die Verwendung
dieser Wiedergabe im Zusammenhang mit den Hurt-Animationen besser
zu verdeutlichen , werde
ich diese
Playback-Action-Animationen nennen. Verwenden Sie dann die
Ersetzungsfunktion, um
alle Instanzen dieser
Variablen mit ihrem neuen Namen zu ändern . Da das
Spielercharakterskript diese Variable erbt, muss
ich auch
in diesem Skript alle Instanzen
des alten Namens
durch den neuen Namen
ersetzen des alten Namens
durch den neuen Namen in diesem Skript Das wird für
den Spielercharakter funktionieren, aber damit es auch für die Gegner
funktioniert, müssen
wir auch
deren
Animationsbaum-Zustandsmaschinen aktualisieren deren
Animationsbaum-Zustandsmaschinen damit sie diesem neuen Format entsprechen Ich aktualisiere meine Mausnacht nur ,
weil der Feind
in meinem Startzimmer ist, und der Vorgang wird für jeden Feind derselbe sein
. Ich mache die Trefferanimation
im Animation-Player-Knoten. Speichern Sie dann den Animation
Tree State Machine als Projektressource. Ersetzen Sie ihn durch einen
neuen Zustandsmaschine. Fügen Sie die alte
Zustandsmaschine als Knoten
hinzu, fügen Sie die Trefferanimation
hinzu, fügen Sie die Übergänge mit demselben Fortschritt hinzu
und wechseln Sie
den Modus. Benennen Sie es in Aktionen um, damit dem
entspricht, wonach das Skript suchen
wird. Jetzt hat dieser Feind
dieselbe Animationsstruktur wie der Spielercharakter, sodass die Skripte genauso
funktionieren Es gibt zwei separate
Playbacks für
das Abspielen der Trefferanimation und
eine weitere für Aktionen Sobald die
Zustandsmaschine eingerichtet ist, kann
die gespeicherte Zustandsmaschine gelöscht werden Dadurch wird der
Zustandsmaschine für
die Szene lokalisiert und nicht mehr zu einer gemeinsam genutzten
Ressource für mehrere Szenen. wir nun Zugriff auf die Wiedergabe
unserer Zustandsmaschine
haben, müssen wir
die Animation auslösen. Wir beginnen mit dem
Hurt Box-Skript. Wir haben ein Signal, das
ausgegeben wird, wenn sich die Gesundheit des
Charakters ändert. Dieses Signal verwenden wir, um das HUD-Element zu
aktualisieren Dieses Signal wird aber
auch ausgegeben, wenn wir die
Gesundheit des Charakters zu Beginn initialisieren,
sowie immer dann, wenn der
Charakter seine Gesundheit wiedererlangen würde Es ist also nicht das beste Signal
, um Schaden zu erleiden. Dafür werden wir ein neues
Signal ausrufen. Wenn du möchtest, dass
der Charakter
auf unterschiedliche Mengen
oder Arten von Schaden reagiert , kannst du
diesem Signal Parameter geben. Ich füge als Faktor zwei einen Parameter
für
die Richtung hinzu,
aus der der Schaden kommt. Aber wir können diese
Information nicht von hier bekommen. Wir haben nur
Zugriff auf die Hurt-Box und nicht auf die Hitbox
, die den Schaden verursacht hat. also
zum Hit-Box-Skript wechseln, haben wir
hier Zugriff sowohl auf
die Hit-Box als auch auf die Hurt Box. Also fügen wir das als weiteres Argument hinzu, das durch
die Take Damage-Funktion übergeben wurde. Wir können die
Richtung von A
nach B berechnen , indem wir A von B subtrahieren dann das Ergebnis normalisieren Bei der Normalisierung ignorieren wir
den Abstand zwischen A und B, indem wir die
Länge des Vektors auf eins setzen Zurück im Hurt Box-Skript fügen wir den
Richtungsparameter Wenn unsere
Herd-Box beschädigt wird, senden
wir das Signal und geben damit die
Richtung weiter. Unser Charakterskript kann
jetzt auf dieses Signal reagieren. Ich benenne die
verbundene Funktion Einfachheit
halber
in On Damage Received um. Okay. Zuerst weisen wir Wiedergabe
der Hurt-Animation
an, in den Trefferstatus zu wechseln. Füge dann dem Körper
des Charakters auch eine Kraft hinzu , die in
Richtung des Schadens wirkt. Da die Richtung normalisiert
ist, wird
sie eine
Länge von einem Pixel haben Wir können dies
mit einer beliebigen Zahl multiplizieren , um zu ändern, wie stark sich die Rückstoßkraft
anfühlt. Vielleicht
möchtest du das sogar als
neue Variable exportieren , sodass es für jedes einzelne Zeichen
angepasst werden kann angepasst Wir müssen
diese Signalverbindung auch in
all unseren Charakterszenen herstellen diese Signalverbindung auch in
all unseren Charakterszenen Lass es uns ausprobieren.
Mein Charakter kann jetzt den Feind angreifen und der
Feind reagiert darauf,
sowohl durch das Spielen als auch durch die Animation getroffen zu werden sowohl durch das Spielen als auch durch die Animation und
es wird auch eine Rückstoßkraft angewendet Das Gleiche passiert auch mit
meinem Charakter, wenn der
Feind mich angreift Unsere Charaktere
reagieren jetzt auf Schaden, aber unser Kampf
fühlt sich nicht besonders saftig Wir sehen uns im nächsten Video.
59. 8-3 Saft: Hallo Freunde. In diesem Video werden
wir
unserem Kampf einige
Partikeleffekte hinzufügen , damit er
sich wirkungsvoller anfühlt Beginnend mit unserer
Spielercharakter-Szene fügen
wir unserer Szene einen neuen Knotentyp
hinzu,
einen Partikelemitter-Knoten einen Partikelemitter-Knoten Godot hat zwei verschiedene
Typen, CPU und GPU. Der CPU-Partikelknoten rendert Partikel auf
die gleiche Weise, wie wir die Sprites unserer Charaktere
zeichnen Sprites unserer Charaktere
zeichnen den
Zentralprozessor des Geräts
verwenden
, der weniger effizient, aber mit älteren Geräten
kompatibler ist mit älteren Geräten
kompatibler Ein
GPU-Partikelknoten delegiert das Zeichnen dieser Partikel vollständig an die Grafikkarte des Geräts, was effizienter ist, aber
nur auf modernen Der GPU-Partikelknoten kann eine
viel höhere Anzahl von Partikeln verarbeiten viel höhere Anzahl von Partikeln ohne die Leistung zu beeinträchtigen. Ich würde die
Verwendung von CPU-Partikeln nur empfehlen wenn Sie Ihr Spiel speziell auf
Smartphones oder Tablets ausrichten Ihr Spiel speziell auf
Smartphones oder Tablets ausrichten Andernfalls solltest du GPU-Partikel
verwenden. unserer Charakterszene einen GPU Particles
Two-D-Node hinzufüge, nenne
ich ihn einfach Partikel, verschiebe ihn nach oben, sodass er sich
in der Mitte des Charakters befindet, und
schaue mir seine Eigenschaften
im Inspektor an. Bevor ein Partikelemitter
etwas zeichnen
kann, benötigt er ein Prozessmaterial Dies ist eine Ressource, die
dem Emitter mitteilt, wie
Partikel erzeugt werden sollen und wie sich die Partikel nach dem
Spawnen Partikel erzeugt werden sollen und wie sich die Partikel verhalten
sollen Für unser Prozessmaterial gibt es zwei verschiedene Optionen:
ein Partikelprozessmaterial oder ein Shadum-Material Das
Material für den Partikelprozess wird
als Projektressource erstellt , die wir direkt hier
im Inspektor bearbeiten
können, während ein
Shader-Material es uns ermöglicht ein Shader-Skript
zu schreiben,
um dasselbe zu tun Shader-Skripte sind
nicht wie alle
unsere
bisherigen Skripte in GDScript geschrieben wie alle
unsere
bisherigen Skripte in GDScript Sie sind in GD-Shader geschrieben, was in diesem Kurs nicht
behandelt wird Deshalb werden wir stattdessen eine
Materialressource für die
Partikelverarbeitung verwenden stattdessen eine
Materialressource für die
Partikelverarbeitung Klicken Sie auf die Ressource, um ihre Eigenschaften anzuzeigen
und zu bearbeiten. Da unser
Partikelemitterknoten nun über ein Prozessmaterial verfügt, erzeugt
er von seinem Ausgangspunkt
aus einzelne
weiße Pixel , die aufgrund der Schwerkraft herunterfallen Damit die Partikel
besser zu erkennen sind, verstecke
ich meinen Charakter Bevor wir uns mit den
einzelnen Eigenschaften befassen, hilft
es, zuerst die Schwerkraft
auszuschalten befindet
sich im Bereich
Beschleunigung Und da diese
Partikel
im Kampf zum Aufprall verwendet
werden, setze ich ihre
Explosivität auf eins Ich habe ein Spritesheet, das ich für meine Partikel verwenden
möchte, also importiere ich es
in meinen Effektordner und weise es
dann meiner Textureigenschaft für
Partikelemitter Aber das zeichnet nur das gesamte Spritesheet
für jeden Partikel Um ein Partikel zu animieren, müssen
wir ihm
unter den vom Canvas-Element
übernommenen Eigenschaften
ein benutzerdefiniertes Material unter den vom Canvas-Element
übernommenen Eigenschaften Wir erstellen ein neues
Canvas-Objekt als Material aktivieren
dann dessen Eigenschaft „
Partikelanimation Jetzt können wir die Anzahl der
Animationsframes
horizontal und
vertikal im Spritesheet ändern Animationsframes
horizontal und vertikal im Spritesheet Die Partikel zeichnen jetzt
nur das erste Bild. den Animationsbereich
des
Partikelprozessmaterials erweitern , können
wir die
Animationsgeschwindigkeit für die Partikel festlegen. Ich möchte, dass meine Partikel eine konstante Geschwindigkeit
haben, daher setze ich sowohl das
Minimum als auch das Maximum auf eins. Hier kann auch eine Kurve
verwendet werden, um
die Randomisierung der Animationsgeschwindigkeit der einzelnen
Partikel zu ändern die Randomisierung der Animationsgeschwindigkeit der einzelnen
Partikel Dieselben Werte können
auch angegeben werden, um jedem Partikel seinen
eigenen Animationsversatz zu geben die Erweiterung des Bereiches können
wir die Position, an
der die Partikel erscheinen,
ihren Drehwinkel und
ihre Anfangsgeschwindigkeit bearbeiten ihren Drehwinkel und
ihre Anfangsgeschwindigkeit Wir können die Emissionsform von einem einzigen Punkt aus eine Vielzahl anderer Formen ändern
und die Größe
der Form ändern, wenn wir möchten Punktemissionsformen eignen sich normalerweise am besten
zur Bekämpfung von Partikeln. Der Winkel ermöglicht eine zufällige Anordnung der Rotation der Partikel Um es völlig zufällig zu machen, stellen Sie
einfach max auf 360 ein. Da ich Pixelkunst verwende, möchte
ich nicht, dass meine
Partikel gedreht werden. Durch die Anfangsgeschwindigkeit fühlen sich
unsere Partikel
explosiver an. Die Stärke der Kraft
wird
für jedes Partikel nach dem Zufallsprinzip zwischen Minimum und Maximum bestimmt, wodurch sich die Partikel weniger gleichmäßig
anfühlen Durch die Verteilung
entsteht eine fächerförmige Form. Bei maximaler Ausrichtung auf 180 Grad die Richtung
völlig zufällig Der Bereich mit der animierten Geschwindigkeit enthält Variablen, die
Sie verwenden können
, um Ihren Partikeln im Laufe
ihrer Lebensdauer eine Vielzahl
verschiedener konstanter Geschwindigkeiten zuzuweisen Ihren Partikeln im Laufe Angular lässt sie rotieren. Directional bewegt
sie
weiterhin in die Richtung, in die
sie sich bereits bewegen. Orbital lässt sie
um den Spawnpunkt kreisen. Das Radio bewegt sie
vom Spawnpunkt weg. Und die Geschwindigkeitsbegrenzung verwendet eine Kurve, um die
Geschwindigkeit jedes Partikels zu begrenzen Der
Abschnitt „Beschleunigungen“ enthält ähnliche Variablen, mit denen Sie die Geschwindigkeit der einzelnen
Partikel im Laufe ihrer Lebensdauer
schrittweise beeinflussen
können , sodass sie
sich realistischer anfühlen Die Schwerkraft ist eine konstante Kraft in einer Richtung für alle Partikel Linear ist die Richtung
, in die
sich das Partikel bereits bewegt. Radial ist
vom Spawnpunkt entfernt. Und tangential ist
ähnlich wie orbital. Dämpfung ist eine nützliche
Kraft, die dafür sorgt, dass
Partikel im
Laufe ihrer Lebensdauer langsamer werden . Das ist nützlich bei explosiven Partikeln
oder Aufprallpartikeln
, ist nützlich bei explosiven Partikeln
oder Aufprallpartikeln
, wie Partikelattraktoren sind für zwei D
nicht verfügbar, daher hat diese Einstellung
keine Wirkung den Anzeigebereich erweitern, können
wir die Art und Weise ändern, wie
jedes Partikel gezeichnet wird Durch Skalieren werden die Partikel nach dem
Zufallsprinzip ihre eigene Größe bestimmen. Wenn wir eine Maßstabskurve hinzufügen, ändert sich
dadurch die Art und Weise,
wie jedes Partikel seine Skala im
Laufe seiner Lebensdauer
ändert Wir werden bald den
Kurveneditor durchgehen. Bei Skalierung über Geschwindigkeit wird
stattdessen die Skala von Partikeln im Verhältnis zu ihrer Geschwindigkeit und nicht zu
ihrer Lebensdauer berechnet. Dies ist besonders nützlich um Staubwolken zu erzeugen
, die sich auflösen. Farbkurven haben mehrere
unterschiedliche Eigenschaften, angefangen bei einer
Grundfarbe für alle Partikel Farbverlauf ermöglicht es uns,
einen Farbverlauf zu erstellen , bei dem jedes Partikel im
Laufe seiner Lebensdauer von der
Farbe
nach links zur Farbe auf der
rechten Seite Diese Farbe wird mit
der Grundfarbe multipliziert , um das Ergebnis zu
erhalten Beim ersten Farbverlauf
wird
die Anfangsfarbe der einzelnen
Partikel im Verlauf nach dem Zufallsprinzip ausgewählt Die Emissionskurve
kann verwendet werden, um drei D-Partikel im
Laufe ihrer Lebensdauer
unterschiedliche Lichtmengen emittieren zu lassen, was bei zwei D nicht verwendet wird. Die Alpha-Kurve ist
nützlich, um nur den Alphawert Ihrer
Partikel im Laufe ihrer Lebensdauer zu
bearbeiten Lassen Sie uns hier eine neue Ressource für
Kurventexturen erstellen. Diese Kurventexturressource benötigt eine weitere eigene
Kurvenressource. Wenn Sie darauf klicken, wird
ein Kurveneditor geöffnet, mit dem wir auf einfache Weise eine
Vielzahl von Effekten erstellen
können. Die X-Achse dieses Diagramms ist Zeit, wobei Null der
Zeitpunkt ist, an dem das Partikel erzeugt wird, und Eins das Ende der Lebensdauer des
Partikels. Nein, 1 Sekunde Die Y-Achse ist der
Wert,
den wir bearbeiten handelt es sich um die
Partikelfarben Alpha, wobei
eins undurchsichtig und
Null unsichtbar Wir können die
Minimal- und Maximalwerte für unsere Achse bearbeiten, müssen das
aber in diesem Zusammenhang nicht
tun Wenn Sie einfach auf
das Diagramm klicken, wird
ein Punkt hinzugefügt , den wir nach Bedarf
verschieben können. Ich möchte, dass meine Partikel zunächst undurchsichtig werden und dann
im Laufe ihrer Lebensdauer unsichtbar Das ist
ideal, um Partikel verblassen anstatt
einfach zu
verschwinden Tangenten werden
automatisch auf die Punkte angewendet , um eine Kurve zu erzeugen einen beliebigen Punkt
im Diagramm auswählen, können
wir die Tangenten bearbeiten um jede Art von
Kurve zu erstellen, die wir benötigen Wir können die Punkte und
Tangenten auch manuell
bearbeiten , indem wir den
Punktebereich unten erweitern Farbtonvariation kann verwendet werden, um den Farbton
Ihrer Partikelfarben nach dem
Zufallsprinzip zu ordnen, wodurch sie weniger
einheitlich aussehen Die restlichen
Eigenschaften sind für unser Tot-Projekt nicht besonders geeignet, aber ich gebe Ihnen eine kurze
Zusammenfassung dessen, wofür sie bestimmt sind Turbulenz kann angewendet werden, um zu
simulieren, wie sich Luftströmungen auf Ihre Partikel auswirken
würden Sie können das
Geräuschmuster bearbeiten, das zur
Berechnung der Turbulenzen verwendet wird
, wenn es aktiviert ist Partikel können durch Kollisionen gestoppt
oder abgetötet werden. Kollisionen sind hier nicht dasselbe wie Kollisionen, die wir
bisher verwendet haben , da die Partikel von
der Grafikkarte verarbeitet werden Sie können nur mit
Lichtokkludern kollidieren, nicht mit Lichtokkludern Und wenn Ihre Partikel skalieren, kann ihr Kollisionsradius auch mit ihnen skaliert werden Und ein Subemitter kann
verwendet werden , um Effekte
wie ein Feuerwerk zu erzeugen, wodurch zusätzliche
Partikelauslassungen entstehen. Damit meine Partikel den anderen Bildraten
meines Spiels entsprechen, lege
ich die
Lebensdauer der Partikel auf
acht Frames geteilt durch
12 Frames pro Sekunde Nachdem der
Partikelemitter eingerichtet ist, sollten
wir seine
One-Shot-Eigenschaft auf true setzen Jetzt emittiert er nur noch
Partikel in einem einzigen Burst
, den wir mit unserem Skript
auslösen können Ich schalte meinen Charakter
Sprite wieder ein und öffne
dann mein Charakterskript dem
Partikelknoten einen eindeutigen Namen geben, können
wir ihn in einer Variablen
mit dem Tag on ready speichern Wenn der Charakter dann Schaden
erleidet, können
wir den Schnee anweisen,
Partikel zu emittieren , indem wir seine
Emissionseigenschaft auf true setzen. Beachten Sie, dass dies nicht funktioniert,
wenn es schnell hintereinander verwendet
wird, da der Partikelemitter da der Partikelemitter bereits Partikel
emittiert Wenn Sie also nur die Einstellung „Emission“ auf „true“ werden keine weiteren Partikel erzeugt Zeiten wie diesen
sollten Sie entweder für
jeden Treffer
einen neuen GPU-Partikelknoten erzeugen oder stattdessen die
Neustart-Funktion aufrufen Beim Neustart wird der
Partikelemitter gezwungen,
seine aktuelle Emission zu beenden und mit einem neuen
Satz von Partikeln von vorne zu
beginnen Denkt daran, diesen Knoten nach Bedarf
in eure feindlichen
Szenen zu kopieren Bedarf
in eure feindlichen
Szenen zu Lass es uns ausprobieren.
Wenn sie den Feind angreifen, stoßen
sie jetzt Partikel aus
, wenn sie getroffen werden. Und der Spielercharakter
emittiert auch Partikel,
wenn er Schaden erleidet Wir haben jetzt Partikeleffekte, die durch unsere Angriffe
ausgelöst werden, aber
wir können noch mehr tun, damit sich Kampf noch knackiger anfühlt Wir sehen uns im nächsten Video.
60. 8-4 Schütteln: Hallo Freunde. In diesem Video fügen
wir eine
Verwacklung der Kamera hinzu,
damit sich der Kampf
noch wirkungsvoller anfühlt Ab dem Kameraskript benötigen
wir eine Variable, mit der
wir es verwackeln können. Dabei handelt es
sich um einen zweiten Vektor Es gibt zwar eine Vielzahl
verschiedener Möglichkeiten,
einen Kamerawake-Effekt zu erzeugen, aber
ich denke, es ist
sinnvoll, ein Tween zu verwenden, da es sich um eine Eigenschaftsänderung handelt , die über
einen bestimmten Zeitraum stattfindet Lassen Sie uns also eine neue
Tween-Variable namens Shake Tween deklarieren. Deklarieren Sie dann auch eine
neue Funktion, die öffentlich zugänglich
sein wird und
die Kamera erschüttern kann Prüfen Sie zunächst, ob die Kamera bereits wackelt, indem
Sie überprüfen, ob der Shake-Tween bereits
existiert, und falls ja, beenden Wir können dann ein neues Tween erstellen. Dafür sind keine speziellen Übergangs
- oder Lockerungsarten erforderlich - oder Lockerungsarten erforderlich Wir wollen
eine Eigenschaft nicht gleichmäßig von
einem Wert zum anderen verknüpfen, sondern
eine Methode einfach mehrmals
über einen kurzen Zeitraum aufrufen eine Methode einfach mehrmals
über einen kurzen Zeitraum Wir müssen die
Funktion, die wir aufrufen, deklarieren, aber ich nenne sie set shake
als private Funktion Dann müssen wir ein Argument
angeben, vom Anfang bis zum
Ende
des Tweens an die Funktion
übergeben wird Dies ist die Intensität des Schütteleffekts,
gemessen in Wir können dies
als Parameter
der Shake-Funktion akzeptieren , sodass jedes Skript, das
eine Kamerawackelung auslösen
möchte , die Intensität
angeben kann Sie dann im Laufe
der Dauer des
Kamerawakels Reduzieren Sie dann im Laufe
der Dauer des
Kamerawakels die
Intensität schrittweise auf Null. Möglicherweise
möchten Sie diesen Parameter stattdessen zu einem anderen
Parameter
machen, wenn Sie Kamerawacklungen mit
gleichbleibender oder
steigender Intensität
zulassen möchten Kamerawacklungen mit
gleichbleibender oder
steigender Intensität
zulassen gleichbleibender oder
steigender Intensität Das letzte Argument ist
die Dauer von dazwischen, die wir auch
in einen anderen Parameter umwandeln können Als Nächstes schreiben wir die
Set-Shake-Funktion, die die
Intensität als Parameter akzeptiert. Diese Funktion wird für die
Dauer des Shakes bei
jedem Frame aufgerufen , wobei die Intensität allmählich von dem Wert, der im ursprünglichen
Funktionsaufruf
angegeben wurde, auf Null
ändert . Wir müssen also nur
den Wert von Shake
auf einen neuen Vektor zwei setzen. Wenn wir mit dem zweiten
Punkt nach rechts beginnen, drehen wir ihn
dann in eine
zufällige Richtung. Ein zufälliger Drehwinkel kann eine zufällige Gleitkommazahl
zwischen Null und Tau sein. Wir können die
Ergebnisse dann mit der Intensität multiplizieren. Wenn dein
Shake-Tween aus irgendeinem Grund nicht damit
endet, dass du den
Shake-Wert auf Null setzt, musst du das
am Ende des Tweens tun Wir können das fertige Signal des
Shake-Tweens mit der Set-Shake-Funktion
verbinden und Null als Intensität festlegen Dadurch wird sichergestellt, dass der
Shake-Wert jederzeit, nachdem die Kamera mit dem
Schütteln fertig ist , wieder auf Null
zurückgesetzt wird Damit der Verwacklungsvektor die Kamera
tatsächlich bewegt, müssen wir ihn lediglich
zur Kameraposition in
unserer Prozessfunktion hinzufügen zur Kameraposition in
unserer Prozessfunktion Wie in unserer Spieleszene können
wir jetzt jedes
Signal, das
ein Verwacken der Kamera auslösen soll, mit der Verwacklungsfunktion unserer
Kamera verbinden . Zum Beispiel, wenn
der Spielercharakter einen Feind
angreift oder
wenn er Schaden erleidet. Im Spielercharakter-Skript können
wir Signale
für diese Ereignisse hinzufügen. Zurück in der Spielszene können
wir diese Signale
mit der Shake-Funktion der Kamera verbinden . Um einer Signalverbindung Argumente
hinzuzufügen, müssen
wir den Abschnitt für
Fortgeschrittene erweitern. Wir können dann
Float aus der Liste der
Argumenttypen auswählen , da
der Intensitätsparameter in unserem Skript ein Float
ist. Klicken Sie dann auf die Schaltfläche Hinzufügen. Der Shake benötigt auch eine Dauer, was ebenfalls vom Typ Float ist. Wir können also
erneut auf die Schaltfläche Hinzufügen klicken , um einen weiteren Float hinzuzufügen. Die Werte, die wir
für Argument eins angeben ändern die Intensität der
Erschütterung, gemessen in Pixeln, und Argument zwei gibt
die Dauer der
Erschütterung in Sekunden an. Ich lasse meine Spielercharaktere angreifen und innerhalb einer
Viertelsekunde ein Kamerawackeln
mit einer Intensität von vier
Pixeln verursachen ein Kamerawackeln
mit einer Intensität von vier . Aber wenn sie Schaden erleiden, werde
ich die Kamera innerhalb einer
halben Sekunde
mit einer Intensität von
acht Pixeln erschüttern . zur Szene mit den
Spielercharakteren wechseln, müssen
wir diese Signale
zu den richtigen Zeiten aussenden, angefangen mit unserem Signal „
Schaden erhalten“ in den Hurt-Boxen, das bereits mit einer Funktion
verbunden ist, die
im Charakterskript nach erlittenem Schaden
benannt ist. Wenn wir diese Funktion
im Spielercharakterskript überschreiben , können
wir die
Superklassenfunktion aufrufen und dann das Signal ausgeben Als Nächstes können wir
das Trefferfeld auswählen und dem Signal im
eingegebenen Bereich eine
weitere Signalverbindung
hinzufügen Signal im
eingegebenen Bereich eine
weitere Signalverbindung und eine neue Funktion aufrufen
lassen Nennen wir es
bei Angriff gelandet. Das muss sich nicht
mit dem anderen Bereichsknoten befassen , also können wir den Abschnitt für
Fortgeschrittene verwenden um dieses Argument
von der Signalverbindung Da wir
das Gebietsargument aufgehoben haben, hat
die Funktion keine Diese Funktion muss lediglich das Signal
aussenden, das die Kamera
verwackelt Nein, lass es uns ausprobieren. Wenn ich den Mausritter angreife, löst
das das Signal „
Trefferfelder sind eingegeben“ aus, das durch
den Spielercharakter bis zur Spielszene sprudelt und ein Verwacken
der Kamera
auslöst. Wenn der Mausritter den Spielercharakter
trifft wird das
beschädigte Empfangssignal der Hurt-Box ausgelöst, was zu einem
stärkeren Kamerawackeln führt. Unsere Kamera
wackelt jetzt als Reaktion darauf, dass der Spielercharakter
Feinde angreift und Schaden erleidet, aber unsere Charaktere sterben nicht,
wenn ihnen die Gesundheit ausgeht Wir sehen uns im
nächsten Video.
61. 8-5 Todesfälle: Hallo Freunde. In diesem Video werden
wir unsere Charaktere sterben lassen, wenn ihnen die Gesundheit ausgeht. beginne in der Nachtszene mit der
Maus, wähle den
Animation-Player-Knoten aus und erstelle schnell eine
neue tote Animation, indem
ich die
Trefferanimation dupliziere Nachdem Sie das Sprite auf das richtige Bild im
Spritesheet gesetzt haben, empfiehlt es sich,
die Hurt-Box auszuschalten, damit sie keinen Schaden
mehr erleiden können , und sie auch
nicht wieder einzuschalten Das Gleiche kann für alle anderen Areal- und Di-Knoten gemacht werden , wobei
der Kontaktschaden
und die Trefferbox zwei
ausgeschaltet werden, sodass der tote Feind
dem Spielercharakter keinen Schaden
mehr zufügen kann dem Spielercharakter keinen Schaden
mehr zufügen den
Animationsbaumknoten auswählen, können
wir diese tote Animation
zur Zustandsmaschine hinzufügen und automatisch zu
ihr wechseln, wenn dieser Charakter tot ist. Im Gegensatz zu anderen Animationen ist
kein Übergang
aus dem toten Zustand erforderlich. Jetzt müssen wir nur noch die Variable Is
dead zum
Charakterskript hinzufügen . Ich setze es als booleschen Wert an
den Anfang des Skripts. Und deklariere auch ein Signal zwei,
nur für den Fall, dass wir
jemals wollen, dass etwas
auf den
Tod nur für den Fall, dass wir
jemals wollen, dass etwas bestimmter
Charaktere reagiert Schreiben Sie dann eine öffentliche Funktion
namens Die, die
den Wert dieser Variablen
auf true setzt und das Signal ausgibt. Überall in diesem Skript
, wo ein Charakter jede Aktion
ausführen könnte , die nach seinem Tod nicht erlaubt sein
sollte, können
wir einfach zuerst den Wert
der Variablen is dead überprüfen . Wenn dem Charakter also
gesagt wird, dass er in eine Richtung schauen soll, er
aber tot ist,
sollte er diese Aufforderung ignorieren. Genauso ignorieren wir es,
wenn sie angreifen. In ähnlicher Weise sollte dieser Charakter nicht springen, wenn ihm gesagt
wird, er soll springen,
er
aber tot ist. Das Gleiche gilt für Angriffe. Und im physikalischen Prozess setze
ich ihre
Bewegungsrichtung auch
auf Null, setze
ich ihre
Bewegungsrichtung auch wenn sie tot sind, sodass sie
sich nie bewegen, solange sie tot sind, sondern von der Physik beeinflusst werden. Im Hurt Box-Skript haben wir bereits das farbige
Signal erzeugt und es ausgegeben, wenn der Charakter keine Lebenspunkte
mehr hat, als wir das Drehbuch im
vorherigen Abschnitt
geschrieben haben das Drehbuch im
vorherigen Abschnitt
geschrieben Aber um
eine Todesanimation und
keine Trefferanimation abzuspielen ,
wenn der Charakter Schaden
erleidet und dadurch
stirbt, müssen
wir sicherstellen, dass wir zu diesem
Zeitpunkt nur das gefärbte Signal
aussenden Also verschieben wir das Signal, das Schaden erlitten hat,
in einen SE-Block und geben dem gefärbten Signal Priorität Wir müssen lediglich das gefärbte Signal
der Hurt-Box mit der Würfelfunktion des
Feindes verbinden gefärbte Signal
der Hurt-Box mit der Würfelfunktion des ,
um die Animation auszulösen Entweder in der feindlichen Szene oder in der Rauminhaltsszene, wo auch immer du die KI-Knoten deines
Feindes
hast, möchtest du vielleicht auch das
DID-Signal des Feindes mit der freien
Funktion dieser Knoten
verbinden DID-Signal des Feindes mit der freien
Funktion dieser Knoten Alternativ können Sie dies
in den Skripten selbst tun. Wenn Sie die Ready-Funktion außer Kraft setzen, können
feindliche Gegner mit Ure
verbunden werden Auf diese Weise
müssen Sie das Signal im gesamten Projekt nicht hunderte Male
manuell anschließen gesamten Projekt nicht hunderte Male
manuell Lass es uns ausprobieren. Wenn ich den
Mausritter fünfmal
angreife, erreicht seine Gesundheit
Null und er stirbt, wodurch die Todesanimation abgespielt wird
und alle Aktionen gestoppt werden. Ich kann ihn auch berühren,
ohne Schaden zu nehmen. Nun zum Spielercharakter, ich habe eigentlich keine
Todesanimations-Sprites für diesen Charakter Stattdessen werde ich die Trefferanimation
wiederverwenden und sie
duplizieren, um
eine Todesanimation zu erstellen, da ich weiß, dass
die Spielszene sowieso
ausgeblendet und zurückgesetzt wird, wenn
dieser Charakter stirbt die Spielszene sowieso
ausgeblendet und zurückgesetzt wird Wie beim Feind ist
es eine gute Idee, auch alle Verletzungs- und
Trefferboxen auszuschalten Die einzige wirkliche Änderung, die ich
hier vornehmen werde , ist die
Animationsschleife. Im Animationsbaum füge
ich die tote Animation wie zuvor hinzu, mit einem automatischen Übergang,
wenn der Charakter tot ist. Aber dieses Mal füge ich auch
einen Übergang aus dem toten Zustand hinzu, vorausgesetzt , dass sie nicht mehr tot
sind, da der Spielercharakter nach seinem Tod wiederbelebt
wird Nachdem ich das Signal für den
Tod der Hurt Box mit dem
Charakterskript verbunden habe, wechsle ich zum Charakterskript des
Spielers Wir müssen eine
Revive-Funktion schreiben, die verwendet
werden kann, um den
Spielercharakter wieder zum Leben zu erwecken, indem wir die
Variable I dead wieder auf False setzen Wir können der Hurt-Box auch sagen gleichzeitig ihre volle Gesundheit
wiedererlangen
soll Um der Todesanimation des
Spielercharakters mehr hinzuzufügen, überschreibe
ich die Würfelfunktion im Spielercharakter-Skript. Ich rufe zunächst
die Superklassenfunktion auf und mache
dann einige andere Dinge, mache
dann einige andere Dinge den
Spielercharakter
spezifisch den
Partikeleffekte-Node wiederverwende, setze ich seine
One-Shot-Eigenschaft auf False seine Explosivität Und die
Eigenschaft „Emission“ wird auf „Wahr“ gesetzt, wodurch der spontane Ausbruch von Partikeln in einen stetigen Strom umgewandelt wird Darüber hinaus werde ich die Modulationsfarbe des
Charakters verändern eine höhere
Intensität zu erzielen Nachdem ich ein neues Tween erstellt
habe, setze ich die
Modulationsfarbe dieses Knotens auf
eine neue Farbe mit
RGB-Werten von Dann setze
ich in der Revive-Funktion all diese Werte wieder
auf ihre normalen Werte zurück A In der Spielszene kann
die Kamera auch auf den Tod
des Spielers mit einem weiteren,
noch intensiveren Kamerawackeln reagieren Tod
des Spielers mit einem weiteren noch intensiveren Kamerawackeln Der Spielmanager muss
auch auf den Tod
des Spielercharakters reagieren Tod
des Spielercharakters , um alles zurückzusetzen. So können wir das dD-Signal des
Spielercharakters
mit dem Game Manager-Skript verbinden . Nennen wir diese
Funktion auf Player DD. Wenn der Spieler stirbt, können
wir zunächst den Eingabe-Handler deaktivieren, können
wir zunächst den Eingabe-Handler deaktivieren sodass er den Charakter nicht mehr
kontrollieren kann. Ich warte zuerst eine Sekunde , bis die
Todesanimation meines Charakters abgespielt wird. Das kann erreicht werden, indem dem Szenenbaum anweise, einen Timer zu
erstellen. Wir können den
Szenenbaum jederzeit mit der Funktion get tree abrufen und
die Funktion create timer aufrufen, die ein Argument
für die Länge des Timers akzeptiert. Dies gibt den bereits
gestarteten Timer zurück , sodass wir auf
sein Timeout-Signal warten können Dadurch wird die Ausführung dieser Funktion in
dieser Zeile
für genau 1 Sekunde unterbrochen Funktion in
dieser Zeile
für genau 1 Sekunde Nachdem er zu Schwarz verblasst ist, müssen
wir
den Spielercharakter neu positionieren , so
dass er reagieren soll Da wir noch keine
geeigneten Systeme
dafür haben , werde
ich sie einfach am Ursprung
der Spielszene platzieren und einen Kommentar hinterlassen, dass
dies später implementiert werden muss Wir können jetzt den
Spielercharakter wiederbeleben, wieder einblenden
und den Eingabe-Handler wieder aktivieren, und den Eingabe-Handler wieder aktivieren sodass der Spieler
weiterspielen kann Wenn Sie Text
anzeigen möchten, können
Sie der Canvas-Ebene einen Label-Node
hinzufügen Ich nenne Mind Game Over
und gebe ihm einen eindeutigen Namen. Füllen Sie es dann mit
etwas Text und zentrieren Sie es. Geben Sie ihm eine größere Schriftgröße. Und verankern Sie es in der
Mitte des Bildschirms. Bevor ich es zu Schwarz verblasse, erstelle
ich auch
einen Tween, Alphawert des Labels bis zu eins
verblassen lässt Ich moduliere den Alphawert auf Null, sodass er standardmäßig unsichtbar ist Ohne zu warten, wird
dies zur
gleichen Zeit geschehen , in der der
Bildschirm schwarz wird Das Etikett
muss
vor der Blende gezeichnet werden ,
damit es sichtbar ist Nachdem ich
den Spielercharakter neu positioniert
habe, warte ich noch eine Sekunde bevor ich zum Text übergehe Aber ich mache es schneller,
als es eingeblendet ist. Nachdem ich den
Spielercharakter wiederbelebt
habe, zeige ich eine andere Meldung an das Spiel wieder eingeblendet Ich dupliziere die bestehende
Game-Over-Nachricht,
nenne diese Nachricht Revive und ändere Bevor das Einblenden wieder gelöscht wird, verwende
ich ein weiteres Tween,
damit der Text eingeblendet Warten Sie eine weitere Sekunde und blenden
Sie den Text dann wieder aus Lass es uns ausprobieren. Ich lasse die Nacht der Maus
meinen Spielercharakter töten. Unsere
Charaktere sterben jetzt und der Spielmanager reagiert auf den Tod des Spielercharakters, aber in unserem Spiel ist
noch kein Boss drin Wir sehen uns im nächsten Video.
62. 8-6 Chef 1: Hallo Freunde. In diesem Video bauen
wir einen Boss für unser Spiel , der komplexer ist
als unsere anderen Feinde. Ich beginne damit,
einen neuen Asset-Ordner zu erstellen , der
die Assets für diesen Boss enthält. Importiere dann die Sprites. Dann erstelle ich in meinem Ordner mit feindlichen
Szenen eine
neue Szene mit dem Namen Mac Mouse
mit dem Stammknotentyp CharacterBody two D. Dieser Boss besteht aus mehreren
verschiedenen Sprite-Komponenten , die ich zusammensetzen
und übereinander schichten muss Zuerst füge ich ein
normales D
ohne zwei hinzu, ich alle visuellen
Komponenten des
Bosses umdrehen kann , wenn sie sich
umdrehen, und es Flip nennen umdrehen, und Dann füge mehrere Sprites
für die verschiedenen Komponenten hinzu. Ich benötige ein Sprite für
die Panzerung,
das wird eine Atlas-Textur sein Und nachdem ich
die Textur ausgefüllt
habe, wähle ich die entsprechende
Region aus dem Spritesheet aus Dies wird um 48 Pixel nach
oben verschoben. diesen Sprite-Knoten dupliziere, benenne
ich ihn in
Gears um und ändere seinen Typ
in Animated Sprite two D. Wenn ich dem Knoten eine
Sprite-Frames-Ressource gebe, füge
ich die Zahnrad-Sprites Dann ändere die
Animationsgeschwindigkeit auf 12 Bilder pro Sekunde. Das sollte
hinter der Panzerung stehen,
also ordne ich die Knoten neu an den Sprite-Knoten für die
Panzerung erneut dupliziere, erstelle ich ein weiteres Sprite für den Hintergrund hinter den Zahnrädern Nachdem ich die
Atlas-Textur für diesen Knoten einzigartig gemacht
habe, kann ich eine
andere Region zum Zeichnen auswählen und diesen Knoten neu anordnen, sodass er hinter den anderen
gezeichnet wird Dieser Hintergrund dient auch
dazu, die Zahnräder
so zu beschneiden, dass nichts außerhalb
des Körpers gezeichnet wird Das können wir tun,
indem wir die Zahnräder als untergeordnetes Element des
Hintergrundknotens platzieren. Wählen Sie dann im Bereich „Sichtbarkeit“
den Hintergrund aus und
ändern Sie die Einstellung „Clip-Kinder“ von „
Deaktiviert“ auf „Ausschneiden und Zeichnen“. Jetzt
ziehen sich die Zahnräder nur noch in den Körper hinein. Es gibt auch eine animierte
Aufziehtaste. Also werde ich meinen
Gears-Knoten duplizieren, um einen weiteren Animated
Sprite-Tout-Knoten zu erstellen, und ihn Key nennen Nachdem ich die
Sprite-Frames-Ressource für diesen Knoten
einzigartig gemacht
habe, ersetze ich die Gear-Sprite-Frames durch die wichtigsten
Sprite-Frames Sprite-Frames Ich werde dann
die Taste neu positionieren, sodass sie sich an der entsprechenden Position auf Rückseite des
Körpers der Mc-Maus Ich benötige mehr Animated Sprite
Two-D-Knoten für die Räder, also dupliziere ich den Schlüssel, um ein animiertes Rad
zu erstellen Nachdem ich die
Sprite-Frames-Ressource einzigartig gemacht
habe, tausche ich die
wichtigsten Sprite-Frames gegen die Rad-Sprite-Frames
aus die Rad-Sprite-Frames Stellen Sie das Rad dann an eine gute Position und verschieben Sie
es so, dass es auf dem Boden liegt O. Um
die Räder hinter dem Körper zu zeichnen ,
ordne ich sie so an, dass sie sich im Szenenbaum über
dem Körper Ich dupliziere das
Vorderrad, um ein zweites Rad zu erstellen
und es neu zu positionieren Die letzte visuelle Komponente dieses Bosses ist ein Fass, das aus seinem Mund
herausragt Es wird nur
ein gewöhnlicher Geist sein. Nachdem ich die
Sprite-Textur zugewiesen
habe, verschiebe ich sie so, dass sie um den Mund der Mc-Maus liegt, und sie hinter
die
Body-Sprites Wenn dieses Fass Projektile abfeuert, möchte
ich, dass es aus dem Mund der
Mc-Maus herausragt, sodass es einen Offset
von minus 16 Pixeln hat Ich füge an dieser Position einen
Flächentutti-Knoten hinzu, der
das Projektil sein wird Geben Sie ihm dann einen animierten
Sprite Tutti-Knoten mit Sprite-Frames-Ressourcen und fügen Sie die beiden
Fireball-Sprite-Frames hinzu Nachdem ich die Bildrate eingestellt
habe, habe ich standardmäßig auch diese
automatische Wiedergabe Dazu wird eine
Kollisionsform benötigt, die nur ein Kreis sein wird. Damit es
als Projektil funktioniert,
muss das
Projektilskript beigefügt sein Das Projektilskript erwartet, dass das Projektil
eine Aufprallanimation hat,
also füge ich eine hinzu, indem ich dieselben Schlag-Sprites
wie mein anderes Projektil verwende dieselben Schlag-Sprites Dabei muss die
Hurt-Box-Ebene des Spielers überwacht und maskiert Wir können den eingegebenen Bereich
und die vom Körper eingegebenen Signale
mit dem Projektilskript verbinden , um Aufprallanimation und den Schaden
auszulösen O. Wenn der Feuerball zusammengebaut ist, können
wir ihn als eigene Szene
im Projektilordner speichern im Projektilordner Ich füge einen
Toti-Knoten als untergeordnetes Element des Feuerballs hinzu,
der als Ort dient, an dem
die
Projektile erscheinen,
genau wie wir es mit dem Spielercharakter gemacht Ordne dann den
Tutti-Markerknoten so an, dass er ein Bruder des Feuerballs ist, wobei seine relative Position
beibehalten wird, und lösche den Feuerball beibehalten an, dass er ein Bruder des Feuerballs ist, wobei seine relative Position
beibehalten wird, und lösche den Feuerball. Setzen Sie dann den Abstand der Fässer Standardposition zurück nur
den Körper nach links und rechts drehen, Ich möchte nicht nur
den Körper nach links und rechts drehen, sondern auch, dass der Körper
der Mc-Maus rumpelt,
aber nicht die Räder Also werde ich alles, was
ich will, als
Kinder eines anderen
Körpers mit dem Namen D zum Rumpeln bringen Kinder eines anderen
Körpers mit dem Namen D Jedes Mal, wenn sich die Mc-Maus bewegt, möchte
ich, dass Staub und Steine von den Rädern vom
Boden aufgewirbelt werden von den Rädern vom
Boden aufgewirbelt Also füge ich einen GP-Partikel mit
zwei D-Knoten für die Felsen hinzu. Dann weise ich einen Rock Sprite als Textur zu und erstelle ein Prozessmaterial für
Partikel Okay. Lass die Steine vom
Boden aufsteigen, alles was ich tun muss, ist die Geschwindigkeitsrichtung nach oben zu
ändern und jedem Stein
eine zufällige Geschwindigkeit von 32-64
Pixeln pro Sekunde zu geben eine zufällige Geschwindigkeit von 32-64
Pixeln pro Sekunde Bei Staub
dupliziere ich zunächst den
Gesteinspartikel-Emitter und Dann weise ich der
Textureigenschaft dasselbe Partikel-Spritesheet zu,
das ich
für Attack Impacts verwendet habe das ich
für Attack Impacts Da es sich um ein Spritesheet handelt,
das animiert werden
soll, benötigt
dieser Knoten ein
Canvas-Objektmaterial mit aktivierter
Partikelanimationseigenschaft der richtigen
Anzahl von Nachdem ich das Material für die
Partikelverarbeitung einzigartig gemacht
habe, behalte ich die Geschwindigkeit bei, entferne
aber die Schwerkraft und füge genügend Dämpfung hinzu, um
der ursprünglichen Geschwindigkeit entgegenzuwirken Unter „Anzeige“ füge ich
eine Animationsgeschwindigkeit
von eins hinzu, um
die Partikel zu animieren , und eine Alpha-Kurve , damit sie mit der
Zeit verschwinden. Ich möchte, dass das im Vordergrund dargestellt wird, also setze ich die
Eigenschaft „Reihenfolge“ auf eins Das sollte ausreichen, also dupliziere ich die
beiden Partikelknoten und füge sie dem anderen Rad hinzu. Ich möchte nicht, dass sie standardmäßig
emittieren, also wähle ich alle gruppiert aus und schalte ihre
Emissionseigenschaften aus. Wie jeder andere Feind benötigt auch
dieser eine
Kollisionsform, um mit
der Umgebung zu kollidieren , sowie
Verletzungs- und Trefferboxen Da dieser Feind eine
eher einzigartige Form hat, verwende
ich
eher ein Kollisionspolygon als eine Kollisionsform eher ein Kollisionspolygon als eine Kollisionsform dem Polygon einige Scheitelpunkte
hinzufüge , um die allgemeine Form
des Körpers des Chefs zu erhalten, muss
ich sicherstellen, dass das Kollisionspolygon
den Boden berührt Ich möchte mir auch nicht wirklich die
Mühe machen, dieses Polygon umzudrehen, also mache ich es symmetrisch. Das reicht für Kollisionen
mit der Umgebung aus, ermöglicht es
dem Spielercharakter
aber auch ,
auf dem Feind zu stehen Bei der Hurt-Box geht es
mir etwas weniger
darum, die
Form des Feindes so genau abzubilden, also verwende ich eine normale Kapsel Wenn du
mehrere Standardformen kombinieren möchtest , um eine komplexere Hurt-Box zu
erstellen, kannst
du einfach mehr
Kollisionsformknoten hinzufügen. Ich füge
über der ersten eine zweite Kapsel hinzu, um einen
größeren Teil des Körpers abzudecken. Ich möchte mir auch nicht die
Mühe machen, diese Hurt-Boxen umzudrehen, daher hilft es, dass sie symmetrisch
sind Der D-Node Area Two
sendet seine Signale als ob alle Formen zu einer Form
zusammengefasst wären Denken Sie jedoch daran, dass, wenn
die Formen weit voneinander entfernt sind,
etwas möglicherweise in eine Kollisionsform
eindringt, diese
dann verlässt und dann in eine
andere Kollisionsform eintritt, was zu mehreren Kollisionen
führt Ich werde auch eine separate
Hurt-Box für den Aufziehschlüssel hinzufügen. diesem Schlüssel eine
eigene Hurt-Box gibst muss
er nicht mit der Gesundheit des Bosses
verbunden sein,
sondern kann Signale aussenden, wenn
der Spieler ihn angreift Dies kann nur eine einfache
kreisförmige Kollisionsform haben, muss
aber umgedreht werden Ich werde also sicherstellen, dass
die Exposition
des Formknotens
ausschlaggebend dafür ist , auf welcher Seite sich die
Hurt-Box befindet Und schließlich braucht dieser
Feind eine Hitbox. Dies wird verwendet, wenn die
Mc-Maus vorwärts fährt. Ich möchte, dass dies dem
Spielercharakter schadet,
wenn er vor oder
über dem Boss steht. Ich verwende also eine um
90 Grad gedrehte Kapsel, die
über das
Kollisionspolygon
des Körpers davor und darüber hinausragt die
über das
Kollisionspolygon
des Körpers davor und darüber hinausragt , aber nicht dahinter Wählt man den
Wurzelknoten
des Charakters aus, muss der Feind als
Terrain betrachtet werden , damit der
Spielercharakter darauf stehen kann, aber auch auf
der feindlichen Ebene
existiert und nur das Terrain maskiert Keine der Hurt-Boxen
oder Trefferboxen
muss standardmäßig überwacht
oder überwacht werden können Wir schalten sie
durch Skripte oder Animationen ein, wenn sie aktiviert werden
müssen Aber die Hurt-Boxen können auf die
Kollisionsebene
der gegnerischen Hurt-Box gesetzt werden, und die Hit-Boxen können so
eingestellt werden, dass sie die Kollisionsebene der
Verletzungsbox des Spielers maskieren Kollisionsebene der
Verletzungsbox ,
sodass sie funktionieren, wenn sie
aktiviert sind. Wir haben jetzt einen Boss für unser Spiel
zusammengestellt, aber es gibt noch keine
Skripte, die ihn steuern. Wir sehen uns im nächsten Video.
63. 8-7 Chef 2: Hallo Freunde. In diesem Video werden
wir unserem Boss
komplexere Verhaltensweisen geben als unseren normalen Feinden. Die tatsächliche
Mechanik des Fortschritts
wird im nächsten Abschnitt behandelt. Aber vorerst wird es
helfen, darüber nachzudenken, wie unser Boss im
Verhältnis zu seiner Arena existieren sollte. Also lasst uns diesen Boss-Feind in
eine einfache Arena mit einer
Mauer auf beiden Seiten platzieren . Im Allgemeinen fangen Bosse in Metroidvania den
Spieler in einer Arena ein, und sobald der Spieler
sie betritt, muss er den Boss besiegen bevor er sie verlassen
darf Das ist ein Ereignis, das dadurch ausgelöst werden
muss, dass
der Spielercharakter den D-Node von Area Two betritt
, also fügen wir der Szene einen hinzu
und nennen ihn Dann gib ihm eine Kollisionsform. Ich verwende ein Rechteck und
lasse es einen sehr
großen Bereich abdecken, sodass der Spieler es nicht umgehen kann und lasse es den Körper des
Spielercharakters überwachen. Dazu muss ein
Skript angehängt werden, aber ich erstelle es im Dateisystem-Tab in einem neuen
Ordner mit feindlichen Skripten für Bosse, wir
Boss Encounter nennen können,
wodurch Area Two D
erweitert wird. Dieses Skript wird dafür verantwortlich
sein den gesamten
Ablauf der Bossbegegnung zu
steuern, einschließlich wann sie
beginnt, wann sie endet und alle Phasenübergänge, Dinge wie Titelkarten, wechselnde Musik usw. Wir müssen dem einen Klassennamen geben damit wir ihn später erweitern können Um darauf zu reagieren, dass der
Spielercharakter an dieser Bossbegegnung teilnimmt, können
wir weitermachen und die Funktion
on body entered schreiben, die
einen Parameter namens
body vom Typ D ohne zwei akzeptiert und nichts zurückgibt. Der Spielercharakter nimmt an
dieser Boss-Begegnung teil. Zunächst sollten
wir
alle zukünftigen Kollisionen
mit diesem Bereich ausschalten , indem set deferred
verwenden, um die
Überwachungseigenschaft auf False zu setzen Denken Sie daran, dass
wir, wenn eine Funktion durch ein
Kollisionsereignis aufgerufen wird, unsere
Kollisionsobjekte nicht gleichzeitig ändern sollten .
Deshalb verschieben wir dies, bis die Kollisionen
behandelt Wir können dann die Arena schließen, den Spieler darin
gefangen halten und alle
erforderlichen Initialisierungen durchführen Aber darauf kommen wir später zurück. Vorerst deklarieren wir eine
exportierte Variable, die
den Boss-Feind selbst
und eine für den
Spielercharakter als Ziel enthält den Boss-Feind selbst . Wenn der
Spielercharakter an der Bossbegegnung teilnimmt, können
wir den Wert des
Ziels auf den Körper
sowie als lokale
Phasenvariable als Ganzzahl festlegen . Fügen Sie dann eine Startfunktion,
eine Endfunktion und auch eine
Phasenübergangsfunktion die Phase
als Parameter
akzeptiert und die Variable
auf ihren neuen Wert aktualisiert. In der Startfunktion können
wir Phase auf
eins setzen und unsere
Entscheidungsfunktion aufrufen , um den Kampf zu
beginnen. Wir benötigen außerdem eine Funktion , die dem Boss mitteilt,
was er als Nächstes tun soll. Vorerst rufe ich
die Startfunktion auf, wenn der Spielercharakter die Boss-Arena
betritt. Stellen Sie sicher, dass Sie dieses Skript speichern damit der Klassenname registriert ist. wir nun die
Grundstruktur festgelegt haben, hängen wir ein neues Skript
an unseren Boss-Encounter-Knoten an. Ich benenne es nach meinem Boss, Neck Mouse Encounter, der
Boss Encounter erweitert , und speichere es
im entsprechenden Ordner. Mit dem angehängten Skript können
wir der exportierten Variablen den
Endgegner zuweisen, die Kollisionsmaske auf
die Ebene des Spielercharakters
setzen und das vom Körper
eingegebene Signal verbinden. Da die Funktion „Ein Körper
eingegeben bereits in der Oberklasse
Boss-Begegnung existiert, brauchen
wir uns in diesem Skript
darüber keine Gedanken zu machen Wir werden jedoch
die
Entscheidungsfunktion überschreiben und
dieser speziellen Boss-Begegnung einen
eigenen Algorithmus geben dieser speziellen Boss-Begegnung , der entscheidet,
was sie als Nächstes tun wird Die Bossbegegnung auf diese
Weise zu strukturieren, macht es einfacher, das Verhalten eines
Bosses
je nachdem, in welcher Phase er sich gerade
befindet,
zu ändern oder der Arena als Reaktion auf die Aktionen des Bosses Umweltgefahren
hinzuzufügen oder
das Verhalten mehrerer
Bosse in einer einzigen Begegnung
zu synchronisieren das Verhalten mehrerer
Bosse in einer Jede neue Bossbegegnung, die wir erstellen
möchten , kann auch die Klasse der
Bossbegegnungen
erweitern und
für jeden Endgegner
eigene, einzigartige Implementierungen bereitstellen für jeden Endgegner
eigene, einzigartige Implementierungen Zunächst ist es eine gute Idee,
zu überprüfen, ob der Boss tot
ist, bevor wir ihn
entscheiden lassen, was als Nächstes zu tun Wenn sie also schon tot sind, können wir einfach zurückkehren. Es ist auch eine gute Idee, die Aktionen eines Bosses mit einer kurzen Pause
abzuwarten , bis
ein Timeout-Signal des
Timers ausgelöst Wir können es weniger vorhersehbar machen indem wir die Dauer des
Timers zufällig und sogar die Kadenz des Kampfes
mit jeder Phase erhöhen, indem wir
durch
die Phasenzahl dividieren Und egal, wofür sich der
Boss entscheidet, er sollte
sich wahrscheinlich dem Ziel
zuwenden Wir können also eine Funktion aufrufen, die dem Chef
sagt, dass er nach links schauen wenn die globale Exposition des Ziels geringer
ist als seine eigene Mithilfe einer Match-Anweisung für die Phasenvariable können
wir
auf einfache Weise
verschiedene Aktionsoptionen
für verschiedene Phasen bereitstellen verschiedene Aktionsoptionen
für verschiedene Phasen Da mein Chef so einfach ist, werde
ich mich dafür entscheiden,
die Intensität der
Aktionen phasenweise zu erhöhen ,
anstatt neue einzuführen. Mit einer weiteren Match-Anweisung
auf einer zufälligen Ganzzahl von 0-1 schaffe ich eine gleichmäßige Chance, zwischen zwei
verschiedenen Aktionen zu entscheiden Entweder bewegt sich der Boss an eine zufällige Position in der Arena, die der
globalen Position dieses Boss-Begegnungsknotens plus einer Zufallszahl zwischen minus 300
und positiven 300 entspricht, oder der Boss schießt
Feuerbälle auf den Spieler Ich werde die Anzahl der
Feuerbälle basierend auf
der aktuellen Phase randomisieren Feuerbälle basierend auf
der Ich möchte auch, dass der Boss eine dritte Aktion
hat, die darin besteht, den Spielercharakter
mit höherer Geschwindigkeit anzugreifen, aber nur unter
bestimmten Bedingungen Wenn die Mc-Maus also
zum Laden bereit ist , wird sie geladen. Wenn nicht geladen wird, wird die
Aktion nach dem Zufallsprinzip ausgewählt. Und ich gebe ihm das Vorzeichen der globalen
Position
des Ziels abzüglich der globalen
Position der McMouse als Richtung Wenn Sie planen, welche
Aktionen Ihr Chef wann verwenden
soll, erhalten Sie genau die öffentlichen
Variablen und Funktionen, die Sie in deren Skripten
schreiben müssen. Aus diesem Skript können wir also ersehen, dass das Skript unseres Chefs
eine „Ist tot“ -Variable,
eine einsatzbereite Variable und außerdem Funktionen „Nach links zeigen“, „aufladen “, zur Position bewegen und „Feuerbälle abfeuern Dies ist eine einfache Methode, um beim Schreiben komplexer Skripte an die
Kapselung heranzukommen Kapselung Wir können das Skript schreiben, das
zuerst eine Schnittstelle herstellen
muss , sodass wir bereits
genau wissen, was wir Die Kapselung hilft uns auch dabei, Abstraktion
zu erreichen. Da wir uns nur auf das konzentrieren, was öffentlich zugänglich sein
muss, können
wir auch davon ausgehen, dass alles andere privat sein
sollte Als Nächstes hängen wir ein Skript an den Root-Node des MCMUS und speichern es im Ordner
Enemy Scripts Wir können alle
Variablen und Funktionen deklarieren, die die entsprechenden Parameter
aus dem Boss-Encounter-Skript
akzeptieren aus dem Boss-Encounter-Skript Wenn wir ein Signal deklarieren und es
so etwas wie fertig nennen, dann können wir dieses
Signal von
allen Aktionen ausgeben , die in der
Entscheidungsfunktion
ausgewählt wurden . Lassen Sie uns vorerst einfach ausdrucken, was wir
vom Chef erwartet hatten. Wir können zuerst überprüfen, ob dieser
Feind tot ist, und wenn ja, das fertige Signal
aussenden sofort das fertige Signal
aussenden und zurückkehren,
damit nichts passiert. Warten Sie dann 1 Sekunde bevor Sie das
fertige Signal aussenden. Wählen Sie dann in der Inhaltsszene den Knoten „
Endgegner“ aus, den wir
dem
Endgegner selbst zuordnen können , wenn wir
möchten , und verbinden Sie das
fertige Signal mit der Entscheidungsfunktion. Jedes Mal, wenn dieser Bossgegner eine der Aktionen
abschließt, entscheidet
er automatisch, was als Nächstes zu tun ist. Das sollte ausreichen
, um
den Ablauf unseres Bosskampfes zu demonstrieren .
Also lass es uns ausprobieren. Wir können anhand der Ausgabe
alle ein oder zwei Sekunden sehen, der Feind eine Entscheidung
darüber trifft, was als Nächstes zu tun ist. Unser Boss-Feind wird jetzt durch ein
Boss-Encounter-Skript
gesteuert, aber wir
müssen noch implementieren, wie alles
intern in der Boss-Szene funktioniert. Wir sehen uns im
nächsten Video.
64. 8-8 Chef 3: Hallo Freunde. In diesem Video werde
ich durchgehen, wie ich die Funktionen
meines Chefs geschrieben habe, damit Sie meine Methoden mit der Art und Weise vergleichen können , wie Sie Ihre
implementiert haben. Zuerst habe ich
die Hit-Box- und
Hurt-Box-Skripte an
die Hitbox bzw. die Hurt-Boxen des Chefs angehängt Hurt-Box-Skripte an
die Hitbox bzw. die Hurt-Boxen des Chefs Dann habe ich mit den
Boss-Enemy-Skripten angefangen. Ich habe Signale für
alles deklariert , was verwendet
werden sollte, um den Bosskampf zu starten oder zu beenden oder einen Phasenübergang
herbeizuführen. Ein anderes, wenn
der Boss die
Richtung ändert , sodass ich weiß, wann
ich die Dinge umdrehen muss, und ein paar mehr, um zu wissen,
wann der Boss
an seinem geplanten Ziel angekommen ist oder gegen eine Wand gekracht Dann ist da noch das Signal, das weggelassen wird, wenn die aktuell vom Chef beschlossene
Aktion abgeschlossen ist
und er entscheiden muss, was er als Nächstes tun wird Ich habe das
Richtungsänderungssignal an
die Hit-Box angeschlossen und die
Aufziehtasten Hurt Box, sodass sie umgedreht werden
können Das Hurt Box-Skript hatte diese Funktion
eigentlich nicht, also habe ich sie aus
dem Hit Boox-Skript kopiert Die Aufziehtaste
Hurt Box befindet sich jedoch hinter dem Boss, sodass ich
eine exportierte Variable hinzufügen musste um die Richtung
für diesen speziellen Fall umzukehren Zurück im Drehbuch der Mac-Maus brauchte
ich einen Verweis auf Körper
des Chefs, um ihn
zum rumpeln zu bringen Das wird also
in einer Variablen gespeichert, da ich
es sehr häufig verwenden werde Und natürlich muss
ich wissen, ob der Boss lebt oder tot ist. Ich möchte, dass mein Bosskampf mit
ausgeschalteter McMuse
beginnt und der Spieler die Aufziehtaste
mehrmals angreift , um ihn zu starten Also habe ich eine Variable deklariert, die angibt,
ob der Motor
gerade gestartet ist oder nicht , sowie eine
Geschwindigkeit für die Aufziehtaste, bei einem
Achtel der normalen Geschwindigkeit
gestartet wird, und einen Tween, mit dem ich die Geschwindigkeit im Laufe der
Zeit schrittweise
ändern kann die Geschwindigkeit im Laufe der
Zeit schrittweise
ändern Um diesen Effekt zu erzielen, habe ich die Animation der Aufziehtasten automatisch
abspielen lassen, allerdings mit einer Geschwindigkeitsskala von Null und die Hurt-Box ist
standardmäßig überwachbar Ich habe dann
das beschädigte Signal mit meinem Boss-Skript verbunden und eine
Funktion
namens On Key Um sicherzustellen, dass die
Verletzungsbox des Schlüssels niemals stirbt, nenne
ich sie ihre Wiederherstellungsfunktion, da dies nicht die Gesundheit
des Bosses widerspiegelt,
sondern lediglich ein weiteres Angriffsziel für den
Spielercharakter Nachdem ich die
Animationsgeschwindigkeitsskala der
Aufziehtasten auf das Doppelte eingestellt hatte, habe ich den Tween verwendet, um ihn
im
Laufe von 1 Sekunde
schrittweise auf den erwarteten Wert zu reduzieren Laufe von 1 Sekunde
schrittweise auf den erwarteten Wert Wenn die Engine
bereits gestartet wurde, Angriff auf die
Aufziehtaste dazu, dass die Mac-Maus auf den
Spielercharakter zustürmt als nächste Aktion Ansonsten habe ich
die Tastengeschwindigkeit verdoppelt und geprüft, ob sie
einen Wert von mindestens eins erreicht hat. Bei dem
Standardwert von einem Achtel passiert
das
erst, wenn der Aufziehschlüssel zum dritten Mal angegriffen wird. Wenn das passiert, habe ich
eine Funktion aufgerufen , um den Motor
der Mc-Maus zu starten. Diese Funktion weist lediglich
die Zahnradanimation an, mit der Wiedergabe
zu
beginnen, einen Rumble-Timer zu starten
, der auf eine
Zwöltelsekunde eingestellt ist, sodass der Motor variabel
auf True
gestartet wird und das Signal ausgegeben Jede Zwölfsekunde,
wenn der Timer das Timer abläuft, habe ich die Y-Position
des Körpers auf eine zufällige Ganzzahl
zwischen negativ
und positiv verschoben zwischen negativ
und positiv sodass der Körper auf und ab rumpelt Das Gesicht des Bosses nach links
zu setzen war sehr ähnlich wie beim Spielercharakter,
mit der Ausnahme, dass dieser Boss-Feind standardmäßig
nach links schaut Damit der Boss
herumfährt und auf
den Spielercharakter zustürmt, habe ich viele der gleichen
Bewegungsvariablen
im Charakterskript verwendet ,
nur mit unterschiedlichen Namen, und auch das Ziel des
Bosses
und die Entfernung zu seinem
Ziel als Floats aufgenommen , sodass ich sie verwenden kann,
um zu bestimmen, wohin der Boss im
physikalischen Prozess gehen muss. Ich habe auch die Schwerkraft für alle
Fälle mit einbezogen und die Bewegungsgeschwindigkeit standardmäßig auf
die Fahrgeschwindigkeit
eingestellt die Fahrgeschwindigkeit Ich habe die Räder in
einem Array gespeichert , damit ich sie einfach
synchronisieren kann. Dies mag zwar
für nur zwei Räder unnötig erscheinen, aber wenn Sie es auf diese Weise
schreiben, funktioniert es
für eine beliebige Anzahl von Rädern. Ich habe eine öffentliche
Variable verwendet, um zu sagen,
ob die Aufziehtaste dieser Mc-Maus
angegriffen
wurde und sie bereit ist, einen Ladeangriff
auszuführen und eine Ganzzahl, um zu
zählen , wie oft sie gegen eine Wand
gestürzt Als das Boss-Encounter-Skript entscheidet, dass sich die
Mc-Maus zu
einer Position innerhalb
der Boss-Arena bewegen soll , und die Position, zu der man
sich bewegen soll, als Parameter
angibt schnell zu überprüfen, ob der Boss
tot ist , sodass die
Anfrage ignoriert werden kann ,
habe ich das Ziel gespeichert ,
die Bewegungsrichtung und die Bewegungsgeschwindigkeit
festgelegt und
bewegt sich auf true. Ich habe eine private Funktion aufgerufen
, um alle Räder zu animieren, warte
dann auf mein eingehendes Signal, bevor ich das
fertige Signal ausgestrahlt Das eingegangene Signal wird später vom
physikalischen Prozess
ausgegeben Das Argument, das an
das Drehen der Räder übergeben wird, steuert,
wie
schnell sie animiert werden und ob die Animation vorwärts oder rückwärts abgespielt
wird Wenn also die Mac-Maus
nach links zeigt und sich nach links bewegt oder nach
rechts zeigt und sich nach rechts bewegt, spiele
ich die Animation
mit einer Geschwindigkeit von eins Andernfalls werden bei einer Geschwindigkeit von
minus Eins die
Animationen rückwärts abgespielt Ein Angriff auf den Spielercharakter bewirkt im Großen und Ganzen das Gleiche Ich möchte jedoch, dass die Mc-Maus immer
in die Richtung zeigt, in
die sie geladen wird, und
die Räder mit doppelter Geschwindigkeit durchdrehen. Mit einer kurzen Pause wird
die Ladung an
den Spieler telegraphiert , sodass er reagieren
und ihm aus dem Weg gehen kann Da es sich bei dem Angriff um einen Angriff handelt, ist
die
Überwachungseigenschaft der Hitbox auf true gesetzt Nachdem die Einstellung auf
true gesetzt ist, warte
ich auf das Signal, das
ausgegeben wird , nachdem die
McMuse gegen eine Wand
gekracht ist , und nutze eine weitere kurze Pause, um
den Boss
für einen kurzen Moment zu betäuben Denken Sie daran, das Signal im
eingegebenen Bereich
der Trefferboxen zu verbinden , um tatsächlich Schaden zu verursachen drehte die Räder
und akzeptierte die Richtung der
Drehung als Parameter.
Ich wiederholte jedes Rad in
meiner Radanordnung und
wies
jedes einzelne an, Ich wiederholte jedes Rad in
meiner Radanordnung und
wies
jedes einzelne seine Standardanimation abzuspielen , wobei
der absolute Wert
von Richtung als Animationsgeschwindigkeit verwendet der absolute Wert
von Richtung als wurde
und ob
die Richtung negativ
war oder nicht, um zu bestimmen, ob die Animation rückwärts abgespielt werden
sollte Ich habe auch
die
Emitter für Gesteins- und Staubpartikel, die an
jedem Rad angebracht waren, gleichzeitig gestartet die
Emitter für Gesteins- und Staubpartikel, die an
jedem Rad angebracht , wenn der Richtungswert
etwas anderes als Null war Andernfalls
werden sie ausgeschaltet. Nun zum physikalischen Prozess
, der
diese beiden Aktionen ermöglicht.
Wenn der Boss bereits tot ist, kann er sich nicht freiwillig bewegen, sodass seine Bewegungsrichtung auf Null gesetzt
wird Dann habe ich die X-Geschwindigkeit des
Bosses beschleunigt oder
gebremst und die Schwerkraft auf
seine Y-Geschwindigkeit angewendet , bevor ich die Bewegungs - und
Gleitfunktion
aufgerufen habe, um die Geschwindigkeit - und
Gleitfunktion
aufgerufen habe, um die des
Charakters anzuwenden Wenn der Boss
gerade fährt, muss
ich überprüfen, ob er sein Ziel
erreicht hat
oder ob er gerade aufgeladen wird und
gerade eine Wand berührt, dann weiß ich, dass er abgestürzt ist dann weiß ich Um zu wissen, ob der Chef sein
angestrebtes Ziel
erreicht hat , muss
ich zunächst die
Entfernung zu seinem Ziel ermitteln Das ist der absolute Wert des Ziels abzüglich der aktuellen
globalen Exposition des Chefs Formel für die
Sprunghöhe umkehren, können
wir feststellen, ob
der Endgegner nah
genug am Ziel
ist , um mit dem Abbremsen zu beginnen Wenn die Entfernung
kleiner ist als die Geschwindigkeit Quadrat geteilt durch die
Verzögerung geteilt durch zwei Wenn das wahr ist, höre ich auf, mich im Kreis zu
drehen,
setze die Bewegungsrichtung
auf Null, ist die Fahrtrichtung falsch und
gebe
das eingetroffene Signal Wenn der Boss
gegen eine Wand prallt, habe ich fast das Gleiche getan, aber ich habe auch die Geschwindigkeit
erhöht, damit sie
von der Wand weg abprallen Und die Hitbox ausgeschaltet. Ich habe auch gezählt, wie oft das passiert, und beim dritten Absturz wurde die
Panzerung der Mc-Maus
beschädigt, Panzerung der Mc-Maus
beschädigt sodass sie in die zweite Phase
übergehen kann. Wenn die Panzerung
durch zu viele Stürze beschädigt wurde, habe ich die Geschwindigkeit
der Aufziehtaste auf zwei erhöht Um die Panzerung zu beschädigen, musste ich
lediglich den Bereich des Spriteblatts
ändern,
der
vom Spriteknoten der Panzerung gezogen wurde der
vom Spriteknoten der Panzerung gezogen Außerdem habe ich die Geschwindigkeit der
Aufziehtaste und der Ausrüstungsanimationen sowie
des Rumble-Timers verdoppelt Ausrüstungsanimationen sowie
des , um
die Boss-Szene noch
instabiler zu machen die Boss-Szene noch Und ich habe die
überwachbare Eigenschaft der Hurt-Box auf true gesetzt, sodass der Spielercharakter jetzt den Körper
der Mc-Maus angreifen
kann ,
um ihm Schaden zuzufügen Dann habe ich das Signal ausgegeben, um den
Phasenübergang auszulösen. Um die Feuerbälle abzuschießen, brauchte
ich eine vollgepackte Szene
für die Feuerbälle sowie für die neuen Feuerbälle.
Ich würde den Marker instanziieren, wo sie instanziiert werden sollten ,
plus
das Fass und einen Tween,
um plus
das Fass Als der Boss aufgefordert wird, mehrere Feuerbälle
abzufeuern, habe ich zuerst darauf gewartet, den Lauf zu
verlängern, dann habe ich mehrere Male wiederholt, habe ich zuerst darauf gewartet, den Lauf zu
verlängern,
dann habe ich mehrere Male wiederholt, vor jedem Schuss eine
Viertelsekunde Pause dann einen Feuerball abgefeuert. Nachdem ich alle
Feuerbälle abgeschossen hatte, wartete
ich darauf, den Lauf zurückzuziehen, bevor ich das fertige Signal aussendete . Aus- oder
Einfahren des Fasses war ein einfacher Vorgang, bei dem
die Fässer im Abstand von X über eine Viertelsekunde auf die gewünschte Zahl gedreht Abfeuern eines einzelnen
Feuerballs ist fast das
Gleiche wie mit den Projektilen des Spielercharakters es einfach als Geschwister hinzu bringen Sie es an die
richtige Position und feuern Sie in die vorwärts
gerichtete Richtung ich in meinem Projektilskript Wenn ich in meinem Projektilskript einer
Hurt-Box anweise, Schaden zu nehmen, muss
ich auch
die Richtung des Schadens angeben Und wenn der Boss
keine Lebenspunkte mehr hat, verwende
ich Set Deferred, um die Trefferbox und
beide Hurt-Boxen
auszuschalten und alle Animationen zu beenden , bevor ich
das farbige Signal aussende , um
die Bossbegegnung zu beenden In der Szene mit dem Rauminhalt habe ich das
Signal zum Starten des Motors mit der
Startfunktion gegen den Endgegner und mit dem Signal
zum Beenden der zweiten
Begegnung verbunden Signal zum Starten des Motors mit der
Startfunktion gegen den Endgegner und mit dem Signal
zum Beenden der zweiten
Begegnung Startfunktion gegen den Endgegner und mit dem Signal
zum Beenden der Außerdem habe ich das Signal
„
Panzerung beschädigt“ mit der Funktion „Phase einstellen“ verknüpft und zwei als Argument verknüpft, zwei als Argument um den
Übergang zur zweiten Phase auszulösen. Ich habe den Aufruf
der Startfunktion auskommentiert, sodass ich den
Beginn des Kampfes nach
dem Start des
Motors auslösen konnte . Ja. Oh. jetzt Unser Chef führt
jetzt
eine komplexe Abfolge von Aktionen mit eskalierender
Intensität über mehrere Phasen Unserem Spiel fehlt jedoch jegliche
sinnvolle Weiterentwicklung. Wir sehen uns im
nächsten Abschnitt.
65. 9-1 Punkt speichern: Hallo Freunde. In diesem Abschnitt werden
wir diese
Zwei-D-Plattform in
ein Metroidvania verwandeln , indem wir den Fortschritt des Spielers richtig verfolgen Wir beginnen damit, unserem Spiel einen
Speicherpunkt hinzuzufügen. Ich habe meine
Begegnung mit dem Boss in eigenen Raum verschoben und sie
an die Seite meiner Karte in eine separate Vulkanregion Außerdem habe ich einen neuen Speicherraum für meine
Waldregion auf der linken Seite eingerichtet. Ich habe meinen
Spielercharakter hier oben gelassen. Ich setze ihre
Position einfach wieder auf den Ursprung zurück. Fangen wir mit den
Speicherdaten der Spieler an, wo wir den Ort speichern
müssen , an dem der Spieler sein Spiel zuletzt
gespeichert hat. Wie du diese Informationen speicherst hängt von der
Struktur deines Spiels ab. Aber für mein Spiel
verwende ich eine Reihe von Zeichenketten. Es mag zwar
effizienter sein, Speicherpunkte als Zahlen zu speichern, das ist nur eine einzige Variable, sodass die Auswirkungen
vernachlässigbar sein werden Es hilft auch,
die Speicherdatei
für Debugging-Zwecke lesbar zu halten die Speicherdatei
für Debugging-Zwecke lesbar zu Das erste Element
des Arrays ist der
Name der Region und das zweite ist
der Name des Raums Dieses Muster folgt der
Struktur meines Szenenbaums. Wenn ich die Speicherdaten der
Spieler lade, muss ich
nur
die Region finden , die mit
der ersten Zeichenfolge übereinstimmt, dann den Raum finden, der der zweiten Zeichenfolge
entspricht und den
Spielercharakter
am Speicherpunkt in diesem Raum positionieren . Beachten Sie, dass dieser Speicherpunkt im Spiel
zu dem Zeitpunkt
existieren sollte im Spiel
zu dem Zeitpunkt
existieren dem die Speicherdaten geladen
werden und noch
kein Rauminhalt geladen
wurde. Daher sollte sich das
Speicherpunktobjekt in der Raumszene und nicht in
der Rauminhaltsszene befinden. Ich füge
meiner gespeicherten Raumszene einen Knoten zwei D hinzu und
nenne ihn Savepoint Einfachheit halber platziere
ich diesen Knoten so, dass er sich an
der Position befindet, an der ich den Charakter spawnen
möchte Da wir mehrere
dieser
Speicherpunkte in unserem Spiel haben müssen , sollte
es
als eigene Szene gespeichert werden Wir können
es dann isoliert bearbeiten. Wie Sie Ihren
Speicherpunkt aktivieren möchten, liegt ganz bei Ihnen. Ich verwende einfach ein einfaches
Kollisionsereignis. Jedes Mal, wenn der Spieler einen Speicherpunkt
berührt, wird
sein Fortschritt gespeichert. Also füge ich der Szene einen D-Node mit zwei Bereichen hinzu und setze ihn
um 96
Pixel vom Boden ab , sodass der Spieler springen muss
, um ihn zu berühren. Ich habe einige Elemente
für meinen Speicherpunkt importiert handelt es
sich um ein Buch und auch um ein Effekt-Sprite, das ich hinter das Buch
zeichne, damit es leuchtet Ich füge dem Gebietsknoten ein Sprite mit zwei D-Nodes hinzu, um zuerst
den
Glüheffekt zu zeichnen Dann füge ein animiertes
Sprite mit zwei D für das Buch hinzu. Geben Sie ihm eine Sprite-Frames-Ressource und füllen Sie sie mit
den Die Animation vorwärts
und dann wieder rückwärts abspielen. Der Bereich benötigt eine
Kollisionsform, also gebe ich ihm einen Kreis und
verwende den Radius des Glühens
, der 32 Pixel beträgt Da es sich um die Raumszene nicht um die Rauminhaltsszene
handelt, muss sie
vor dem Rauminhalt angeordnet werden . Es muss nach dem Körper
des Spielercharakters Ausschau halten. Wenn anhängen ein Skript an den Speicherpunkt
anhängen, können
wir dann das vom Körper
des Bereichs
eingegebene Signal mit dem Skript verbinden eingegebene Signal mit dem Skript Wenn der Spielercharakter den Speicherpunkt
berührt, setzen
wir den Wert
von last saved at in seinen Speicherdaten
auf ein neues Array, wobei das erste Element des
Arrays der Name
der Region und das zweite
Element der Name des Raums Wir können diese Namen
mit dem Tag on ready automatisieren, da das übergeordnete Element
des Speicherpunkts immer der
Raum ist, in dem er sich befindet, und das übergeordnete Element des Raums immer
die Region ist. Aufgrund der Art des Szenenbaums , bei dem Geschwister eindeutige Namen haben
müssen wird sichergestellt, dass dies
ausreicht, um genau zu bestimmen, in welchem
Raum sie zuletzt gespeichert haben. Wir können uns auch einen Verweis
auf den Animated Sprite
Two D-Knoten holen und ihn anweisen, seine Animation
abzuspielen
, wenn das passiert Vergiss nicht,
dem globalen Dateiknoten mitzuteilen, dass er das Spiel
speichern soll , wann immer du
etwas Dauerhaftes erstellen möchtest Wenn wir zum
Game Manager-Skript wechseln, müssen
wir die zuletzt gespeicherte Position des
Spielers laden. Nachdem die gesamte
Initialisierung abgeschlossen ist, rufen
wir eine Funktion auf, um den Spielercharakter zu
positionieren Wenn die Speicherdaten des Spielers den Wert „Zuletzt gespeichert am“ haben, können wir die Region anhand ihres Namens ermitteln, da wir wissen, dass sie
ein untergeordnetes Element des Weltknotens ist Und dann machen Sie dasselbe,
um den Raum abzurufen, in dem
Wissen, dass der Raum
ein untergeordnetes Element der Region ist. Wir können
den Spielercharakter dann an der globalen Position des
Speicherpunkts in diesem Raum positionieren. Dadurch wird der
Spieler den Raum betreten, seinen Inhalt
laden und
erwartungsgemäß wieder einblenden. Wenn der Spieler noch keinen sicheren Punkt
erreicht hat, setze
ich ihn zum
Ausgangspunkt, um das Spiel zu starten. Ein Problem tritt jedoch auf, wenn der
Spieler stirbt, da wir
den Spielercharakter auch an die Position bringen wollen, die zu diesem Zeitpunkt zuletzt
gespeichert wurde . Sowohl die Death-Event-Sequenz
als auch der Spieler, der
einen Raum betritt , manipulieren gleichzeitig
den Fade Es gibt mehrere Möglichkeiten, dieses Problem
zu lösen, aber der Einfachheit halber werde
ich überprüfen, ob der
Spielercharakter seinem Tod den Raum wechselt Wenn sie sterben und
im selben Raum wieder erscheinen, wird der Spieler, der den
Raum betreten hat, nicht ausgelöst, sodass die Todessequenz das Ausblenden bewältigen
kann Andernfalls ersetze ich es
durch eine einfache Pause
für 1 Sekunde Um zu wissen, ob die
Neupositionierung des Spielercharakters den Raum verändert
hat, lasse
ich die Funktion einen booleschen Wert
zurückgeben Und kehre zurück, ob der
neue Raum mit dem aktuellen Raum
identisch ist oder ob er standardmäßig
falsch Lass es uns ausprobieren. Wenn
ich mein Spiel zum ersten Mal lade, startet
mein Charakter an der Standardposition
in meinem Startraum. Wenn ich nach links gehe, finde
ich den Speicherpunkt. Wenn ich zum Speicherpunkt springe,
wird mein Spiel gespeichert. Wenn ich das Spiel schließe
und erneut spiele, startet mein Spielercharakter
jetzt am Speicherpunkt. Um meinen Speicherpunkt
etwas magischer zu machen, lasse
ich ihn auf und ab schweben. Ich exportiere ein paar Variablen für den
Oszillationsbereich und Geschwindigkeit mit einer Standardeinstellung von 16 Pixeln und einer
Schwingung pro Sekunde Das Objekt, das
sich bewegen wird, ist der Area-Node, auch
die
Sprites als seine untergeordneten Objekte bewegt Ich muss seine
anfängliche Y-Position kennen und wissen, wie viel Zeit vergangen ist die Prozessfunktion außer Kraft zu setzen, setze
ich T auf sich
selbst plus Delta multipliziert mit der Schwingungsgeschwindigkeit zwischen Null
und Dadurch kann sich die Schwingung unendlich wiederholen
, ohne jemals das Maximum
einer
Fließkommazahl zu ohne jemals das Maximum
einer
Fließkommazahl zu erreichen. Die Y-Position des Bereichs
kann dann auf die
Ausgangsposition
plus den Sinus von
T multipliziert mit dem
Schwingungsbereich gesetzt Ausgangsposition
plus den Sinus von T multipliziert mit dem Um den
Speicherpunkt auf der Karte zu zeichnen, können
wir der Speicherpunktszene einfach
ein Sprite mit zwei D hinzufügen und
ihr
die Textur geben, die
wir zeichnen möchten Skalieren Sie es sehr groß, sodass es für die Kartenkamera sichtbar
ist, verstecken
Sie es dann, damit es nicht im Weg ist, und fügen Sie
das Kartensymbol-Skript Es muss sich
auf Sichtbarkeitsebene zwei befinden, nicht auf Ebene eins, und alle seine Vorfahren
im Szenenbaum müssen sowohl auf
Ebene eins als auch auf Ebene zwei sichtbar sein. Ich möchte auch das
Todesproblem testen, also füge ich meinem Spielercharakterskript eine einfache
Eingabefunktion hinzu. Wenn ich also die
Leertaste drücke, stirbt der Charakter. Wenn ich das Spiel jetzt starte, schwebt
der Speicherpunkt auf und ab, und ich kann ihn auf der Karte sehen. Wenn ich die Leertaste drücke, stirbt
der Charakter und
reagiert am Speicherpunkt. Wenn ich in einen anderen Raum
wechsle, kann ich es erneut tun und am
Speicherpunkt erneut
antworten. Wir haben jetzt einen Speicherpunkt
,
der sich die zuletzt gespeicherte Position des Spielers merkt und sie an der
richtigen Position lädt. Im nächsten Video werden
wir die Fähigkeit hinzufügen, Gegenstände
freizuschalten , die ein
Metroidvania ausmachen Wir sehen uns im nächsten Video.
66. 9-2 Metroidvania: Hallo Freunde. In diesem Video fügen
wir Gegenstände hinzu,
die der Spieler sammeln kann
, um seine
Metroidvania-Fähigkeiten freizuschalten Ich beginne damit,
einen neuen Szenenordner mit
dem Namen Upgrades zu erstellen einen neuen Szenenordner mit
dem Namen Dann dupliziere meine
gespeicherte Point-Szene, nenne sie Gem und lege sie in
den neuen Upgrade-Ordner. Dann öffne es, um es zu bearbeiten. Im Gegensatz zum Speicherpunkt möchte
ich nicht, dass dies auf meiner Karte dargestellt
wird Deshalb lösche ich das Kartensymbol. Es ist nicht erforderlich,
dass das Objekt vom Ursprung aus verschoben Deshalb setze ich die Position der
Gebietsknoten zurück. Machen Sie dann den Bereich zwei zu einem
D-Knoten, dem Wurzelknoten, benennen Sie ihn in GEM um und löschen Sie
den alten Save-Point-Knoten zwei D. Ich ersetze die
Sprite-Frames des Buchs durch neue,
zeichne einen rotierenden Edelstein. Lassen
Sie dann diese
Animation automatisch abspielen
und mit Lassen
Sie dann diese
Animation automatisch 12
Bildern pro Sekunde wiederholen Wir können dann ein neues
Skript für unsere Upgrades anhängen. die vom Körper
eingegebenen
Area-2-D-Nodes wieder verbinden , können wir die
neuen Fähigkeiten der
Spielercharaktere freischalten , wenn sie dieses Upgrade
berühren Dazu
exportieren wir eine Variable vom Typ Enums-Punkt-Fähigkeiten, das zuvor erstellte
Enums-Skript
verweist Dadurch entsteht ein praktisches
Drop-down-Menü im Inspektor, in dem
wir eine
unserer Fähigkeiten auswählen können, die wir für diesen
Upgrade-Gegenstand Denken Sie jedoch daran, dass eine Aufzählung nur eine Ganzzahl mit einem Namen
ist In meinem Spiel wird der Edelstein die Fähigkeit
des
Spielercharakters freischalten Fähigkeit
des
Spielercharakters Projektile
abzuschießen Zurück im Skript können
wir, wenn der
Körper des Spielercharakters diesen Bereich betritt, den Wert von
Datei, der
Körper des Spielercharakters diesen Bereich betritt, den Wert von
Datei, Punkt, Punkt „Fähigkeiten
freigeschaltet“ mit dem Index „
Fähigkeit“ auf „Wahr“ setzen Punkt, Punkt „Fähigkeiten
freigeschaltet“ mit dem Index „
Fähigkeit“ auf „Wahr Speichere dann das Spiel, um
dieses Upgrade dauerhaft zu machen. Damit sich das
wirkungsvoller anfühlt, werden
wir wahrscheinlich davor
und danach eine Menge
ausgefallener Sachen machen wollen und
diesen Knoten
dann irgendwann entfernen wollen, wenn wir fertig sind Wir können sicherstellen, dass bei diesem Knoten immer nur
ein einziges Kollisionsereignis eintritt indem wir set
deferred verwenden, um
seine Überwachungseigenschaft
nach der ersten Kollision auszuschalten seine Überwachungseigenschaft
nach In meiner Szene mit dem Inhalt von Speicherräumen lege
ich das irgendwo hin, damit ich es testen kann A
Ich wollte jedoch auf und ab schweben,
wie es der Speicherpunkt tut. Anstatt
den Code von einem
Skript in ein anderes zu kopieren und einzufügen , sollten
wir ihn zu
einer Komponente machen, die jeden Node Two D angehängt werden
kann, ähnlich wie die Enemy
Behavior-Skripte. Zurück in der Edelstein-Szene füge ich einfach einen normalen Node hinzu
und nenne ihn Float. Kopieren Sie dann den Code
aus dem Save
Point-Skript und fügen Sie ihn in dieses Skript ein. Anstatt eines Area-Tote-Knotens wird
dies lediglich der übergeordnete Knoten des
Float-Knotens
sein, allerdings muss es sich um einen No-Tutti-Node oder einen Vorfahren eines
No-Tutti-Nodes handeln, um eine Position zu haben Wir können diesen Knoten dann in
die Save Point-Szene kopieren und den Code aus
dem Save Point-Skript
entfernen Diese drei Skripte
sind viel besser wiederverwendbar, wenn sie nur für einen einzigen Zweck geschrieben
wurden.
Außerdem sind nur für einen einzigen Zweck sie leichter zu verstehen und
zu debuggen Eine weitere Sache, die wir tun
sollten, ist,
diesen Upgrade-Gegenstand B nicht hier zu haben , wenn der Spieler diese Fähigkeit bereits
freigeschaltet hat Indem wir die Bereitschaftsfunktion außer Kraft
setzen, überprüfen wir den Wert der freigeschalteten
Fähigkeiten in den Speicherdaten des Spielers, um zu sehen ob diese Fähigkeit bereits
freigeschaltet ist , und stellen diesen
Knoten in die Warteschlange, um freigegeben zu werden, falls
dies der Fall ist. Lass es uns jetzt ausprobieren. Wenn ich das Spiel starte,
sehe ich meinen Upgrade-Gegenstand dort
schweben. Das Drücken der Taste zum
Abfeuern von Projektilen funktioniert nicht, da ich diese Fähigkeit noch nicht
freigeschaltet habe hochspringe, um
den Upgrade-Gegenstand zu holen , verschwindet
er und ich kann
jetzt Projektile abschießen das Spiel
schließe und erneut spiele, ist
der Upgrade-Gegenstand nicht da, da ich ihn
bereits gesammelt habe, und ich kann immer noch Projektile
abfeuern da die Fähigkeit
dauerhaft freigeschaltet war Jetzt wollen wir dafür sorgen, dass sich das
Sammeln dieses Gegenstands Spieler viel
wirkungsvoller
anfühlt Um das zu testen, müssen
wir
unsere Speicherdaten löschen im Projektmenü Benutzerdatenordner
öffnen aus, Wählen Sie im Projektmenü Benutzerdatenordner
öffnen aus, um diesen Ordner in
Ihrem Dateimanager zu öffnen, wo wir
Speicherpunkte sehen und ihn löschen können. Wenn wir das Spiel jetzt starten, hat
der Spieler keine
zuletzt gespeicherte Position und es sind keine Fähigkeiten freigeschaltet. Ich gehe einfach zurück in
den Speicherraum und
klicke auf meinen Speicherpunkt.
Dann schließe ich das Spiel. Wenn Sie versuchen möchten, die Ereignissequenz
für das Sammeln des
Objekts selbst zu
erstellen , werden
Sie wahrscheinlich
Partikeleffekte oder andere
Knoten hinzufügen wollen , um Ihr Ergebnis zu erzielen. Halte das Video hier an
und dann gehen
wir nochmal durch, was ich gemacht habe. Nach der Implementierung
meiner Event-Sequenz sehen meine
Ergebnisse wie folgt aus. Zuerst habe ich eine konstante
Farbe für hellweiß erklärt. Das ist nicht nur weiß, sondern
hat auch eine maximale Intensität,
was bedeutet, dass auch andere
Farben fast weiß erscheinen. Wenn der Spielercharakter den Gegenstand
berührt, stoppe ich sofort
das Auf- und
Abschweben und friere den
Spielercharakter indem ich die Verarbeitung deaktiviere Dann habe ich einen
Partikelemitter gestartet,
der die Partikel aus der Umgebung
des Gegenstands emittiert und sich nach innen bewegt Dann führe den Gegenstand zur Position
des Spielercharakters zur Hälfte nach
oben, bis er sich in der Nähe
seiner Körpermitte befindet.
Gleichzeitig werden seiner Körpermitte befindet.
Gleichzeitig die Farben des Gegenstands und des
Charakters hellweiß getwebt Gegenstands und des
Charakters hellweiß Das Hinzufügen von Parallelen zu
einer Tween-Funktion bedeutet, dass diese alle
gleichzeitig ablaufen ,
anstatt zu
warten , bis eine fertig ist, bevor
mit der nächsten begonnen Dann schalte ich die Fähigkeit und speichere das Spiel
wie zuvor Und wenn die
Fähigkeit freigeschaltet ist, blende alle visuellen Elemente aus, stoppe die nach innen gerichteten Partikel, eine
nach außen gerichtete
Partikelexplosion aus
und aktualisiere das Sprite des
Charakters, und aktualisiere das Sprite des
Charakters den
neuen Gegenstand enthält Nachdem ich die Farbe des
Spielercharakters wieder auf normales Weiß gebracht
habe, schalte ich die Verarbeitung des
Spielercharakters wieder ein und entferne dieses
Objekt aus dem Die nach innen gerichteten Partikel verwenden dieselben Sprites wie
die Staubpartikel des
Chefs Sie werden
von einer Kugel mit
einem Radius von 32 Pixeln emittiert . Die Partikel haben eine
negative Radialgeschwindigkeit, um sie zum
Mittelpunkt zu
ziehen, keine Schwerkraft. Alpha krümmt sich um 1-0 und ist animiert. Nach außen gerichtete Partikel
sind im Großen und Ganzen
dieselben , außer dass es sich um eine
Explosion mit Explosivität Emittiert von einem Punkt mit maximaler Streuung und ausreichender Dämpfung, um die ursprüngliche Geschwindigkeit aufzuheben Wir haben jetzt
Sammelgegenstände in unserem Spiel, die dem Spieler neue
Möglichkeiten bieten, die Welt zu erkunden Aber es
würde viel mehr Spaß machen, unser Spiel zu erkunden, wenn es Abkürzungen gäbe Wir sehen uns im nächsten Video. Und
67. 9-3 Abkürzung: Freunde. In diesem Video fügen
wir eine Verknüpfung hinzu, die der
Spieler freischalten kann, um das
Erkunden unseres Spiels
reibungsloser und lohnender zu gestalten Erkunden unseres Spiels
reibungsloser und lohnender Ich werde den zweiten Raum rechts neben meinem Startraum verwenden ,
um meine Abkürzung in der Inhaltsszene des
zweiten Raums zu erstellen Ich habe den Raum
in zwei separate Hälften aufgeteilt
und platziere meine Abkürzung
in der Mitte, sodass
der Spieler
diesen Raum nicht durchqueren kann, wenn er ihn von links
betritt Ich beginne mit einem statischen Körper zur Kennzeichnung,
um Kollisionen zu erkennen, und einem Sprite
Toti-Knoten Ich verwende eine Atlas-Textur und bevölkere mein
Waldgelände als Atlas Dann zeichne ich mit den drei vertikalen
Kacheln eine Kollisionsform als Box hinzufüge und die Mauer
mit
einer Geländekollision überdecke, kann
der Spieler nicht durchkommen Wir können dann
mithilfe einer Atlas-Textur einen weiteren
Sprite-Tutti-Knoten hinzufügen , und ich habe bereits
ein neues Spritesheet
für eine Holzspange importiert ein neues Spritesheet
für eine Ich verwende das erste
unbeschädigte Sprite und positioniere es auf Wenn der Spieler diesen
Raum also von der rechten Seite betritt, kann er diese Stütze
angreifen,
sie
beschädigen und die
Mauer zerstören, um die Abkürzung zu öffnen Die Zahnspange benötigt
einen Hurt Box-Bereich zwei D-Knoten und ein untergeordnetes Objekt mit
Kollisionsform zwei D-Knoten Ich nehme eine andere Kastenform
und lasse sie das Sprite abdecken. O. Es wäre eine gute Idee, das auf
eine andere
Kollisionsebene zu legen , damit wir genau kontrollieren
können,
was es beschädigen kann Ich verwende Ebene zwei
für meine Abkürzungen. Vergessen Sie nicht,
Ihre Physik-Ebenen in
den Projekteinstellungen zu benennen , damit Sie sich merken können,
wofür sie gedacht sind. Wir müssen dafür sorgen, dass die männliche
Attack-Hitbox unserer
Charaktere diese Ebene maskiert ,
damit sie die Klammer beschädigen können Sowie alle Projektile, die
sie abschießen können. Zurück in der Rauminhaltsszene sollten
wir diese
Abkürzung zu einer eigenen Szene machen, da wir wahrscheinlich
mehrere davon in unserem Spiel haben Diese Abkürzung wird speziell nur
für die Waldregion erstellt. Also speichere ich es in diesem Ordner und muss weitere
Shortcut-Szenen für
meine anderen Regionen erstellen . diese Szene öffnen, können
wir das
Hurt-Box-Skript an
den Hurt-Box-Knoten den Hurt-Box-Knoten anhängen
und auch ein neues Skript für das Shortcut-Verhalten
an
den Stammknoten anhängen. Der Hauptzweck dieses Skripts , zu speichern, wenn
diese Verknüpfung
gelöscht wird , und sie beim Laden des
Rauminhalts
gelöscht zu lassen . Dazu verwenden wir
etwas, das allgemein als Flagge bezeichnet wird , indem wir
eine Zeichenkettenvariable
für den Namen der Flagge exportieren . In der Rauminhaltsszene müssen
wir einen
Flaggennamen für diese Tastenkombination angeben. Wir können dieser Flagge einen
beliebigen Namen geben, aber sie muss für
jede Tastenkombination in unserem Spiel eindeutig sein. Ich nenne meine Abkürzung Forest
Second Room. Wenn wir
zum Datenskript wechseln, benötigen
wir eine neue
exportierte Variable um unsere Flaggen
in einem Wörterbuch zu speichern. Wenn Sie die Zeichenfolge als
Schlüssel verwenden ,
wird der Wert ein boolescher Wert sein Zurück im Shortcut-Skript, wenn diese Verknüpfung gelöscht ist, können
wir den Wert der Punktmarkierungen für
Dateidaten so setzen , dass
der Schlüssel unser Flagname ist,
und den Wert auf true setzen Speichere dann das Spiel, um es
dauerhaft zu machen , und nachdem
du einige visuelle Dinge getan hast, entferne die Verknüpfung
aus dem Szenenbaum. die Ready-Funktion außer
Kraft setzen, können wir den
Wert unserer Flagge überprüfen um zu sehen, ob die Verknüpfung
bereits
zerstört wurde , und sie aus
dem Szenenbaum entfernen, falls dies der Fall war Wenn die Verknüpfung jedoch noch nicht gelöscht wurde,
enthält
das Wörterbuch noch keinen Wert für diesen
Flaggennamen Wir müssen also zuerst überprüfen, ob der Wert existiert,
bevor wir versuchen, darauf zuzugreifen. Lassen Sie uns das Signal, das die Hurt-Box erhalten hat, mit der Funktion
zum
Zerstören von Shortcuts verbinden und das Argument
entbinden Ich verlege den zweiten
Raum auf die linke Seite des Speicherraums,
damit ich ihn testen kann Wenn ich diesen Raum
von rechts betrete, verhindert
die Wand, dass mein Charakter
hindurchkommt. Ich kann die
Klammer angreifen, um sie zu zerstören, wodurch die Mauer zerstört wird, und ich kann sie durchqueren Wenn ich das Spiel schließe und
es erneut starte, bleibt
der Shortcut geöffnet Es gibt jedoch
ein kleines Problem. Ich ordne meine Räume neu sodass sich der zweite Raum
wieder auf der rechten Seite befindet, und lösche
dann meine sichere Datei,
um die Verknüpfung wiederherzustellen Ich führe das Spiel erneut aus. Die Mauer verhindert, dass mein Charakter
weitermachen kann. Ich kann
die Abkürzung jedoch immer noch von dieser Seite aus öffnen. Wir müssen also
verhindern, dass unser Charakter durch Wände
angreifen kann. die Charakterszene öffnen, können
wir der Trefferbox einen Cast Two
D-Node hinzufügen. Wir werden dieselbe Strategie anwenden, die wir bei feindlicher Aggression angewendet haben, um zu überprüfen, ob es eine klare Linie zwischen der Trefferbox
und der Verletztenbox gibt. Dazu muss der Strahl von der Mitte des
Charakters
ausgehen
und wir müssen
alles maskieren, was diese Trefferbox treffen kann
, sowie alles , was ihn
behindern kann, wie Gelände, also sowohl Körper als
auch Bereiche Der Strahl kann auch
innerhalb einiger
dieser Collider entstehen , also muss er in der Lage
sein, auch Bereiche
und Körper innerhalb
ihrer Formen zu treffen und Körper innerhalb
ihrer Formen Im Hit-Box-Skript können
wir einen Verweis auf
diesen gecasteten Knoten mit
dem Tag on ready abrufen , aber ich ändere den Knotenpfad so,
dass ich get node oder null verwende Auf diese Weise muss nicht an jede Hitbox in unserem Spiel
ein Raycast angehängt Wenn es zu einer Kollision kommt, überprüfen
wir zuerst, ob der
Strahl existiert, weisen den Strahl
dann
an, auf die Verletzungsbox zu zeigen , die von
der Trefferbox getroffen wurde, und erzwingen, dass sie
sofort aktualisiert Wenn der Strahl
auf etwas trifft und
es sich dabei um etwas
anderes als den Bereich handelt, bedeutet das, dass
etwas anderes im Weg ist. Durch die Rücksendung wird verhindert, dass der
Schaden entsteht. Wenn wir das Spiel jetzt starten, Angriff auf die Abkürzung von wird ein
Angriff auf die Abkürzung von
der falschen Seite
durch den Walls Collider blockiert Wenn ich diesen Raum nach
links bewege und ihn von rechts
betrete, kann
ich die Stütze angreifen und die Mauer
zerstören, da der Strahl, der aus
der
Trefferbox
des Charakters abgefeuert wird, nicht blockiert wird Wenn du willst, kannst du
hier eine Pause machen und Partikeleffekte hinzufügen, schütteln und sogar
mehrere Angriffe benötigen , um die Stütze zu durchbrechen, bevor du
die Wand
zerstörst Jetzt, wo ich meine Effekte hinzugefügt habe, sehen meine
Ergebnisse wie folgt aus Nach einem Angriff
gibt die Wand Staubpartikel ab, wackelt und die Stütze
ist Nach einem zweiten Angriff zerfällt die Zahnspange
in mehrere Teile, die Wand wird entfernt und die Partikel Um diesen Effekt zu erzielen, habe ich dem Knoten
GPU-Partikel hinzugefügt die dieselben
Staubpartikel
emittieren wie zuvor, diesmal
jedoch in Form
einer Box Ich habe einen
Trümmerknoten als Ordner hinzugefügt drei verschiedene
Teile als starre Körper
enthält. Und ein Shake-Timer, 12
Mal pro Sekunde ein Signal
aussendet. das
beschädigte Empfangssignal
der Hurt-Box mit einer beschädigten Empfangsfunktion verbunden , Ich habe das
beschädigte Empfangssignal
der Hurt-Box mit einer beschädigten Empfangsfunktion verbunden, den
Partikelemitter neu gestartet und
dann überprüft, ob zum ersten Mal beschädigt
ist Wenn die
Hurt Box bereits beschädigt ist, schalte ich die
Kollisionserkennung die
Kollisionserkennung aus und zerstörte die Wand Andernfalls setze Damage auf
true, aktualisiere die Klammer,
sprite, um die
beschädigte Version zu zeichnen, starte
dann den Shake-Timer
und stoppe ihn 1 Sekunde Das Timeout-Signal des Shake-Timers ruft diese Shake-Funktion auf, die die Wand lediglich um ein Pixel in einer
zufälligen Richtung versetzt ein Pixel in einer
zufälligen Als die Mauer zerstört wurde, habe ich die
Speicherdaten wie zuvor aktualisiert, aber auch einige Trümmer verstreut, sowohl die Wand als auch die
Stütze
versteckt Warten Sie dann, bis die Partikel
fertig sind, bevor Sie
die gesamte Szene entfernen Um die Trümmer zu zerstreuen,
habe ich sie sichtbar gemacht, dann alle Teile wieder
aufgetaut und ihnen
Impulskräfte hinzugefügt , ihrer Position im
Verhältnis zum Elternteil
entsprechen Wir haben jetzt eine Abkürzung, die
der Spieler öffnen kann, was das Zurückverfolgen bei der Erkundung unserer
Welt erheblich erleichtert Erkundung unserer
Welt Aber die gesamte Karte ist für sie
von Beginn des Spiels an deutlich sichtbar Wir sehen uns im nächsten Video.
68. 9-4 Karte: Hallo, Freunde. In diesem Video verstecken
wir unsere Karte
vor dem Spieler und enthüllen Räume
erst, wenn
der Spieler sie betritt. Ausgehend
von unserem Speicherdaten-Skript können
wir dieselbe
Strategie wie beim
Speicherpunkt anwenden , um zu verfolgen , welche Räume der
Spieler betreten hat. Wir exportieren eine neue Variable
mit dem Namen Map vom Typ Wörterbuch. Die Schlüssel dieses Wörterbuchs
werden die Namen von Regionen sein, und die Werte werden
ein anderes Wörterbuch sein. Die Schlüssel des
zweiten Wörterbuchs werden die Namen der
Räume in dieser Region sein,
und die Werte werden boolesche Werte sein, die angeben , ob der
Spieler diesen Raum betreten hat oder nicht Wenn wir in
einer unserer Raumszenen nachschauen, wird
die Karte von einer
Art Tu-Di-Knoten gezeichnet In meinem Spiel werden sie von einem Knoten auf der Ebene „Tile Map“
gezeichnet. Was auch immer der Knoten ist, es ist
ziemlich trivial,
seine Sichtbarkeit umzuschalten ist
ziemlich trivial,
seine Sichtbarkeit Wir werden einen Verweis
auf diesen Knoten in unserem Raumskript beschreiben auf diesen Knoten in unserem Raumskript Sie können das Ready-Tag verwenden, wenn der Kartenknoten
für alle Räume in
Ihrem gesamten Projekt einheitlich ist , oder ein Export-Tag, wenn Sie mehr Flexibilität
wünschen, aber Sie müssen es jedem Raum manuell
zuweisen. Außerdem muss jeder Raum den Namen der Region kennen,
in
der er sich befindet. Das können wir
mit einem Ready-Tag automatisieren, sodass der
Name des übergeordneten Knotens des Raums
in der Szenenstruktur abgerufen wird. Wir können dann eine Funktion schreiben
, um die Sichtbarkeit
der Karte zu aktualisieren , je nachdem, ob der Spieler diesen Raum schon einmal
betreten hat oder nicht. Punktdaten
der Datei überprüfen, die nach
dem Namen der Region indexiert dem Namen der Region erhalten wir ein weiteres
Wörterbuch für
die Region, das wir nach
dem Namen des Raums indexieren können Dies ist ein boolescher Wert, der angibt
, ob der Spieler
diesen Raum schon einmal betreten hat oder nicht Und wenn es wahr ist, werden wir die Sichtbarkeit
der Karte auf true setzen Sichtbarkeit
der Karte auf Aber genau wie beim
Flaggenwörterbuch müssen
wir aufpassen, dass wir
nicht versuchen, auf Wörterbucheinträge
zuzugreifen
, die nicht existieren. Dies bietet in diesem Fall jedoch eine zusätzliche
Möglichkeit, da wir das Fehlen
des Wörterbucheintrags als
zusätzliche Information nutzen können . Zum Beispiel können wir
überprüfen, ob das
Kartenwörterbuch einen
Eintrag für diese Region enthält. Wenn nicht, bedeutet das, dass der Spieler diese Region noch nie
betreten hat. Wenn der
Raumeingang nicht existiert,
weiß der Spieler ebenfalls nicht
, dass dieser Raum überhaupt existiert. Wir müssen zuerst überprüfen, ob der Regionseintrag
im Kartenwörterbuch existiert. Ist dies nicht der Fall,
sollte der Spieler diese Karte nicht sehen können
, und wir können diese Funktion einfach
verlassen. Machen Sie dann dasselbe mit
dem Raumeintrag im
Regionalwörterbuch. Wenn der Eintrag nicht
existiert, blende ich die Karte aus. Wenn er jedoch existiert, können wir
die Sichtbarkeit auf
true setzen und den Wert des
booleschen Werts überprüfen Wenn der boolesche Wert wahr ist,
stelle ich die Map-Modulation Alpha auf volle Opazität Aber wenn es falsch ist, stelle ich
es auf halbtransparent ein. Das heißt, ich kann
Räume auf der Karte, von denen
der Spieler weiß, von
denen unterscheiden der Spieler weiß, von , die er
zuvor betreten hat. Alternativ können Sie einen anderen Knoten verwenden, um
diese verschiedenen Zustände zu zeichnen und die Sichtbarkeit
jedes einzelnen Knotens
umzuschalten Wir können die Sichtbarkeit der Karte während
der Bereitschaftsfunktion initialisieren Karte während
der Bereitschaftsfunktion Wir können eine weitere Funktion schreiben, um einen Raum zu entdecken und seine Karte
anzuzeigen Um unsere beiden
unterschiedlichen Kartenstatus zu erstellen, können
wir einen
booleschen Parameter akzeptieren, der angibt ob dieser Raum
entdeckt wird, indem wir ihn betreten Diese Funktion
muss lediglich
den Wert der Datei mit den
Punktdaten Punkt Map, indexiert nach dem Namen der Region, indexiert
nach dem Namen des Raums, auf den Wert
Entered Wenn dieser Wert jedoch bereits existiert und auf true gesetzt wurde, möchten
wir
ihn nicht wieder auf false setzen Wir können die logische
Operation verwenden oder sie nur dann auf False
setzen, wenn
sie nicht bereits wahr ist. Rufen Sie dann die Funktion Sichtbarkeit der
Karte aktualisieren auf, um mit dem entsprechenden Zeichnen zu beginnen. Wenn die Region noch nicht im Kartenwörterbuch
existiert, ist
dies der erste Raum den der Spieler
in dieser Region entdeckt hat. Das wäre eine gute Gelegenheit etwas Interessantes
zu tun, wie zum Beispiel eine
Titelkarte vorzuzeigen oder
eine kurze Szene abzuspielen , um
den Spieler mit der neuen Region vertraut zu machen. Ich rufe eine Funktion
namens Discover auf, die noch nicht für die Region
geschrieben wurde. Dies wird für die
Initialisierung des
Kartenwörterbucheintrags für die Region verantwortlich sein Initialisierung des
Kartenwörterbucheintrags für die Region zum
Game Manager-Skript wechseln, können
wir, wenn der Spielercharakter einen neuen Raum
betritt, wenn der Spielercharakter einen neuen Raum
betritt, diesen Raum mit
einem Argument von true entdecken , um ihn undurchsichtig auf der Karte zu
zeichnen In der Hauptspielszene können
wir den Regionen unseres Spiels ein Skript
hinzufügen Beim Schreiben der Entdeckungsfunktion wird
diese aufgerufen, wenn
ein Spieler
zum ersten Mal einen
Raum in dieser Region betritt. Wir können also damit beginnen,
den Kartenwörterbucheintrag für
diese Region in den Speicherdaten des
Spielers zu erstellen den Kartenwörterbucheintrag für . Ich werde diese
Gelegenheit auch nutzen, um die Region
zur Karte des Spielers hinzuzufügen , indem ich
eine Funktion zum Einblenden von Karten aufrufe. Dadurch wird einfach durch
jeden Raum in dieser
Region iteriert und es entdeckt, allerdings mit dem Argument falsch, sodass es
halbtransparent dargestellt wird Dieses Skript muss an alle Regionen
angehängt werden. In jeder meiner Regionsszenen füge
ich außerdem einen Labelknoten , um den Namen
dieser Region auf der Karte anzuzeigen. Damit dieser Text
auf der Kartenkamera lesbar
ist, muss er eine
sehr große Schriftgröße haben. Ich setze die Schriftgröße auf 256. Stellen Sie dann die Schriftfarbe so ein, dass sie der Farbe der Räume
entspricht. Damit es besser zur Geltung kommt, füge
ich auch einen Schatten
und eine Kontur hinzu. Es muss sich
auf der zweiten Sichtbarkeitsebene befinden, damit die
Kartenkamera es sehen kann. Ich kopiere diese Beschriftungsnotiz in meine Vulkanregion und ändere ihre Textfarbe so, dass sie dieser Region
entspricht. zweiten Szene
der Region eine Leinwandebene hinzufügen, können
wir eine einfache
Titelkarte erstellen, die
angezeigt wird, wenn der Spieler die einzelnen Regionen zum ersten Mal betritt. Mit einem weiteren Label-Node werde
ich den Namen
dieser Region in großer Schriftgröße in der Mitte des Bildschirms
anzeigen. Ich mache das
standardmäßig unsichtbar und
zeige es nur an, wenn der Spieler diese Region
zum ersten Mal
betritt. Im Regions-Skript animiere ich diese
Anzeige mit einem Tween, Alphawert des
Label-Nodes auf eins hochsetze, eine Sekunde
warte und ihn dann wieder auf
Null heruntertweene Es muss einen Alphawert von
Null haben , um zu starten und
sichtbar zu machen Dies kann in
meine anderen Regionen kopiert und mit ihren Namen
aktualisiert werden. Wenn die Region entdeckt wurde, speichere
ich das Spiel und mache
die Kartenbeschriftung sichtbar. Dies muss auch in der
Ready-Funktion
initialisiert werden ,
je nachdem , ob der Regionseintrag im Kartenwörterbuch
existiert oder
nicht im Kartenwörterbuch
existiert Jetzt, wo Regionen untergeordnete Objekte haben,
bei denen es sich nicht um Räume handelt, muss
ich zunächst überprüfen,
ob es sich bei den Kindern tatsächlich um Räume
handelt,
bevor ich
deren Erkennungsfunktionen aufrufe .
Lass es uns ausprobieren. Wenn das Spiel beginnt,
betritt der Spieler automatisch die
Waldregion. Also wird die Titelkarte für die
Waldregion angezeigt. Die Kartendaten werden aufgedeckt, aber nur der
Startraum ist undurchsichtig ,
da das der einzige
Raum ist, den ich betreten habe Wenn ich jeden Raum betrete, wechseln
die Räume von
transparent zu undurchsichtig Ich habe die Abkürzung
aus dem anderen Raum entfernt , um die Dinge einfacher zu
machen Die Vulkanregion wurde noch
nicht betreten und ist
daher nicht auf der Karte
sichtbar. Und wenn ich
die Vulkanregion betrete, wird ihre Titelkarte angezeigt und ihre Räume werden der Karte
hinzugefügt. Obwohl ich noch nichts
Passendes für diese Region gebaut habe. Zurück zur Waldregion Die Region
wurde bereits entdeckt, weshalb ihre Titelkarte nicht
angezeigt wird. Wir verfügen jetzt über ein System
, mit dem Karte
unseres Spiels schrittweise angezeigt wird während der Spieler unsere Welt
erkundet. Aber die Regionen
unseres Spiels würden sich mit
etwas Hintergrundmusik
viel ausgeprägter anfühlen . Wir sehen uns im nächsten Video.
69. 9-5 Musik: Hallo Freunde. In diesem Video fügen
wir Hintergrundmusik , die sich mit
jeder Region in unserem Spiel ändert. Dies wird nicht nur
dazu beitragen,
das einzigartige Erscheinungsbild jeder Region hervorzuheben , sondern auch ein zusätzliches
Gefühl des Fortschritts vermitteln. Wenn du
Hintergrundmusik in dein Spielprojekt importierst, wähle die Dateien auf der Registerkarte „Dateisystem“ aus, öffne
dann die Registerkarte „ Importieren“ und
ändere den Loop-Modus auf „Vorwärts“. Andernfalls wird deine Musik
nur einmal abgespielt und dann gestoppt. Dies erfordert einen
Reimport der Assets. In jeder unserer Regionsszenen könnten
wir einen
Audio-Stream-Player-Knoten einrichten , um diese Musiktitel abzuspielen Aber dafür müssten wir
verwalten, welcher zu einem bestimmten Zeitpunkt
abgespielt wird, was ziemlich umständlich ist. Normalerweise möchten wir sowieso nicht, dass mehr als ein
Hintergrundmusiktitel mehr als ein
Hintergrundmusiktitel gleichzeitig abgespielt Es wäre also einfacher, nur einen
Audio-Stream-Player-Knoten
für das Abspielen von
Hintergrundmusik zu
haben , wir von
überall in unserem Spiel zugreifen können. Aber jede Region muss
trotzdem wissen , welche Hintergrundmusik für sie abgespielt werden
soll. In unserem Regions-Skript können
wir eine Variable exportieren, um
die Hintergrundmusik für diese
Region als Audiostream zu speichern . Füllen Sie dann die
exportierte Variable für jede Region in ihren
einzelnen Szenen mit unterschiedlichen Musikdateien Wir können dann
ein globales Skript
zur Verwaltung unserer Hintergrundmusik erstellen , vom
Audio Stream
Player übernommen Öffnen Sie dann die Projekteinstellungen, die Registerkarte Globals, und fügen Sie dieses Skript der
Liste der globalen Knoten hinzu Um zum Skript zurückzukehren, benötigen
wir eigentlich nur
zwei öffentliche Funktionen,
eine, die
das Skript anweist,
einen Musiktitel abzuspielen und den
Audiostream als Parameter zu akzeptieren,
und eine andere, die
Musikwiedergabe zu beenden Aber plötzlich die Musik zu beenden,
wäre ziemlich erschütternd. Es ist ziemlich üblich
, Musik auszublenden, indem man die Lautstärke
schrittweise reduziert, bevor man sie stoppt Beginnend mit der
Play-Track-Funktion können
wir den Stream, der
gerade abgespielt wird, auf
den Track-Parameter einstellen und
die
Wiedergabefunktion des Audio-Stream-Players aufrufen die
Wiedergabefunktion des Audio-Stream-Players , um die Wiedergabe zu
starten. Aber wenn bereits etwas
abgespielt wird ,
müssen wir es zuerst beenden. Wenn dieses Skript also bereits etwas
abspielt und das, was es spielt, das ist, was wir spielen
möchten,
können wir einfach zurückkehren. Wenn es nicht dasselbe ist,
können wir warten,
bis die Lautstärke wieder eingestellt ist Danach können wir zum neuen Titel
wechseln
und ihn wieder einblenden Um die Lautstärke schrittweise zu verringern, benötigen
wir ein Tween und eine Funktion zum
Tweenern der Lautstärke, endgültige Wert für
die Lautstärke als Parameter
akzeptiert Nachdem wir überprüft haben, ob das Tween bereits existiert, und es gelöscht
haben, erstellen wir ein neues
Tween und schalten die Lautstärke über einen gewissen Zeitraum auf ihren
Endwert Ich brauche nur 1 Sekunde. Die Lautstärke wird normalerweise in Dezibel
gemessen, was keine lineare
Maßeinheit ist Es wird daher nicht empfohlen, die Lautstärke in
Dezibel zu erhöhen. Stattdessen verwenden wir den
linearen Lautstärkewert,
bei dem es einen einfachen Gleitkommawert handelt, der
zwischen Null
für Stummschaltung und Eins
für normale Lautstärke reicht für Stummschaltung und Eins
für normale Wir können das
fertige Tween-Signal zurückgeben , sodass
wir darauf warten können Um die Musikwiedergabe zu beenden, müssen
wir nur warten, bis
die Lautstärke Null erreicht hat, dann Stop aufrufen und
das fertige Signal zurückgeben Und nachdem
wir zwischen den Titeln gewechselt haben, sollten wir die
Lautstärke wieder auf eins reduzieren, damit wir die neue Musik
hören können. Jetzt müssen wir
diesem Knoten nur noch mitteilen , welcher
Musiktitel wann abgespielt werden soll. Der Einfachheit halber gehe ich davon aus ,
dass ich beim Laden der
Inhalte eines Raums die Musik abspielen möchte , die
zu dieser Region gehört. also Music Play Track
nenne, übergebe ich die Region, die
dem Raumpunkt Music übergeordnet ist. Wenn ich aufgefordert werde, dieselbe Musik abzuspielen,
die bereits abgespielt wird, ignoriert
der globale Musikknoten die Anfrage
einfach. Sie müssen also nicht überprüfen,
was bereits abgespielt wird. Lass es uns ausprobieren.
Wenn ich das Spiel starte, fange
ich in der Waldregion an, und so wird das Thema
Waldmusik abgespielt. Wenn ich die Räume wechsle, ändert sich die Musik nicht, solange ich
noch in der Waldregion bin. Aber wenn ich zur
Vulkanregion übergehe, das
Thema Waldregion ausgeblendet und stattdessen wird das
Thema Vulkanregion abgespielt Es wird wahrscheinlich
Zeiten geben, in denen Sie einen bestimmten
Musiktitel vorübergehend
abspielen möchten , z. B. während einer
Zwischensequenz oder eines Bosskampfs Lassen Sie uns also unserem Musikskript zwei weitere
Funktionen hinzufügen. Eine, um den
aktuellen Musiktitel zu überschreiben ,
und eine andere
, um zum vorherigen Musiktitel zurückzukehren Wir benötigen eine Variable für
die Hintergrundmusik der aktuellen Region Wenn wir aufgefordert werden,
die Hintergrundmusik
durch einen neuen Musiktitel zu überschreiben , speichern
wir zunächst die
Hintergrundmusik der Region in unserer Variablen. Warten Sie dann auf das Ausblenden
und spielen Sie unseren neuen Titel ab. Nach Abschluss der Veranstaltung können
wir zur
Hintergrundmusik
unserer Region zurückkehren , indem wir den
alten Musiktitel ausblenden und
dann abspielen In unserem Boss-Encounter-Skript können
wir eine Variable exportieren, die
einen speziellen Musiktitel
für unsere Boss-Musik In der
Boss-Begegnung mit Mc-Mouse können
wir diesem Bosskampf dann einen
eigenen speziellen Musiktitel geben. Der globale
Musikknoten kann angewiesen werden, diese Musik
abzuspielen, wenn die
Bossbegegnung beginnt. Und kehrt zur Hintergrundmusik der
Region zurück ,
wenn der Kampf vorbei ist Und schließlich
sollte diesem Musikknoten mitgeteilt werden, zu welchem
Bus er
am Audiobus gehört , damit wir
seine Lautstärke in anderen
Einstellungen einfacher regeln können seine Lautstärke in anderen
Einstellungen einfacher regeln also die
Bereitschaftsfunktion außer Kraft setzen, können
wir den
Wert des Busses manuell auf Musik Wir haben jetzt ein globales
Musiksystem, mit dem wir jede Musik abspielen
können, die
wir für unser Spiel benötigen,
aber an unserer Begegnung mit dem Boss muss
noch etwas gearbeitet Wir sehen uns im nächsten Video.
70. 9-6 Endlicher Boss: Hallo Freunde. In diesem Video werden
wir die
Boss-Begegnung mit einer Arena abschließen und verhindern, dass der Boss
wieder erscheint, sobald er besiegt ist Ich habe meine
Räume neu angeordnet, sodass der
Spieler im Speicherraum
direkt neben dem Boss-Raum beginnt den Inhalt des Boss-Raums geöffnet Ich habe den Inhalt des Boss-Raums geöffnet und die Inhaltsszene
des Boss-Raums
mit mehreren Parallax-Layern aufgebaut Inhaltsszene
des Boss-Raums mit mehreren Parallax-Layern Damit der D-Knoten der Tile Map-Ebene zwei Parallax-Scrolling ausführen konnte
, musste
ich ein neues
Skript erstellen, das von der Ebene „
Tile Map“ ohne
Auto-Scroll übernommen Ebene „
Tile Map“ ohne Da der D-Knoten der
zweiten Ebene von Tile Map nicht über die Eigenschaft „Region
verwüstet“ verfügt, kann
er nicht dieselbe Methode verwenden wenn wir wollten, dass er Jeder Knoten zwischen den
Ebenen „Tile Map“ und „Di“ hat eine andere Bildlaufskala und moduliert mehr
zur Hintergrundfarbe hin Um zu verfolgen, welche Bosse
der Spieler besiegt hat, öffnen
wir das
Datenskript und fügen eine neue Variable mit dem Namen
Boss ist Eine Alternative zur Verwendung eines
Wörterbuchs ist ein Array. Jedes Mal, wenn ein Boss besiegt wird, können
wir einfach seinen
Namen an dieses Array anhängen Im Boss-Encounter-Skript können
wir die
Bereitschaftsfunktion überschreiben, um zu überprüfen, ob dieser Boss
bereits besiegt wurde Wenn die Datei Punktdaten Punkt Boss ist besiegt einen Eintrag hat, der dem Namen des Bosses
entspricht, dann hat der Spieler
diesen Boss
bereits besiegt und wir können
diese Bossbegegnung entfernen. Wenn der Boss besiegt ist, können
wir den Namen
des Bosses an die Liste der besiegten Bosse anhängen Bosse Speichere dann das Spiel, um es dauerhaft zu machen
. Im Gegensatz zu Wörterbüchern
können Arrays Duplikate enthalten. Wenn Sie also
Informationen auf diese Weise speichern, sollten
Sie überprüfen, ob der Eintrag bereits existiert Wenn Sie zu diesem Zeitpunkt den
Boss-Encounter-Knoten aus dem
Szenenbaum entfernen,
wird auch der Boss selbst entfernt, was ich
nicht tun möchte. Aber wenn der Spieler den Raum
verlässt und wieder hineinkommt, wird
der Boss
durch die Bereitschaftsfunktion entfernt. Das wird ausreichen,
um den Endgegner zu besiegen, aber die Begegnung selbst
könnte einige Verbesserungen gebrauchen. Das Erste, was ich tun möchte,
wenn der Bosskampf beginnt ist, eine Tür zu schließen, die den
Spieler in die Arena einsperrt. Genau wie bei der Abkürzung
habe ich einen statischen Körper verwendet, um den Knoten zu entfernen denselben
Wall-Sprite als Terrain wiederverwendet Und eine rechteckige Kollisionsform. Das Sprite und
die Kollisionsform befinden
sich jedoch weit über dem Ursprung der
Tür, sodass die Tür standardmäßig geöffnet ist Wenn sie aufgefordert wird, sich zu schließen, positioniert
die Tür
die Kollisionsform neu zwickt dann die
Position der Sprites entsprechend, und das Öffnen der Tür bringt die Kollisionsform
und
das Sprite wieder an ihre ursprünglichen Positionen zurück dieser Tür einen eindeutigen Namen geben, können
wir sie im
Encounter-Skript
des Bosses schließen , wenn der Kampf
beginnt, und sie öffnen, wenn der Kampf beginnt, und sie öffnen Denken Sie daran, die Funktionen der
Superklasse aufzurufen, um auch alles andere in den
Start- und Endfunktionen zu
erledigen Ich möchte auch, dass
der Boss
härter kämpft , indem ich brennende
Felsbrocken von der Decke fallen Also habe ich eine weitere Szene
für die brennenden Felsbrocken gemacht, denen es sich um einen starren
Körper mit zwei D-Knoten handelt Dadurch wird die Schwerkraft für mich automatisch
geregelt. Sie werden
von einem Animated
Sprite Two-D-Knoten
gezeichnet und animiert, der die
importierten Sprites
automatisch mit 12 Bildern pro
Sekunde durchläuft 12 Bildern pro
Sekunde Der starre Körper befindet sich auf einer neuen
Kollisionsebene, die
speziell für Gefahren vorgesehen ist und nichts Sie werden also
mit nichts kollidieren ,
auch nicht mit dem Gelände Sie fallen einfach von über der Arena nach unter die Arena und es ist eine Trefferbox angebracht,
die nach der Hurt-Box des
Spielercharakters Ausschau hält Vergiss nicht, dich mit dem
Signal
des betretenen Bereichs zu verbinden , um Schaden zu verursachen. In meinem Mc-Maus-Encounter-Skript habe
ich eine Variable exportiert, um
diesen brennenden Felsbrocken als vollgepackte Szene zu speichern ,
die ich
als neuen starren Körper mit
brennendem Felsbrocken instanziieren
kann neuen starren Körper mit
brennendem Als ich aufgefordert wurde,
flammende Felsbrocken zu spawnen, habe ich mehrmals
zufällig eine Schleife zwischen der
Phasenzahl und der Phasenzahl
mal zufällig eine Schleife zwischen der
Phasenzahl und der Phasenzahl zwei gemacht, sodass
die Anzahl der Felsbrocken in
der zweiten Phase der instanziiere einen neuen Felsbrocken, habe ihn der Szene hinzugefügt
und ihn über der Arena an einer zufälligen Position zwischen
der linken und rechten Wand positioniert Arena an einer zufälligen Position zwischen
der linken Ich instanziiere einen neuen Felsbrocken,
habe ihn der Szene hinzugefügt
und ihn über der Arena an einer zufälligen Position zwischen
der linken und rechten Wand positioniert. Um das Absturzereignis
noch eindrucksvoller zu machen, füge
ich auch Godot macht es ziemlich einfach, von überall auf die aktuelle
Kamera zuzugreifen Zuerst müssen wir nur die Funktion Get Viewport aufrufen und
dann
die Viewports
Get Camera Two D-Funktion aufrufen Wir können dann unsere
Shake-Funktion aufrufen, um die Kamera zu schütteln. Ich gebe ihr für eine
Viertelsekunde eine Intensität von zwei Pixeln. Ich kann dann das abgestürzte Signal der
Mc-Maus mit
dem Encounter-Skript verbinden , um als
Reaktion darauf das Spawnen
der brennenden Felsbrocken
auszulösen Reaktion darauf das Spawnen
der brennenden Felsbrocken Da es sich bei den Felsbrocken um starre Körper
handelt, fallen
sie aufgrund der Schwerkraft auf natürliche Weise herunter Dann kann ich sie, nachdem sie unter den Boden der Arena
gefallen sind, mit
einem Bereich
von zwei D
aufräumen unter den Boden der Arena
gefallen sind, mit
einem Bereich
von . Dieser
Müllsammelbereich ist nur ein rechteckiger Bereich , der den
Boden der Arena abdeckt, weit genug darunter, dass
alles, was in
diesen Bereich gelangt , für die Kamera nicht
sichtbar Der Bereichsknoten überwacht und maskiert die Gefahrenebene Sein vom Körper eingegebenes Signal
stellt eine Verbindung
zum MC-Mauszählerskript her zum MC-Mauszählerskript , um sie aus
dem Szenenbaum zu entfernen Aufgrund der Änderungen,
die an der Trefferbox
unseres Charakters vorgenommen wurden die Übertragung von der Hit-Box zur
Hurt-Box ungebremst sein musste, musste
ich den Schlüssel Hurt Box meiner
Mac-Maus neu organisieren Jetzt
bestimmt die Hurt-Box die Position
und die Kollisionsform befindet sich an
ihrer lokalen Da der D-Node
Area Two die
Position selbst bestimmt, muss
das Script nicht mehr auf die
Kollisionsform
verweisen, sondern
wechselt stattdessen seine eigene Position wenn der Charakter die Richtung
ändert Lass es uns ausprobieren. Ich gehe in mein Boss-Zimmer und finde meinen
Boss-Feind dort sitzen. Ich kann den Schlüssel angreifen, um
ihn aufzuziehen und die
Boss-Begegnung zu starten. Das löst den Beginn
meines Bosskampfes aus, der
die Musik verändert und die Tür zur
Arena zumacht, sodass ich darin gefangen bleibe Wenn ich gegen den Boss kämpfe, löst er
jedes Mal, wenn er gegen eine Wand prallt, ein Wackeln der Kamera aus und
es fallen brennende Felsbrocken Wir können zwar nicht sehen,
was mit
den brennenden Felsbrocken passiert , wenn
sie unter die Kamera fallen, aber sie werden gerade von
der Müllsammelstelle gereinigt Wenn der Boss in die zweite Phase eintritt
, erhöht sich
die Anzahl der gespawnten brennenden
Felsbrocken, und wenn der Boss besiegt wird,
endet die Begegnung, wodurch die Musik wieder zur Musik
der Vulkanregion zurückkehrt und
die Tür geöffnet Wenn Sie den Raum verlassen
und zurückkommen, ist die Begegnung mit
dem Boss Wir haben jetzt
alles, was wir brauchen, um ein ganzes
Metroidvania-Spiel zu entwickeln Im nächsten Video
gehen wir auf unsere nächsten Schritte ein. Wir sehen uns im nächsten Video.
71. 9:7 Finale: Hallo Freunde. Herzlichen
Glückwunsch zum Abschluss des Kurses. Du verfügst jetzt über alle
Werkzeuge und Fähigkeiten, die Erstellung eines
Metroidvania-Grundspiels
erforderlich sind, komplett mit freischaltbaren
Fähigkeiten, die dem
Spieler nach und nach Zugang zu weiteren Teilen der Welt ermöglichen, um
eine Karte zu erkunden, auf
der der aktuelle Standort
des Spielers angezeigt
wird Welt ermöglichen, um
eine Karte zu erkunden, auf
der der aktuelle Standort
des Spielers angezeigt aktuelle Standort
des Spielers und Punkte zu speichern, um seinen Fortschritt zu
verfolgen Jetzt müssen Sie nur noch viele der Lektionen wiederholen, die Sie im Laufe
des Kurses gelernt haben , um mehr davon zu erstellen Mehr Räume, mehr Regionen mit
mehr Feinden zum
Bekämpfen und
mehr Abkürzungen zum Freischalten. Folgen Sie diesen Schritten, um
mehr aus diesem
Kurs herauszuholen und weitere Fähigkeiten zu
erlernen, mit
denen Sie Ihr eigenes
Metroidvania-Spiel
erstellen können Ihr eigenes
Metroidvania-Spiel
erstellen Schritt eins. Wenn dies dein erstes
großes Spielprojekt ist, solltest
du in der Lage sein, ein Spiel nach
dieser Vorlage mit mindestens
drei verschiedenen Regionen zu
erstellen , jede mehrere Räume mit denen
jede mehrere Räume mit unterschiedlichen
Gegnertypen Plattform-Herausforderungen hat, und diese Regionen sollten sich voneinander
unterscheiden Gemäß den Prinzipien des
Metroidvania-Spieldesigns sollte
dein Spiel den Spielern Hindernisse vor Augen führen
, die sie nicht überwinden können,
bevor du die
Fähigkeit dazu freischaltest Der kritische Weg
durch das Spiel sollte eine
Rückreise durch
frühere Bereiche erfordern und dem Spieler
mehrere neue Möglichkeiten
bieten , ihn mit seinen neuen Fähigkeiten zu erkunden Versuche, ein Spiel zu entwickeln, das von Anfang bis
Ende mindestens 10 Minuten
dauert , ohne sich
zu sehr zu wiederholen Schritt zwei: Wenn Sie mit Ihrem Spiel
fertig sind und
eine größere Herausforderung suchen, möchten
Sie sich vielleicht
etwas einfallen lassen , das Sie ändern
möchten Vielleicht gefällt dir die Art und Weise nicht, wie
das Wandspringen funktioniert, oder du möchtest dem Angriff des
Spielercharakters Rückstoßkraft
verleihen dem Angriff des
Spielercharakters Versuche, eine Möglichkeit zu finden die Mechanik so
anzupassen, dass sie so funktioniert
, wie du es bevorzugst, und
ändere die Art und Weise, wie sie im Spiel
implementiert ist Versuche noch zu vermeiden,
etwas völlig Neues zu machen. Konzentrieren Sie sich einfach darauf, Anpassungen
an dem vorzunehmen, was bereits da ist. Schritt drei. Sobald Sie Änderungen
an den bereits vorhandenen Mechaniken
vornehmen können , sollten
Sie im nächsten Schritt
eine neue Mechanik hinzufügen ,
die die bereits bereitgestellten Tools verwendet Einige Dinge, die du
dem Spiel vielleicht hinzufügen möchtest, könnten ein
Sammelobjekt sein, das die
maximale Gesundheit des Spielers
erhöht, oder ein neuer Zauber,
der den Spielercharakter heilt Das Hinzufügen dieser Mechaniken
zum Spiel erfordert keine neuen Fähigkeiten, sondern erfordert, dass du
lernst,
mehrere bestehende Systeme auf neue Weise
miteinander zu integrieren mehrere bestehende Systeme auf neue Weise
miteinander Möglicherweise möchten Sie auch nach neuen Ressourcen suchen, die Sie
für Ihre neuen Mechaniken
verwenden können,
oder versuchen, Ihre eigenen zu entwickeln. Schritt vier. Jetzt, da Sie bestehende
Mechaniken nach Ihren Wünschen zum Laufen bringen und sie
in neue Systeme integrieren können , ist
es an der Zeit, eine neue Mechanik
von Grund auf neu zu entwerfen und zu
bauen Dies könnte eine völlig
neue Metroidvania-Fähigkeit sein , die es dem Spieler ermöglicht,
auf mehr Teile der Welt zuzugreifen, indem sie NPCs
hinzufügt, mit denen der Spieler über ein
Dialogsystem sprechen kann, Feinde
dazu bringt, Geld
fallen zu lassen, das der Spieler sammeln und es ihnen ermöglicht,
dieses Geld in einem Geschäft auszugeben, um ihre dieses Geld in einem Geschäft auszugeben, Bevor du anfängst, solltest du dir etwas Zeit
nehmen, um über all
die vorhandenen Systeme
nachzudenken , die
mit der
neuen Mechanik kommunizieren müssen mit der
neuen Mechanik kommunizieren müssen Überlegen Sie, welche Teile
Ihres Entwurfs
abstrahiert werden sollten oder welche von vorhandenen Skripten
übernommen werden können von vorhandenen Skripten
übernommen Fünfter Schritt. Wenn Sie ein
völlig neues System erstellen
und
es erfolgreich in dieses Spiel integrieren können , sollten Sie bereit sein, ein neues Spiel von Grund auf neu zu
erstellen. Suchen Sie entweder
online nach einem
anderen Asset-Paket oder erstellen Sie Ihre
eigenen Assets, denen Sie ein völlig
neues Metroidvania-Spiel von Grund auf nach Ihrem eigenen Design Du kannst deine
Arbeit gerne auf unserem Discord-Server teilen während du
mit diesem Projekt weiter lernst und deine Fähigkeiten
ausbaust Schritt sechs. Sobald dein Spiel fertig ist, kannst
du es auf
Plattformen wie Ich teilen, um Feedback von
Spielern zu erhalten und das Spiel sogar zu
verkaufen, wenn
es fertig ist. Du wirst wahrscheinlich nicht viel Geld mit
dem
Verkauf von Spielen auf IH verdienen , aber das Feedback wird für die Verbesserung deiner Fähigkeiten in der
Spieleentwicklung von
unschätzbarem Wert sein für die Verbesserung deiner Fähigkeiten in der
Spieleentwicklung von
unschätzbarem Wert Wenn du ein Spiel hast, das auf Ich gut abgeschnitten
hat, dann könntest du versuchen, es auf
Steam zu verkaufen , um ein viel
größeres Publikum zu erreichen Die Messlatte für die
Qualität eines Spiels
, das auf
Steam erfolgreich ist, ist jedoch viel höher. Und Sie benötigen
eine Marktstrategie, wenn Sie möchten, dass Ihr Spiel von den Spielern wahrgenommen
wird. Viel Glück beim Abschluss
Ihres Projekts. Ich freue mich auf
Ihre Arbeit.