So erstellen Sie ein Endless-Runner-Spiel in der virtuellen Realität (Teil 3)

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ In Teil 1 erklärte Alvin die Grundlagen zum Entwerfen eines Virtual-Reality-Modells. In Teil 2 zeigte er, wie man die Kernlogik des Spiels implementiert. In diesem letzten Teil seines Tutorials wird der letzte Schliff hinzugefügt, wie die Menüs „Start“ und „Game Over“ sowie eine Synchronisierung von Spielständen zwischen mobilen und Desktop-Clients. Dies ebnet den Weg für Konzepte zum Erstellen von Multiplayer-Spielen.

Und so geht unsere Reise weiter. In diesem letzten Teil meiner Serie zum Erstellen eines Endlos-Runner-VR-Spiels zeige ich Ihnen, wie Sie den Spielstatus zwischen zwei Geräten synchronisieren können, was Sie dem Erstellen eines Multiplayer-Spiels einen Schritt näher bringt. Ich werde speziell MirrorVR vorstellen, das für die Handhabung des vermittelnden Servers in der Client-zu-Client-Kommunikation verantwortlich ist.

Hinweis : Dieses Spiel kann mit oder ohne VR-Headset gespielt werden. Sie können eine Demo des Endprodukts unter ergo-3.glitch.me ansehen.

Um zu beginnen, benötigen Sie Folgendes.

  • Internetzugang (insbesondere zu glitch.com);
  • Ein Glitch-Projekt, das aus Teil 2 dieses Tutorials abgeschlossen wurde. Sie können mit dem fertigen Produkt aus Teil 2 beginnen, indem Sie zu https://glitch.com/edit/#!/ergo-2 navigieren und auf „Remix to edit“ klicken;
  • Ein Virtual-Reality-Headset (optional, empfohlen). (Ich verwende Google Cardboard, das für 15 $ pro Stück angeboten wird.)

Schritt 1: Ergebnis anzeigen

Das Spiel funktioniert so, wie es ist, mit einem absoluten Minimum, bei dem der Spieler vor eine Herausforderung gestellt wird: Weiche den Hindernissen aus. Abgesehen von Objektkollisionen gibt das Spiel dem Spieler jedoch keine Rückmeldung bezüglich des Fortschritts im Spiel. Um dem abzuhelfen, implementieren Sie in diesem Schritt die Punkteanzeige. Die Partitur wird ein großes Textobjekt sein, das in unserer Welt der virtuellen Realität platziert wird, im Gegensatz zu einer Schnittstelle, die an das Sichtfeld des Benutzers geklebt wird.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

In der virtuellen Realität ist die Benutzeroberfläche im Allgemeinen am besten in die Welt integriert, anstatt am Kopf des Benutzers zu haften.

Ergebnisanzeige
Score-Anzeige (Große Vorschau)

Beginnen Sie damit, das Objekt zu index.html hinzuzufügen. Fügen Sie ein text Mixin hinzu, das für andere Textelemente wiederverwendet wird:

 <a-assets> ... <a-mixin text=" font:exo2bold; anchor:center; align:center;"></a-mixin> ... </a-assets>

Fügen Sie als Nächstes direkt vor dem Player ein text zur Plattform hinzu:

 <!-- Score --> <a-text value="" mixin="text" height="40" width="40" position="0 1.2 -3" opacity="0.75"></a-text> <!-- Player --> ...

Dadurch wird der Virtual-Reality-Szene ein Textobjekt hinzugefügt. Der Text ist derzeit nicht sichtbar, da sein Wert auf leer gesetzt ist. Sie werden die Textentität jetzt jedoch dynamisch mit JavaScript füllen. Navigieren Sie zu assets/ergo.js . Fügen Sie nach dem Abschnitt „ collisions “ einen score hinzu und definieren Sie eine Reihe globaler Variablen:

  • score : der aktuelle Spielstand.
  • countedTrees : IDs aller Bäume, die im Score enthalten sind. (Dies liegt daran, dass Kollisionstests für denselben Baum mehrmals ausgelöst werden können.)
  • scoreDisplay : Verweis auf das DOM-Objekt, das einem Textobjekt in der Welt der virtuellen Realität entspricht.
 /********* * SCORE * *********/ var score; var countedTrees; var scoreDisplay;

