Wie ich Recycle erstellt habe! VR



Im vorherigen Artikel haben wir versucht, eine grundlegende Szene in A-Frame zu erstellen, um die grundlegenden Konzepte des Frameworks in der Praxis auszuprobieren. In diesem Artikel möchte ich meine Erfahrungen bei der Erstellung eines Spiels auf A-Frame - Recycle! VR Das Projekt-Repository ist unter folgendem Link verfügbar.

Recycling !?


Die Idee, ein Spiel zu erstellen, kam fast sofort, als ich von Web VR erfuhr. Obwohl ich im Allgemeinen glaube, dass Spiele im Internet guten Projekten auf jeden Fall unterlegen sind, selbst für mobile Geräte, ganz zu schweigen von PCs und Konsolen. Aber es scheint mir, dass das Spiel der schwierigste Test ist. Ich begann genau darüber nachzudenken, was ich tun kann. Ich habe mir andere Projekte angesehen und war sofort beeindruckt von der Möglichkeit, mit dem Controller etwas aufzunehmen. Und da ich seit einiger Zeit mit einer Organisation verbunden bin, die sich mit der getrennten Müllabfuhr befasst, kam die Antwort von selbst. Recycling. Wir nehmen den Müll und werfen ihn in den Müll. Was könnte einfacher sein. Aber alles stellte sich als nicht so einfach heraus, und dies wird in der Tat weiter diskutiert.

Rahmenauswahl


Zum Zeitpunkt des Beginns der Arbeit am Spiel kannte ich nur zwei mehr oder weniger ernsthafte Frameworks: React 360, A-Frame. Offensichtlich war A-Frame am besten für die Erstellung des Spiels geeignet. Ja, jetzt weiß ich, dass es noch eine PlayCanvas-Spiel-Engine gibt, die auch VR unterstützt, aber es ist zu spät. Darüber hinaus stellte sich heraus, dass A-Frame auch nicht schlecht für die Erstellung von Spielen ist.

Wo soll ich anfangen?


Ich begann damit, offizielle Spielbeispiele von A-Frame-Entwicklern zu studieren. Der Nutzen davon reicht nicht aus. A-Blast, A-Painter, Museum, Super Craft und jetzt auch Gunters of Oasis. Von allen vorgestellten Projekten mochte ich A-Blast am meisten - einen Shooter, in dem man mit den süßesten Kreaturen im Universum kämpfen muss. Deshalb wollte ich dieses Spiel als Vorlage für mein Spiel nehmen. Aber es hat nicht geklappt. Und der Grund dafür war die Struktur des Spiels. Es schien mir, dass sie zu überladen und nicht durchdacht war. Vielleicht ist mehr nicht erforderlich, aber ich wollte etwas bequemeres und verständlicheres tun.

Struktur


Die A-Blast- Struktur stellt nur einen Einstiegspunkt dar - die Datei index.html, die eine Szene mit allen Assets, grundlegenden Spielentitäten, Steuerelementen und allem im Allgemeinen enthält.



Wie Sie im Screenshot sehen können, gibt es neben den erforderlichen Komponenten und Systemen (A-Frame verwendet das Muster des Entity Component System) auch Kugeln und Feinde - im Wesentlichen dieselben Systeme, aber aus irgendeinem Grund haben sie einen eigenen Wrapper. Sagen Sie im Allgemeinen, dass dieser Code nicht leicht zu verstehen ist. Also habe ich mich überlegt, wie dieser Code strukturiert werden kann. Die erste Idee ist, die Szene in ihre Bestandteile zu zerlegen. Warum sollten ein Router und Vorlagen nützlich sein, um diesen oder jenen Teil der Szene zu rendern? Nachdem ich nach der ersten und zweiten gesucht hatte (nein, nicht fünf Minuten), fand ich nichts. Obwohl ich ein Befürworter der Regel bin, schreibe keine Fahrräder, aber diesmal musste ich meine Entscheidung schreiben. Obwohl ich irgendwo in 2-3 Wochen auf Vorlagen von Kevin Ngo gestoßen bin. Aber es war zu spät.

Router und Muster




Und so betreten A-Frame-Router-Vorlagen die Szene. Was kann er tun? Wie oben erwähnt, besteht seine Hauptaufgabe darin, die erforderlichen Teile des Spiels zu rendern, z. B. den Titelbildschirm, das Spielfeld, den Endbildschirm des Spiels usw. Wie kann man das machen? Grundsätzlich finden Sie alles, was Sie brauchen, in der Dokumentation zum Modul auf github, aber kurz gesagt, wir haben folgendes:

