In der modernen Webentwicklung verschwimmen die Grenzen zwischen klassischen und Webanwendungen täglich. Heute können wir nicht nur interaktive Websites, sondern auch vollwertige Spiele direkt im Browser erstellen. Eines der Tools, das dies ermöglicht, ist die Bibliothek – ein leistungsstarkes Tool zum Erstellen von 3D-Grafiken auf Basis von mithilfe Technologie. React Three Fiber- Three.js der React- Über den React Three Fiber Stack ist ein Wrapper für , der die Struktur und Prinzipien von nutzt, um 3D-Grafiken im Web zu erstellen. Mit diesem Stack können Entwickler die Leistungsfähigkeit von mit dem Komfort und der Flexibilität von kombinieren und so den Prozess der Anwendungserstellung intuitiver und organisierter gestalten. React Three Fiber Three.js React Three.js React Das Herzstück von ist die Idee, dass alles, was Sie in einer Szene erstellen, eine Komponente ist. Dadurch können Entwickler bekannte Muster und Methoden anwenden. React Three Fiber React- Einer der Hauptvorteile von ist die einfache Integration in das Ökosystem. Alle anderen Tools können bei Verwendung dieser Bibliothek weiterhin problemlos integriert werden. React Three Fiber React- React- Relevanz von Web-GameDev hat in den letzten Jahren große Veränderungen erfahren und sich von einfachen 2D- Spielen zu komplexen 3D-Projekten entwickelt, die mit Desktop-Anwendungen vergleichbar sind. Diese wachsende Beliebtheit und Leistungsfähigkeit machen Web-GameDev zu einem Bereich, der nicht ignoriert werden darf. Web-GameDev Flash- Einer der Hauptvorteile von Web-Gaming ist seine Zugänglichkeit. Spieler müssen keine zusätzliche Software herunterladen und installieren – klicken Sie einfach auf den Link in ihrem Browser. Dies vereinfacht den Vertrieb und die Werbung für Spiele und macht sie einem breiten Publikum auf der ganzen Welt zugänglich. Schließlich kann die Entwicklung von Webspielen eine großartige Möglichkeit für Entwickler sein, sich mit vertrauten Technologien im Gamedev zu versuchen. Dank der verfügbaren Tools und Bibliotheken ist es auch ohne Erfahrung in der 3D-Grafik möglich, interessante und qualitativ hochwertige Projekte zu erstellen! Spieleleistung in modernen Browsern Moderne Browser haben einen langen Weg zurückgelegt und sich von relativ einfachen Webbrowser-Tools zu leistungsstarken Plattformen für die Ausführung komplexer Anwendungen und Spiele entwickelt. Große Browser wie , , und werden ständig optimiert und weiterentwickelt, um eine hohe Leistung zu gewährleisten, was sie zu einer idealen Plattform für die Entwicklung komplexer Anwendungen macht. Chrome Firefox Edge andere Eines der wichtigsten Tools, das die Entwicklung browserbasierter Spiele vorangetrieben hat, ist . Dieser Standard ermöglichte Entwicklern die Nutzung der Hardware-Grafikbeschleunigung, was die Leistung von 3D-Spielen deutlich verbesserte. Zusammen mit anderen webAPIs eröffnet neue Möglichkeiten, beeindruckende Webanwendungen direkt im Browser zu erstellen. WebGL WebGL Dennoch ist es bei der Entwicklung von Spielen für den Browser wichtig, verschiedene Leistungsaspekte zu berücksichtigen: Ressourcenoptimierung, Speicherverwaltung und Anpassung an verschiedene Geräte sind allesamt wichtige Punkte, die den Erfolg eines Projekts beeinflussen können. Auf dein Zeichen! Allerdings sind Worte und Theorie eine Sache, praktische Erfahrung jedoch eine ganz andere. Um das volle Potenzial der Entwicklung von Webspielen wirklich zu verstehen und zu schätzen, ist es am besten, in den Entwicklungsprozess einzutauchen. Als Beispiel für eine erfolgreiche Entwicklung von Webspielen werden wir daher unser eigenes Spiel erstellen. Dieser Prozess wird es uns ermöglichen, wichtige Aspekte der Entwicklung kennenzulernen, uns echten Problemen zu stellen und Lösungen dafür zu finden und zu sehen, wie leistungsstark und flexibel eine Webspiel-Entwicklungsplattform sein kann. In einer Reihe von Artikeln schauen wir uns an, wie man mithilfe der Funktionen dieser Bibliothek einen Ego-Shooter erstellt, und tauchen in die aufregende Welt von Web-Gamedev ein! Letzte Demo https://codesandbox.io/p/github/JI0PATA/fps-game?embedable=true Repository auf GitHub Jetzt fangen wir an! Einrichten des Projekts und Installieren von Paketen Zunächst benötigen wir eine Projektvorlage. Beginnen wir also mit der Installation. React- npm create vite@latest Wählen Sie die Bibliothek aus. React- Wählen Sie aus. JavaScript Installieren Sie zusätzliche npm-Pakete. npm install three @react-three/fiber @react-three/drei @react three/rapier zustand @tweenjs/tween.js Dann alles Unnötige aus unserem Projekt. löschen Sie Abschnittscode Anpassen der Canvas-Anzeige Fügen Sie in der Datei ein div-Element hinzu, das auf der Seite als Bereich angezeigt wird. Fügen Sie eine Komponente ein und legen Sie das Sichtfeld der Kamera fest. Platzieren Sie innerhalb der Komponente die Komponente. main.jsx Canvas- Canvas- App- Fügen wir Stile hinzu, um die UI-Elemente auf die volle Höhe des Bildschirms auszudehnen und den Bereich als Kreis in der Mitte des Bildschirms anzuzeigen. index.css In der Komponente fügen wir eine Komponente hinzu, die als Hintergrund in unserer Spielszene in Form eines Himmels angezeigt wird. App- Sky- Abschnittscode Bodenfläche Erstellen wir eine Komponente und platzieren sie in der Komponente. Ground- App- Erstellen Sie in ein flaches Oberflächenelement. Bewegen Sie es auf der Y-Achse nach unten, sodass diese Ebene im Sichtfeld der Kamera liegt. Und drehen Sie die Ebene auch um die X-Achse, um sie horizontal zu machen. Ground Obwohl wir als Materialfarbe Grau angegeben haben, erscheint das Flugzeug komplett schwarz. Abschnittscode Grundbeleuchtung Standardmäßig gibt es in der Szene keine Beleuchtung, also fügen wir eine Lichtquelle hinzu, die das Objekt von allen Seiten beleuchtet und keinen gerichteten Strahl hat. Stellen Sie als Parameter die Intensität des Glühens ein. ambientLight Abschnittscode Textur für die Bodenoberfläche Damit die Bodenoberfläche nicht homogen aussieht, fügen wir eine Textur hinzu. Erstellen Sie ein Muster auf der Bodenoberfläche in Form von Zellen, die sich entlang der gesamten Oberfläche wiederholen. Fügen Sie im Ordner ein PNG-Bild mit einer Textur hinzu. Assets- Um eine Textur in die Szene zu laden, verwenden wir den Hook aus dem Paket. Und als Parameter für den Hook übergeben wir das in die Datei importierte Texturbild. Stellen Sie die Wiederholung des Bildes in den horizontalen Achsen ein. useTexture- @react-drei/drei- Abschnittscode Kamerabewegung Fixieren Sie mithilfe der Komponente aus dem Paket den Cursor auf dem Bildschirm, sodass er sich nicht bewegt, wenn Sie die Maus bewegen, sondern die Position der Kamera in der Szene ändert. PointerLockControls- @react-drei/drei- Nehmen wir eine kleine Änderung für die Komponente vor. Ground- Abschnittscode Physik hinzufügen Aus Gründen der Übersichtlichkeit fügen wir der Szene einen einfachen Würfel hinzu. <mesh position={[0, 3, -5]}> <boxGeometry /> </mesh> Im Moment hängt er nur im Weltraum. Verwenden Sie die Komponente aus dem Paket um der Szene „Physik“ hinzuzufügen. Als Parameter konfigurieren wir das Schwerkraftfeld, wobei wir die Gravitationskräfte entlang der Achsen einstellen. Physics- @react- three/rapier, <Physics gravity={[0, -20, 0]}> <Ground /> <mesh position={[0, 3, -5]}> <boxGeometry /> </mesh> </Physics> Allerdings befindet sich unser Würfel innerhalb der Physikkomponente, es passiert ihm aber nichts. Damit sich der Würfel wie ein echtes physisches Objekt verhält, müssen wir ihn in die Komponente aus dem Paket einbinden. RigidBody- @react-drei/rapier- Danach werden wir sofort sehen, dass der Würfel jedes Mal, wenn die Seite neu geladen wird, unter dem Einfluss der Schwerkraft herunterfällt. Aber jetzt gibt es eine andere Aufgabe – es ist notwendig, den Boden zu einem Objekt zu machen, mit dem der Würfel interagieren kann und über das er nicht hinausfällt. Abschnittscode Der Boden als physisches Objekt Kehren wir zur Komponente zurück und fügen eine Komponente als Wrapper über der Bodenoberfläche hinzu. Ground- RigidBody- Wenn der Würfel nun fällt, bleibt er wie ein echter physischer Gegenstand auf dem Boden. Abschnittscode Einen Charakter den Gesetzen der Physik unterwerfen Erstellen wir eine Komponente, die den Charakter in der Szene steuert. Player- Der Charakter ist das gleiche physische Objekt wie der hinzugefügte Würfel, daher muss er sowohl mit der Bodenoberfläche als auch mit dem Würfel in der Szene interagieren. Deshalb fügen wir die Komponente hinzu. Und lassen Sie uns den Charakter in Form einer Kapsel erstellen. RigidBody- Platzieren Sie die Komponente innerhalb der Physics-Komponente. Player- Nun ist unsere Figur auf der Bildfläche erschienen. Abschnittscode Einen Charakter bewegen – einen Hook erstellen Der Charakter wird mit den Tasten gesteuert und mit der springt er. WASD- Leertaste Mit unserem eigenen React-Hook implementieren wir die Logik zum Bewegen des Charakters. Erstellen wir eine Datei und fügen dort eine neue Funktion hinzu. „hooks.js“ „usePersonControls“ Definieren wir ein Objekt im Format {"Schlüsselcode": "auszuführende Aktion"}. Fügen Sie als Nächstes Ereignishandler zum Drücken und Loslassen von Tastaturtasten hinzu. Wenn die Handler ausgelöst werden, ermitteln wir die aktuell ausgeführten Aktionen und aktualisieren ihren aktiven Status. Als Endergebnis gibt der Hook ein Objekt im Format {"action in progress": "status"} zurück. Abschnittscode Einen Charakter bewegen – einen Hook implementieren Nach der Implementierung des Hooks sollte dieser zur Steuerung des Charakters verwendet werden. In der Komponente fügen wir die Verfolgung des Bewegungszustands hinzu und aktualisieren den Vektor der Bewegungsrichtung des Charakters. usePersonControls- Player- Wir werden auch Variablen definieren, die die Zustände der Bewegungsrichtungen speichern. Um die Position des Charakters zu aktualisieren, verwenden der vom Paket bereitgestellt wird. Dieser Hook funktioniert ähnlich wie und führt den Hauptteil der Funktion etwa 60 Mal pro Sekunde aus. wirFrame, @react-two/fiber- requestAnimationFrame Code-Erklärung: Erstellen Sie einen Link für das Player-Objekt. Dieser Link ermöglicht eine direkte Interaktion mit dem Spielerobjekt in der Szene. 1. const playerRef = useRef(); Wenn ein Hook verwendet wird, wird ein Objekt mit booleschen Werten zurückgegeben, das angibt, welche Steuertasten gerade vom Spieler gedrückt werden. 2. const { vorwärts, rückwärts, links, rechts, springen } = usePersonControls(); Der Hook wird in jedem Frame der Animation aufgerufen. Innerhalb dieses Hakens werden die Position und die lineare Geschwindigkeit des Spielers aktualisiert. 3. useFrame((state) => { ... }); Prüft, ob ein Spielerobjekt vorhanden ist. Wenn kein Spielerobjekt vorhanden ist, stoppt die Funktion die Ausführung, um Fehler zu vermeiden. 4. if (!playerRef.current) return; Ermitteln Sie die aktuelle lineare Geschwindigkeit des Spielers. 5. const Velocity = playerRef.current.linvel(); Stellen Sie den Vorwärts-/Rückwärtsbewegungsvektor basierend auf den gedrückten Tasten ein. 6. frontVector.set(0, 0, rückwärts – vorwärts); Legen Sie den Links-/Rechts-Bewegungsvektor fest. 7. sideVector.set(links - rechts, 0, 0); Berechnen Sie den endgültigen Vektor der Spielerbewegung, indem Sie die Bewegungsvektoren subtrahieren, das Ergebnis normalisieren (so dass die Vektorlänge 1 ist) und mit der Bewegungsgeschwindigkeitskonstante multiplizieren. 8. Direction.subVectors(frontVector, sideVector).normalize().multiplyScalar(MOVE_SPEED); „Weckt“ das Spielerobjekt auf, um sicherzustellen, dass es auf Änderungen reagiert. Wenn Sie diese Methode nicht verwenden, wird das Objekt nach einiger Zeit „schlafen“ und nicht auf Positionsänderungen reagieren. 9. playerRef.current.wakeUp(); Stellen Sie die neue lineare Geschwindigkeit des Spielers basierend auf der berechneten Bewegungsrichtung ein und behalten Sie die aktuelle vertikale Geschwindigkeit bei (um Sprünge oder Stürze nicht zu beeinträchtigen). 10. playerRef.current.setLinvel({ x: Direction.x, y: Velocity.y, z: Direction.z }); Als Ergebnis begann sich die Figur beim Drücken der Tasten in der Szene zu bewegen. Er kann auch mit dem Würfel interagieren, da es sich bei beiden um physische Objekte handelt. WASD- Abschnittscode Einen Charakter bewegen – springen Um den Sprung zu implementieren, verwenden wir die Funktionalität der Pakete und . In diesem Beispiel überprüfen wir, ob sich die Figur auf dem Boden befindet und die Sprungtaste gedrückt wurde. In diesem Fall legen wir die Richtung und Beschleunigungskraft des Charakters auf der Y-Achse fest. @dimforge/rapier3d-compat @react-drei/rapier Für werden wir Masse hinzufügen und die Rotation auf allen Achsen blockieren, damit er nicht in verschiedene Richtungen umfällt, wenn er mit anderen Objekten in der Szene kollidiert. den Spieler Code-Erklärung: Erhalten Sie Zugang zur Physik-Engine-Szene. Es enthält alle physischen Objekte und verwaltet deren Interaktion. const world = rapier.world; Rapier- Hier findet „Raycasting“ (Raycasting) statt. Es wird ein Strahl erstellt, der an der aktuellen Position des Spielers beginnt und entlang der y-Achse nach unten zeigt. Dieser Strahl wird in die Szene „geworfen“, um festzustellen, ob er ein Objekt in der Szene schneidet. const ray = world.castRay(new RAPIER.Ray(playerRef.current.translation(), { x: 0, y: -1, z: 0 })); Die Bedingung wird überprüft, wenn der Spieler am Boden liegt: constgrounded = ray && ray.collider && Math.abs(ray.toi) <= 1.5; – ob der erstellt wurde; Strahl Strahl – ob der Strahl mit einem beliebigen Objekt in der Szene kollidiert ist; ray.collider – die „Belichtungszeit“ des Strahls. Wenn dieser Wert kleiner oder gleich dem angegebenen Wert ist, kann dies darauf hindeuten, dass sich der Spieler nahe genug an der Oberfläche befindet, um als „am Boden“ zu gelten. Math.abs(ray.toi) Sie müssen auch die ändern, damit der Raytrace-Algorithmus zur Bestimmung des „Lande“-Status korrekt funktioniert, indem Sie ein physisches Objekt hinzufügen, das mit anderen Objekten in der Szene interagiert. Bodenkomponente Heben wir die Kamera etwas höher an, um die Szene besser sehen zu können. Abschnittscode Erster Commit Zweiter Commit Bewegen Sie die Kamera hinter die Figur Um die Kamera zu bewegen, ermitteln wir die aktuelle Position des Players und ändern die Position der Kamera jedes Mal, wenn das Bild aktualisiert wird. Und damit sich der Charakter genau entlang der Flugbahn bewegt, auf die die Kamera gerichtet ist, müssen wir hinzufügen. applyEuler Code-Erklärung: Die Methode wendet eine Drehung auf einen Vektor basierend auf angegebenen Euler-Winkeln an. In diesem Fall wird die Kameradrehung auf den angewendet. Dies wird verwendet, um die Bewegung relativ zur Kameraausrichtung anzupassen, sodass sich der Spieler in die Richtung bewegt, in die die Kamera gedreht wird. applyEuler Richtungsvektor Passen wir die Größe von leicht an und machen ihn im Verhältnis zum Würfel höher, wodurch wir vergrößern und die „Sprung“-Logik korrigieren. Player CapsuleCollider Abschnittscode Erster Commit Zweiter Commit Erzeugung von Würfeln Damit sich die Szene nicht völlig leer anfühlt, fügen wir die Würfelgenerierung hinzu. Listen Sie in der JSON-Datei die Koordinaten der einzelnen Würfel auf und zeigen Sie sie dann in der Szene an. Erstellen Sie dazu eine Datei , in der wir ein Array von Koordinaten auflisten. „cubes.json“ [ [0, 0, -7], [2, 0, -7], [4, 0, -7], [6, 0, -7], [8, 0, -7], [10, 0, -7] ] Erstellen Sie in der Datei eine Komponente, die Cubes in einer Schleife generiert. Und Komponente wird direkt zum generierten Objekt. Cube.jsx Cubes- die Cube- import {RigidBody} from "@react-three/rapier"; import cubes from "./cubes.json"; export const Cubes = () => { return cubes.map((coords, index) => <Cube key={index} position={coords} />); } const Cube = (props) => { return ( <RigidBody {...props}> <mesh castShadow receiveShadow> <meshStandardMaterial color="white" /> <boxGeometry /> </mesh> </RigidBody> ); } Fügen wir die erstellte Komponente zur Komponente hinzu, indem wir den vorherigen einzelnen Cube löschen. Cubes- App- Abschnittscode Importieren des Modells in das Projekt Nun fügen wir der Szene ein 3D-Modell hinzu. Fügen wir ein Waffenmodell für den Charakter hinzu. Beginnen wir mit der Suche nach einem 3D-Modell. Nehmen wir zum Beispiel . dieses Laden Sie das Modell im GLTF-Format herunter und entpacken Sie das Archiv im Stammverzeichnis des Projekts. Um das Format zu erhalten, das wir zum Importieren des Modells in die Szene benötigen, müssen wir das Zusatzpaket installieren. gltf-pipeline npm i -D gltf-pipeline Konvertieren Sie das Modell mithilfe des Pakets erneut vom in das , da in diesem Format alle Modelldaten in einer Datei abgelegt werden. Als Ausgabeverzeichnis für die generierte Datei geben wir den Ordner an. gltf-pipeline- GLTF-Format GLB-Format öffentlichen gltf-pipeline -i weapon/scene.gltf -o public/weapon.glb Dann müssen wir eine Reaktionskomponente generieren, die das Markup dieses Modells enthält, um es der Szene hinzuzufügen. Nutzen wir die der Entwickler. offizielle Ressource @react-two/fiber- Wenn Sie zum Konverter gehen, müssen Sie die konvertierte Datei laden. Weapon.glb Suchen Sie diese Datei per Drag & Drop oder per Explorer-Suche und laden Sie sie herunter. Im Konverter sehen wir die generierte Reaktionskomponente, deren Code wir in einer neuen Datei in unser Projekt übertragen und dabei den Namen der Komponente in denselben Namen wie die Datei ändern. WeaponModel.jsx Abschnittscode Anzeigen des Waffenmodells vor Ort Jetzt importieren wir das erstellte Modell in die Szene. Fügen Sie in der Datei Komponente hinzu. App.jsx- die WeaponModel- Abschnittscode Schatten hinzufügen Zu diesem Zeitpunkt in unserer Szene wirft keines der Objekte Schatten. Um in der Szene zu aktivieren, müssen Sie der Komponente das hinzufügen. Schatten Canvas- Schattenattribut Als nächstes müssen wir eine neue Lichtquelle hinzufügen. Trotz der Tatsache, dass bereits vor Ort ist, kann es keine Schatten für Objekte erzeugen, da es keinen gerichteten Lichtstrahl hat. Fügen wir also eine neue Lichtquelle namens hinzu und konfigurieren sie. Das Attribut zum Aktivieren des „ “-Schattenmodus ist . Das Hinzufügen dieses Parameters gibt an, dass dieses Objekt einen Schatten auf andere Objekte werfen kann. ambientLight DirectionalLight cast castShadow Danach fügen wir der ein weiteres Attribut hinzu, was bedeutet, dass die Komponente in der Szene Schatten auf sich selbst empfangen und anzeigen kann. Bodenkomponente „receiveShadow“ Ähnliche Attribute sollten anderen Objekten in der Szene hinzugefügt werden: Würfeln und Spieler. Für die Würfel werden wir “ und hinzufügen, da sie sowohl Schatten werfen als auch empfangen können, und für den Spieler werden wir nur hinzufügen. „castShadow „receiveShadow“ „castShadow“ Fügen wir für hinzu. castShadow Player Fügen Sie und für hinzu. „castShadow“ „receiveShadow“ Cube Abschnittscode Schatten hinzufügen – Schattenbeschneidung korrigieren Wenn Sie nun genau hinsehen, werden Sie feststellen, dass die Oberfläche, auf die der Schatten geworfen wird, recht klein ist. Und wenn man über diesen Bereich hinausgeht, wird der Schatten einfach abgeschnitten. Der Grund dafür ist, dass die Kamera standardmäßig nur einen kleinen Bereich der angezeigten Schatten von erfasst. Wir können für die Komponente durch Hinzufügen zusätzlicher Attribute diesen Sichtbarkeitsbereich erweitern. Nach dem Hinzufügen dieser Attribute wird der Schatten leicht unscharf. Um die Qualität zu verbessern, werden wir das Attribut hinzufügen. DirectionalLight DirectionalLight- „shadow-camera-“ (oben, unten, links, rechts) „shadow-mapSize“ Abschnittscode Waffen an einen Charakter binden Fügen wir nun die Ego-Waffenanzeige hinzu. Erstellen Sie eine neue , die die Verhaltenslogik der Waffe und das 3D-Modell selbst enthält. Waffenkomponente import {WeaponModel} from "./WeaponModel.jsx"; export const Weapon = (props) => { return ( <group {...props}> <WeaponModel /> </group> ); } Platzieren wir diese Komponente auf derselben Ebene wie den des Charakters und legen wir im Hook die Position und den Drehwinkel basierend auf der Position der Werte von der Kamera fest. RigidBody useFrame- Abschnittscode Animation des Waffenschwingens beim Gehen Um den Gang des Charakters natürlicher zu gestalten, fügen wir ein leichtes Wackeln der Waffe während der Bewegung hinzu. Zum Erstellen der Animation verwenden wir die installierte Bibliothek . tween.js Die Komponente wird in ein Gruppen-Tag eingeschlossen, sodass Sie über den Hook einen Verweis darauf hinzufügen können. Weapon- useRef- Fügen wir einen hinzu, um die Animation zu speichern. useState Lassen Sie uns eine Funktion erstellen, um die Animation zu initialisieren. Code-Erklärung: Erstellen einer Animation eines Objekts, das von seiner aktuellen Position zu einer neuen Position „schwingt“. const twSwayingAnimation = new TWEEN.Tween(currentPosition) ... Erstellen einer Animation des Objekts, das nach Abschluss der ersten Animation zu seiner Startposition zurückkehrt. const twSwayingBackAnimation = new TWEEN.Tween(currentPosition) ... Verbinden Sie zwei Animationen, sodass die zweite Animation automatisch startet, wenn die erste Animation abgeschlossen ist. twSwayingAnimation.chain(twSwayingBackAnimation); In rufen wir die Animationsinitialisierungsfunktion auf. useEffect Nun gilt es, den Zeitpunkt zu bestimmen, in dem die Bewegung stattfindet. Dies kann durch die Bestimmung des aktuellen Vektors der Richtung des Zeichens erfolgen. Wenn es zu einer Charakterbewegung kommt, aktualisieren wir die Animation und führen sie nach Abschluss erneut aus. Code-Erklärung: Hier wird der Bewegungszustand des Objekts überprüft. Wenn der Richtungsvektor eine Länge größer als 0 hat, bedeutet dies, dass das Objekt eine Bewegungsrichtung hat. const isMoving = Direction.length() > 0; Dieser Zustand wird ausgeführt, wenn sich das Objekt bewegt und die „schwingende“ Animation beendet ist. if (isMoving && isSwayingAnimationFinished) { ... } Fügen wir in der Komponente einen hinzu, in dem wir die Tween-Animation aktualisieren. App- useFrame aktualisiert alle aktiven Animationen in der Bibliothek. Diese Methode wird bei jedem Animationsframe aufgerufen, um sicherzustellen, dass alle Animationen reibungslos ablaufen. TWEEN.update() TWEEN.js- Abschnittscode: Erster Commit Zweiter Commit Rückstoßanimation Wir müssen den Moment definieren, in dem ein Schuss abgefeuert wird, also wenn die Maustaste gedrückt wird. Fügen wir hinzu, um diesen Zustand zu speichern, , um einen Verweis auf das Waffenobjekt zu speichern, und zwei Ereignishandler zum Drücken und Loslassen der Maustaste. useState useRef Lassen Sie uns eine Rückstoßanimation beim Klicken mit der Maustaste implementieren. Zu diesem Zweck verwenden wir die Bibliothek . tween.js Definieren wir Konstanten für die Rückstoßkraft und die Animationsdauer. Wie bei der Animation zum Wackeln der Waffe fügen wir zwei useState-Zustände für den Rückstoß und die Animation zur Rückkehr in die Ausgangsposition sowie einen Zustand mit dem Endstatus der Animation hinzu. Lassen Sie uns Funktionen erstellen, um einen zufälligen Vektor der Rückstoßanimation zu erhalten – “ und “. „generateRecoilOffset „generateNewPositionOfRecoil Erstellen Sie eine Funktion, um die Rückstoßanimation zu initialisieren. Wir werden auch hinzufügen, in dem wir den „Shot“-Status als Abhängigkeit angeben, sodass bei jedem Shot die Animation erneut initialisiert und neue Endkoordinaten generiert werden. useEffect Und in fügen wir eine Prüfung zum „Gedrückthalten“ der Maustaste zum Abfeuern hinzu, damit die Abfeueranimation nicht stoppt, bis die Taste losgelassen wird. useFrame Abschnittscode Animation bei Inaktivität Realisieren Sie die Animation der „Inaktivität“ für den Charakter, sodass nicht das Gefühl entsteht, dass das Spiel „hängt“. Dazu fügen wir über einige neue Zustände hinzu. useState Lassen Sie uns die Initialisierung der „Wackel“-Animation korrigieren, um Werte aus dem Zustand zu verwenden. Die Idee ist, dass verschiedene Zustände (Gehen oder Anhalten) unterschiedliche Werte für die Animation verwenden und jedes Mal die Animation zuerst initialisiert wird. Abschluss In diesem Teil haben wir Szenengenerierung und Charakterbewegung implementiert. Wir haben außerdem ein Waffenmodell und eine Rückstoßanimation beim Schießen und im Leerlauf hinzugefügt. Im nächsten Teil werden wir unser Spiel weiter verfeinern und neue Funktionen hinzufügen. Auch veröffentlicht. hier