Definieren Sie als Nächstes eine Setup-Funktion, um unsere globalen Variablen zu initialisieren. Definieren Sie in gleicher Weise eine teardown Funktion.

 ... var scoreDisplay; function setupScore() { score = 0; countedTrees = new Set(); scoreDisplay = document.getElementById('score'); } function teardownScore() { scoreDisplay.setAttribute('value', ''); }

Aktualisieren Sie im Abschnitt „ GamegameOver , startGame und window.onload , um die Einrichtung und den Teardown für die Punktzahl einzuschließen.

 /******** * GAME * ********/ function gameOver() { ... teardownScore(); } function startGame() { ... setupScore(); addTreesRandomlyLoop(); } window.onload = function() { setupScore(); ... }

Definieren Sie eine Funktion, die die Punktzahl für einen bestimmten Baum erhöht. Diese Funktion prüft gegen countedTrees , um sicherzustellen, dass der Baum nicht doppelt gezählt wird.

 function addScoreForTree(tree_id) { if (countedTrees.has(tree_id)) return; score += 1; countedTrees.add(tree_id); }

Fügen Sie außerdem ein Dienstprogramm hinzu, um die Partituranzeige mithilfe der globalen Variablen zu aktualisieren.

 function updateScoreDisplay() { scoreDisplay.setAttribute('value', score); }

Aktualisieren Sie den Kollisionstest entsprechend, um diese Funktion zur Erhöhung der Punktzahl immer dann aufzurufen, wenn ein Hindernis den Spieler passiert hat. Navigieren Sie immer noch in assets/ergo.js zum Abschnitt collisions . Fügen Sie die folgende Prüfung und Aktualisierung hinzu.

 AFRAME.registerComponent('player', { tick: function() { document.querySelectorAll('.tree').forEach(function(tree) { ... if (position.z > POSITION_Z_LINE_END) { addScoreForTree(tree_id); updateScoreDisplay(); } }) } })

Aktualisieren Sie schließlich die Punkteanzeige, sobald das Spiel beginnt. Navigieren Sie zum Spielabschnitt und fügen Sie Game updateScoreDisplay(); um das Spiel zu startGame :

 function startGame() { ... setupScore(); updateScoreDisplay(); ... }

Stellen Sie sicher, dass assets/ergo.js und index.html mit den entsprechenden Quellcodedateien übereinstimmen. Navigieren Sie dann zu Ihrer Vorschau. Sie sollten Folgendes sehen:

Ergebnisanzeige
Score-Anzeige (Große Vorschau)

Damit ist die Punkteanzeige abgeschlossen. Als nächstes fügen wir die richtigen Start- und Game Over- Menüs hinzu, damit der Spieler das Spiel wie gewünscht wiederholen kann.

Schritt 2: Startmenü hinzufügen

Jetzt, da der Benutzer den Fortschritt verfolgen kann, werden Sie den letzten Schliff hinzufügen, um das Spielerlebnis zu vervollständigen. In diesem Schritt fügen Sie ein Startmenü und ein Game Over- Menü hinzu, sodass der Benutzer Spiele starten und neu starten kann.

Beginnen wir mit dem Startmenü , wo der Spieler auf eine „Start“-Schaltfläche klickt , um das Spiel zu beginnen. Für die zweite Hälfte dieses Schritts fügen Sie ein Game Over- Menü mit einer Schaltfläche „Neustart“ hinzu:

Start- und Game Over-Menüs
Start- und Spielende-Menüs (große Vorschau)

Navigieren Sie in Ihrem Editor zu index.html . Suchen Sie dann den Abschnitt Mixins . Hängen Sie hier das title Mixin an, das Stile für besonders großen Text definiert. Wir verwenden die gleiche Schriftart wie zuvor, richten den Text zentriert aus und definieren eine der Textart angemessene Größe. (Beachten Sie unten, dass anchor dort ist, wo ein Textobjekt an seiner Position verankert ist.)

 <a-assets> ... <a-mixin text=" font:exo2bold; height:40; width:40; opacity:0.75; anchor:center; align:center;"></a-mixin> </a-assets>