<a-scene router> ... <!-- Routes --> <a-route id="start-screen" template="start-screen"></a-route> <a-route id="game-field" template="game-field"></a-route> <a-route id="game-over" template="game-over"></a-route> <a-route id="how-to-play" template="how-to-play"></a-route> <!-- End Routes --> ... <!-- Templates --> <a-template name="controls"></a-template> <!-- End Templates --> ... </a-scene> 

  1. Wir fügen der Szene die Routerkomponente hinzu.
  2. Fügen Sie für jeden Teil der Anwendung (Szenenbilder) eine Route hinzu. Eine Route für den Startbildschirm, eine andere für das Spielfeld usw.
  3. Rendern Sie Vorlagen direkt über a-Vorlagen
  4. Bei Bedarf ändern wir die Routen durch

     this.el.systems.router.changeRoute('game-field'); 

    Hinweis : Dieses Beispiel bezieht sich auf den Szenencode, sodass wir das Routersystem direkt aufrufen können.
  5. Wir setzen und verbinden die Vorlagen, ungefähr so:

     AFRAME.registerTemplate('game-field', ` <a-sub-assets> <a-asset-item id="glass" src="/assets/models/glass_bottle.gltf"></a-asset-item> ... <audio id="fail" src="/assets/sounds/fail.wav" preload></audio> </a-sub-assets> <a-template name="button" options="text: EXIT; position: 0 1 4; rotation: 0 180 0; event: stop-game"></a-template> <a-entity id="indicator" indicator visible="false" position="0 1 -2" text="align: center; width: 4; color: #00A105; value: -1" ></a-entity> <a-entity game-field-manager></a-entity> `); 

    Hinweis: Mit a-sub-Assets können Sie sowohl Assets als auch a-Assets laden, jedoch nur mit dem Unterschied, dass standardmäßig eine Prüfung erfolgt. Wenn das Asset bereits hinzugefügt wurde, wird es beim Ändern der Route nicht erneut hinzugefügt.

    Hinweis 2: Normalerweise können Sie Vorlagen nur mit ES6-Vorlagenzeichenfolge verwenden. Andernfalls kann es zu "string" + var + "string" werden, nicht cool. Kevin unterstützt beispielsweise Template-Engines. Aber warum sollte man es komplizieren?

Auf diese Weise können Sie eine praktische Anwendungsstruktur erstellen, die Folgendes enthält: Komponenten, Systeme, Vorlagen, Status, Bibliotheken . Nichts mehr und alles steht in den Regalen.

Objekte manipulieren




Die allererste Aufgabe, die gelöst werden sollte, war die Manipulation von Objekten. Ich brauchte einen funktionalen Greifer. Anfangs begann ich darüber nachzudenken, wie man eine solche Komponente von Grund auf neu erstellt. Rein auf philistischer Ebene ist eine solche Reflexion zulässig: Wir haben einen Controller (im Fall eines Desktops ist es ein Cursor), er hat eine Position. Wir haben auch bestimmte Objekte, zum Beispiel Würfel, sie haben auch eine Position. Durch Ändern der Position des Controllers müssen wir die Position des Objekts ändern. Ist es einfach Also ja, aber es wird nicht funktionieren. Ich werde einige Punkte aus einer sehr langen Liste erwähnen, um Sie davon zu überzeugen:

  • Der Cursor in A-Frame ist ein Nachkomme einer Kamera und hat relative Koordinaten.
  • Die Position des Controllers reicht nicht aus. Sie müssen dennoch die Ausrichtung, den Abstand zum Objekt und die Position der Kamera (des Players) berücksichtigen.
  • Bei Objekten mit einem physischen Körper funktioniert dies überhaupt nicht, da die Koordinaten der Geometrie mit den Koordinaten des Körpers verbunden sind.

Es ist gut, dass der gute Mr. Wil Murphy und seine Freunde A-Frame-Super-Hände gemacht haben . Im Wesentlichen enthält diese Bibliothek alle erforderlichen Komponenten:

  • schwebbar . Anleitung. Zeigen Sie mit dem Controller oder Cursor auf die Kollisionszone des Objekts (normalerweise das gesamte Objekt).
  • greifbar : Erfassen. Nehmen Sie ein Objekt mit der entsprechenden Schaltfläche und ziehen Sie es
  • dehnbar : Mit beiden Händen greifen und dehnen
  • draggable \ dropable : Wird im Wesentlichen benötigt, um das Ereignis "Das Objekt wurde an einen bestimmten Ort geworfen" zu bestimmen.

Im oben genannten Repository finden Sie alles, was Sie zum Einrichten und Verbinden von Superhänden benötigen. Ich möchte nur auf eine Reihe von Nuancen aufmerksam machen:

  • Erstellen Sie separate Mixins für die rechte und linke Hand. Trennen Sie die Komponenten nach Art der unterstützten Geräte. Zum Beispiel kann die rechte Hand zusätzlich zu Oculus-Touch, Vive-Steuerungen, Windows-Bewegungssteuerungen auch Oculus-Go-Steuerungen und Gear-VR-Steuerungen geben. Die linke Hand muss für BP-Helme versteckt sein. Jeder Controller muss sowohl Mixin-Hände als auch eine Super-Hands-Komponente enthalten. Ein Beispiel ;
  • Wenn Sie Objekte angegeben haben: .clsname für reycaster, vergessen Sie nicht, es jedem Element hinzuzufügen, das mit dem Controller übernommen werden kann. Andernfalls schlägt kein Ereignis für Superhände fehl. Natürlich, wenn colliderEvent: Raycaster-Schnittpunkt ;
  • Durch Ziehen mit der Maus werden 2D-Koordinaten in die 3D-Welt projiziert. Verwenden Sie daher besser den Cursor für den Desktop.

Physik hinzufügen


Das Hinzufügen von Physik zu einem Frame ist eigentlich sehr einfach. Hierfür gibt es ein spezielles System . Es wird der Szene hinzugefügt und voila, Physik ist bereits in Ihrer Tasche.

 <a-scene physics="debug: false"> <a-box dynamic-body position="0 1 -2"></a-box> <a-box id="floor" static-body></a-box> </a-scene> 

Mark : debug: true ermöglicht die Anzeige von physischen Körpern, die an Geometrie gebunden sind. Dies ist praktisch, wenn Sie ein Objekt „skizzieren“ müssen.

Tatsächlich ist dies ein Wrapper für cannon.js , der die ganze Drecksarbeit erledigt , Geometrie und physische Körper für Sie zu vergleichen. Informationen zur Funktionsweise dieses Systems finden Sie in der Beschreibung des Repositorys. Und ich möchte nur auf einen Punkt eingehen, der für mein Spiel wichtig ist.

Ich musste sicherstellen, dass durch Drücken der Taste auf den Papierkorb eine bestimmte Kraft eingestellt wurde (je mehr Sie die Taste gedrückt halten, desto größer ist die Kraft). Wie sich herausstellte, ist diese Aufgabe nicht so einfach, wie es auf den ersten Blick scheint. Was ist so kompliziert? - Sie sagen, wir bewerbenImpluse und Voila. Nicht wirklich ... Es legt die Drehung eines Objekts entlang eines Vektors fest, der auf die Körpermitte angewendet wird. Mit dieser Methode können wir nur ein Weihnachtsfest emulieren. Wenn Sie jedoch einen Vektor mit dem richtigen Winkel zur Ebene festlegen, erhalten Sie möglicherweise etwas Ähnliches wie einen Push. Aber das brauchte ich nicht.

Wie sich herausstellte, brauchte ich Geschwindigkeit, um diesen Parameter einzustellen. Das Objekt beginnt seine Bewegung in eine bestimmte Richtung. Diese Richtung wird durch den Vektor angegeben. Und hier beginnt der Spaß. Wie finde ich diesen Vektor? Ich habe zwei Möglichkeiten gefunden:

  1. Holen Sie sich das Quaternion des Controllers (oder der Kamera für den Desktop), das seine Ausrichtung im Raum beschreibt. Erstellen Sie einen Vektor V1 = <1,1,1>, multiplizieren Sie ihn mit der Wurfkraft und wenden Sie die Ausrichtung auf all dies an.

     const velocityVector = new THREE.Vector3(1,1,1); velocityVector.multiplyScalar(this.force); velocityVector.applyQuaternion(controllerQuaternion); this.grabbed.body.velocity.set(velocityVector.x, velocityVector.y, velocityVector.z); 
  2. Suchen Sie die Position des Controllers (Cursors) und die Position des geworfenen Objekts. Berechnen Sie den Richtungsvektor für zwei Punkte. Normalisieren Sie den Vektor. Und multiplizieren Sie es mit Gewalt.

     const directionX = (trashPosition.x - zeroPosition.x); const directionZ = (trashPosition.z - zeroPosition.z); const vectorsLength = Math.sqrt(Math.pow(directionX, 2) + Math.pow(directionZ, 2)); const x = (directionX / vectorsLength) * this.force; const y = this.force; const z = (directionZ / vectorsLength) * this.force; this.grabbed.body.velocity.set(x , y, z ); 