Fügen Sie als Nächstes ein zweites Mixin für sekundäre Überschriften hinzu. Dieser Text ist etwas kleiner, aber ansonsten identisch mit dem Titel.

 <a-assets> ... <a-mixin text=" font:exo2bold; height:10; width:10; opacity:0.75; anchor:center; align:center;"></a-mixin> </a-assets>

Definieren Sie für das dritte und letzte Mixin Eigenschaften für beschreibenden Text – sogar kleiner als sekundäre Überschriften.

 <a-assets> ... <a-mixin text=" font:exo2bold; height:5; width:5; opacity:0.75; anchor:center; align:center;"></a-mixin> </a-assets>

Nachdem alle Textstile definiert sind, definieren Sie nun die In-World-Textobjekte. Fügen Sie einen neuen Abschnitt Menus unterhalb des Abschnitts Score hinzu, mit einem leeren Container für das Startmenü :

 <!-- Score --> ... <!-- Menus --> <a-entity> <a-entity position="0 1.1 -3"> </a-entity> </a-entity>

Definieren Sie im Startmenü-Container den Titel und einen Container für den gesamten Nicht-Titel-Text:

 ... <a-entity ...> <a-entity position="0 1 0"> </a-entity> <a-text value="ERGO" mixin="title"></a-text> </a-entity> </a-entity>

Fügen Sie im Container für Nicht-Titeltext Anweisungen zum Spielen des Spiels hinzu:

 <a-entity...> <a-text value="Turn left and right to move your player, and avoid the trees!" mixin="copy"></a-text> </a-entity>

Um das Startmenü zu vervollständigen, fügen Sie eine Schaltfläche mit der Aufschrift „Start“ hinzu:

 <a-entity...> ... <a-text value="Start" position="0 0.75 0" mixin="heading"></a-text> <a-box position="0 0.65 -0.05" width="1.5" height="0.6" depth="0.1"></a-box> </a-entity>

Überprüfen Sie noch einmal, ob Ihr HTML-Code für das Startmenü mit Folgendem übereinstimmt:

 <!-- Menus --> <a-entity> <a-entity position="0 1.1 -3"> <a-entity position="0 1 0"> <a-text value="Turn left and right to move your player, and avoid the trees!" mixin="copy"></a-text> <a-text value="Start" position="0 0.75 0" mixin="heading"></a-text> <a-box position="0 0.65 -0.05" width="1.5" height="0.6" depth="0.1"></a-box> </a-entity> <a-text value="ERGO" mixin="title"></a-text> </a-entity> </a-entity>

Navigieren Sie zu Ihrer Vorschau und Sie sehen das folgende Startmenü :

Bild des Startmenüs
Startmenü (Große Vorschau)

Fügen Sie immer noch im Abschnitt Menus (direkt unter dem start ) das game-over Menü mit denselben Mixins hinzu:

 <!-- Menus --> <a-entity> ... <a-entity position="0 1.1 -3"> <a-text value="?" mixin="heading" position="0 1.7 0"></a-text> <a-text value="Score" mixin="copy" position="0 1.2 0"></a-text> <a-entity> <a-text value="Restart" mixin="heading" position="0 0.7 0"></a-text> <a-box position="0 0.6 -0.05" width="2" height="0.6" depth="0.1"></a-box> </a-entity> <a-text value="Game Over" mixin="title"></a-text> </a-entity> </a-entity>

Navigieren Sie zu Ihrer JavaScript-Datei assets/ergo.js . Erstellen Sie vor dem Abschnitt „ Game “ einen neuen Abschnitt „ Menus “. Definieren Sie außerdem drei leere Funktionen: setupAllMenus , hideAllMenus und showGameOverMenu .

 /******** * MENU * ********/ function setupAllMenus() { } function hideAllMenus() { } function showGameOverMenu() { } /******** * GAME * ********/

Aktualisieren Sie als Nächstes den Game an drei Stellen. Zeigen Sie in gameOver das Game Over- Menü an:

 function gameOver() { ... showGameOverMenu(); } ``` In `startGame`, hide all menus: ``` function startGame() { ... hideAllMenus(); }

Entfernen Sie als Nächstes in window.onload den direkten Aufruf von startGame und rufen Sie stattdessen setupAllMenus . Aktualisieren Sie Ihren Listener so, dass er mit Folgendem übereinstimmt:

 window.onload = function() { setupAllMenus(); setupScore(); setupTrees(); }

Navigieren Sie zurück zum Abschnitt Menu . Speichern Sie Verweise auf verschiedene DOM-Objekte:

 /******** * MENU * ********/ var menuStart; var menuGameOver; var menuContainer; var isGameRunning = false; var startButton; var restartButton; function setupAllMenus() { menuStart = document.getElementById('start-menu'); menuGameOver = document.getElementById('game-over'); menuContainer = document.getElementById('menu-container'); startButton = document.getElementById('start-button'); restartButton = document.getElementById('restart-button'); }

Binden Sie als Nächstes die Schaltflächen „Start“ und „Restart“ an startGame :

 function setupAllMenus() { ... startButton.addEventListener('click', startGame); restartButton.addEventListener('click', startGame); }

Definieren Sie showStartMenu und rufen Sie es von setupAllMenus auf:

 function setupAllMenus() { ... showStartMenu(); } function hideAllMenus() { } function showGameOverMenu() { } function showStartMenu() { }

Um die drei leeren Funktionen zu füllen, benötigen Sie einige Hilfsfunktionen. Definieren Sie die folgenden zwei Funktionen, die ein DOM-Element akzeptieren, das eine A-Frame-VR-Entität darstellt, und es ein- oder ausblendet. Definieren Sie beide Funktionen oben showAllMenus :

 ... var restartButton; function hideEntity(el) { el.setAttribute('visible', false); } function showEntity(el) { el.setAttribute('visible', true); } function showAllMenus() { ...

Füllen Sie zuerst hideAllMenus . Sie entfernen die Objekte aus dem Sichtfeld und entfernen dann die Klick-Listener für beide Menüs:

 function hideAllMenus() { hideEntity(menuContainer); startButton.classList.remove('clickable'); restartButton.classList.remove('clickable'); }

showGameOverMenu . Stellen Sie hier den Container für beide Menüs sowie das Game Over- Menü und den Klick-Listener der Schaltfläche "Neustart" wieder her. Entfernen Sie jedoch den Klick-Listener der Schaltfläche „Start“ und blenden Sie das Menü „Start“ aus.

 function showGameOverMenu() { showEntity(menuContainer); hideEntity(menuStart); showEntity(menuGameOver); startButton.classList.remove('clickable'); restartButton.classList.add('clickable'); }

showStartMenu . Machen Sie hier alle Änderungen rückgängig, die das showGameOverMenu bewirkt hat.

 function showStartMenu() { showEntity(menuContainer); hideEntity(menuGameOver); showEntity(menuStart); startButton.classList.add('clickable'); restartButton.classList.remove('clickable'); }

Überprüfen Sie noch einmal, ob Ihr Code mit den entsprechenden Quelldateien übereinstimmt. Navigieren Sie dann zu Ihrer Vorschau und Sie werden das folgende Verhalten beobachten:

Start- und Game Over-Menüs
Start- und Game Over-Menüs (große Vorschau)

Damit sind die Start- und Game Over- Menüs abgeschlossen.

Glückwünsche! Sie haben jetzt ein voll funktionsfähiges Spiel mit einem richtigen Start und einem richtigen Ende. In diesem Tutorial haben wir jedoch noch einen Schritt übrig: Wir müssen den Spielstatus zwischen verschiedenen Player-Geräten synchronisieren. Dies wird uns einen Schritt näher in Richtung Multiplayer-Spiele bringen.

Schritt 3: Synchronisieren des Spielstatus mit MirrorVR

In einem früheren Tutorial haben Sie gelernt, wie Echtzeitinformationen über Sockets gesendet werden, um die unidirektionale Kommunikation zwischen einem Server und einem Client zu erleichtern. In diesem Schritt bauen Sie auf einem vollwertigen Produkt dieses Tutorials auf, MirrorVR, das den vermittelnden Server in der Client-zu-Client-Kommunikation verwaltet.

Hinweis : Hier erfahren Sie mehr über MirrorVR.

Navigieren Sie zu index.html . Hier laden wir MirrorVR und fügen der Kamera eine Komponente hinzu, die angibt, dass sie gegebenenfalls die Ansicht eines Mobilgeräts spiegeln soll. Importieren Sie die socket.io-Abhängigkeit und MirrorVR 0.2.3.

 <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script> <script src="https://cdn.jsdelivr.net/gh/alvinwan/[email protected]/dist/mirrorvr.min.js"></script>

Fügen Sie als Nächstes eine Komponente, camera-listener , zur Kamera hinzu:

 <a-camera camera-listener ...>

Navigieren Sie zu assets/ergo.js . In diesem Schritt sendet das mobile Gerät Befehle und das Desktop-Gerät spiegelt nur das mobile Gerät.

Um dies zu erleichtern, benötigen Sie ein Dienstprogramm, mit dem Sie zwischen Desktop- und Mobilgeräten unterscheiden können. Fügen Sie am Ende Ihrer Datei eine mobileCheck Funktion nach shuffle hinzu:

 /** * Checks for mobile and tablet platforms. */ function mobileCheck() { var check = false; (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[aw])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); return check; };