Ich habe die zweite Option gewählt, weil ich darin nur x und z zählen kann. Und stellen Sie sich selbst ein, da ich einen Wurf entlang des Bogens brauchte, damit der abgelegte Müll in den Korb fällt, obwohl der Benutzer den Controller hält.

Ein paar Worte zum Modell




Von Anfang an habe ich mich für ein Low-Poly- Spiel entschieden. Obwohl WebGL heutzutage in der Lage ist, relativ komplexe Szenen zu rendern, ist seine Leistung fortgeschrittenen Bibliotheken wie DirectX, Vulkan, Mantle usw. immer noch unterlegen. Dies hängt auch von der Leistung des Geräts des Benutzers ab. Da ich mich auf günstigere mobile BP-Helme (Oculus Go, Gear VR) konzentrieren möchte, denke ich, dass Low-Poly eine der wenigen Lösungen für die Erstellung einer VR-Anwendung oder eines VR-Spiels ist. Obwohl natürlich alles von der Lautstärke abhängt.

Okay, Low-Poly ist so Low-Poly, aber wie macht man das alles? Alles ist sehr einfach, es gibt ein gutes Open Source Tool - Blender . Glauben Sie mir, er ist zu viel fähig, aber für einfache Aufgaben ist er nicht ganz geeignet. Es gibt viele Schulungsmaterialien zum Modellieren in Blender, und es wird nicht schwierig sein, sie zu finden. Ich wollte Ihre Aufmerksamkeit nur auf eine Reihe von Punkten im Zusammenhang mit der Webentwicklung lenken:

  1. Der Drei-Js-Exporteur ist veraltet. Notwendigkeit, GLTF-Exporteur zu finden und zu liefern. GLTF ist ein spezielles Format für das Web. Und ja, das ist JSON.
  2. GLTF unterstützt Cycles Renderer nicht, daher müssen Sie Blender Renderer verwenden. Und das bedeutet, dass es keine coolen Knoten, Farbtransformationen oder Metallhighlights gibt (kann anders gemacht werden).
  3. Sie müssen nur das ausgewählte Element exportieren. Sie benötigen keine zusätzlichen Kameras und Lichter? Datei> Exportieren> gltf 2.0. Im linken Menü wird nur GLTF 2.0 exportieren> Exportieren ausgewählt.
  4. Wir beginnen mit dem Export von Position <0, 0, 0> in Blender. Es ist besser, an derselben Stelle zu skalieren, damit Sie später die Skalierungskomponente nicht in einem Frame verwenden.
  5. Wenn Sie wie in Recycle! VR, Sie müssen Objekte nur dort hinzufügen, wo der Spieler theoretisch hinschauen kann. Hinter, hinter den Häusern, im Recycling! Es gibt ein paar Bäume und nur an der Stelle, an der der Benutzer sie sehen kann. Es ist nicht erforderlich, die Szene zu überladen.
  6. Wenn Sie das Modellmaterial ändern müssen, müssen Sie warten, bis es geladen ist, das Modell selbst abrufen und alle Knoten herausziehen (GLTF enthält Informationen nicht nur zu Netzen).

     e.detail.model.traverse((node) => { if (node.isMesh) { node.material.color = new THREE.Color(someColor); } }); 

Abschließend


Vielen Dank für Ihre Aufmerksamkeit! Ich erinnere Sie noch einmal daran, dass das Projekt-Repository unter dem folgenden Link verfügbar ist. Jeder, der etwas Neues in dieses Spiel bringen möchte - willkommen.

Source: https://habr.com/ru/post/de443062/


All Articles