Zuerst werden wir den Spielstart synchronisieren. Fügen Sie in startGame im Bereich Game am Ende eine mirrorVR Benachrichtigung hinzu.

 function startGame() { ... if (mobileCheck()) { mirrorVR.notify('startGame', {}) } }

Der mobile Client sendet jetzt Benachrichtigungen über den Beginn eines Spiels. Sie implementieren nun die Antwort des Desktops.

Rufen Sie im Fenster Load Listener eine setupMirrorVR Funktion auf:

 window.onload = function() { ... setupMirrorVR(); }

Definieren Sie einen neuen Abschnitt über dem Spielabschnitt für das Game -Setup:

 /************ * MirrorVR * ************/ function setupMirrorVR() { mirrorVR.init(); }

Fügen Sie als Nächstes der Initialisierungsfunktion für MirrorVR Schlüsselwortargumente hinzu. Insbesondere werden wir den Handler für Spielstartbenachrichtigungen definieren. Zusätzlich geben wir eine Raum-ID an; Dadurch wird sichergestellt, dass jeder, der Ihre Anwendung lädt, sofort synchronisiert wird.

 function setupMirrorVR() { mirrorVR.init({ roomId: 'ergo', state: { startGame: { onNotify: function(data) { hideAllMenus(); setupScore(); updateScoreDisplay(); } }, } }); }

Wiederholen Sie denselben Synchronisierungsvorgang für Game Over . gameOver in gameOver im Abschnitt „ Game “ ein Häkchen für Mobilgeräte hinzu und sende eine entsprechende Benachrichtigung:

 function gameOver() { ... if (mobileCheck()) { mirrorVR.notify('gameOver', {}); } }

Navigieren Sie zum Abschnitt MirrorVR und aktualisieren Sie die Schlüsselwortargumente mit einem gameOver Listener:

 function setupMirrorVR() { mirrorVR.init({ state: { startGame: {... }, gameOver: { onNotify: function(data) { gameOver(); } }, } }) }

Wiederholen Sie als Nächstes denselben Synchronisierungsprozess für das Hinzufügen von Bäumen. Navigieren Sie im Abschnitt Trees zu addTreesRandomly . Verfolgen Sie, welche Fahrspuren neue Bäume erhalten. Dann, direkt vor der return , und eine entsprechende Benachrichtigung senden:

 function addTreesRandomly(...) { ... var numberOfTreesAdded ... var position_indices = []; trees.forEach(function (tree) { if (...) { ... position_indices.push(tree.position_index); } }); if (mobileCheck()) { mirrorVR.notify('addTrees', position_indices); } return ... }

Navigieren Sie zum Abschnitt MirrorVR und aktualisieren Sie die Schlüsselwortargumente auf mirrorVR.init mit einem neuen Listener für Bäume:

 function setupMirrorVR() { mirrorVR.init({ state: { ... gameOver: {... }, addTrees: { onNotify: function(position_indices) { position_indices.forEach(addTreeTo) } }, } }) }

Abschließend synchronisieren wir den Spielstand. Senden Sie in updateScoreDisplay aus dem Score -Bereich gegebenenfalls eine Benachrichtigung:

 function updateScoreDisplay() { ... if (mobileCheck()) { mirrorVR.notify('score', score); } }

Aktualisieren Sie die mirrorVR Initialisierung zum letzten Mal mit einem Listener für Partituränderungen:

 function setupMirrorVR() { mirrorVR.init({ state: { addTrees: { }, score: { onNotify: function(data) { score = data; updateScoreDisplay(); } } } }); }

Überprüfen Sie noch einmal, ob Ihr Code mit den entsprechenden Quellcodedateien für diesen Schritt übereinstimmt. Navigieren Sie dann zu Ihrer Desktop-Vorschau. Öffnen Sie außerdem dieselbe URL auf Ihrem Mobilgerät. Sobald Ihr Mobilgerät die Webseite lädt, sollte Ihr Desktop sofort damit beginnen, das Spiel des Mobilgeräts zu spiegeln.

Hier ist eine Demo. Beachten Sie, dass sich der Desktop-Cursor nicht bewegt, was darauf hinweist, dass das mobile Gerät die Desktop-Vorschau steuert.

Final Endless Runner Game mit MirrorVR-Spielstatussynchronisierung
Endergebnis des Endlos-Runner-Spiels mit MirrorVR-Spielstatussynchronisierung (Große Vorschau)

Damit ist Ihr erweitertes Projekt mit MirrorVR abgeschlossen.

Dieser dritte Schritt führte einige grundlegende Schritte zur Synchronisierung des Spielstatus ein; Um dies robuster zu machen, könnten Sie mehr Plausibilitätsprüfungen und mehr Synchronisierungspunkte hinzufügen.

Fazit

In diesem Tutorial haben Sie Ihrem Endlos-Runner-Spiel den letzten Schliff gegeben und die Echtzeitsynchronisierung eines Desktop-Clients mit einem mobilen Client implementiert, wodurch der Bildschirm des mobilen Geräts effektiv auf Ihrem Desktop gespiegelt wurde. Damit ist die Serie zum Erstellen eines endlosen Runner-Spiels in der virtuellen Realität abgeschlossen. Zusammen mit A-Frame-VR-Techniken haben Sie 3D-Modellierung, Client-zu-Client-Kommunikation und andere weit verbreitete Konzepte aufgegriffen.

Die nächsten Schritte können Folgendes umfassen:

  • Erweiterte Modellierung
    Dies bedeutet realistischere 3D-Modelle, die möglicherweise in einer Drittanbietersoftware erstellt und importiert werden. Zum Beispiel macht (MagicaVoxel) das Erstellen von Voxel-Art einfach und (Blender) ist eine vollständige 3D-Modellierungslösung.
  • Mehr Komplexität
    Komplexere Spiele, wie z. B. ein Echtzeit-Strategiespiel, könnten eine Drittanbieter-Engine für mehr Effizienz nutzen. Dies kann bedeuten, A-Frame und WebVR vollständig zu umgehen und stattdessen ein kompiliertes (Unity3d) Spiel zu veröffentlichen.

Andere Möglichkeiten sind Multiplayer-Unterstützung und reichhaltigere Grafiken. Mit dem Abschluss dieser Tutorial-Reihe verfügen Sie nun über ein Framework, das Sie weiter untersuchen können.