{"id":73869,"date":"2019-12-06T04:18:21","date_gmt":"2019-12-06T11:18:21","guid":{"rendered":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/"},"modified":"2019-12-06T04:18:21","modified_gmt":"2019-12-06T11:18:21","slug":"how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2","status":"publish","type":"post","link":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/","title":{"rendered":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)"},"content":{"rendered":"<link rel=\"canonical\" href=\"https:\/\/www.smashingmagazine.com\/2019\/12\/real-time-multiplayer-virtual-reality-game-part-2\/\"><title>How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)<\/title><\/p>\n<article>\n<header>\n<h1>How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)<\/h1>\n<address>Alvin Wan<\/address>\n<p>                  <time datetime=\"2019-12-05T11:00:00+00:00\">2019-12-05T11:00:00+00:00<\/time><time datetime=\"2019-12-05T11:00:00+00:00\">2019-12-06T11:06:21+00:00<\/time><\/header>\n<p>In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the <a href=\"https:\/\/www.smashingmagazine.com\/2019\/08\/real-time-multiplayer-virtual-reality-game-part-1\/\">first part<\/a> of this series, we designed the orbs featured in the game. In this part of the series, we will add game mechanics and setup communication protocols between pairs of players.<\/p>\n<p>The game description here is excerpted from the first part of the series: Each pair of players is given a ring of orbs. The goal is to \u201cturn on\u201d all orbs, where an orb is \u201con\u201d if it\u2019s elevated and bright. An orb is \u201coff\u201d if it\u2019s lower and dim. However, certain \u201cdominant\u201d orbs affect their neighbors: if it switches state, its neighbors also switch state. Player 2 can control even-numbered orbs, and player 1 can control odd-numbered orbs. This forces both players to collaborate to solve the puzzle.<\/p>\n<p>The 8 steps in this tutorial are grouped into 3 sections:<\/p>\n<ol>\n<li>Populating User Interface (Steps 1 and 2)<\/li>\n<li>Add Game Mechanics (Steps 3 to 5)<\/li>\n<li>Setup Communication (Steps 6 to 8)<br \/>\n<\/li>\n<\/ol>\n<p>This part will conclude with a fully functioning demo online, for anyone to play. You will use A-Frame VR and several A-Frame extensions.<\/p>\n<p><em>You can find the finished source code <a href=\"https:\/\/github.com\/alvinwan\/lightful\">here<\/a>.<\/em><\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/2-real-time-multiplayer-vr-game-1.gif?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/2-real-time-multiplayer-vr-game-1.gif?w=900&#038;ssl=1\" alt=\"The finished multiplayer game, synchronized across multiple clients\"><\/a><figcaption>The finished multiplayer game, synchronized across multiple clients. (<a href=\"https:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/2-real-time-multiplayer-vr-game-1.gif\">Large preview<\/a>)<\/figcaption><\/figure>\n<h3>1. Add Visual Indicators<\/h3>\n<p>To start, we will add visual indicators of an orb\u2019s ID. Insert a new <code>a-text<\/code> VR element as the first child of <code>#container-orb0<\/code>, on L36.<\/p>\n<div>\n<pre><code><a-entity id=\"container-orb0\" ...>\n    <a-text class=\"orb-id\" opacity=\"0.25\" rotation=\"0 -90 0\" value=\"4\" color=\"#FFF\" scale=\"3 3 3\" position=\"0 -2 -0.25\" material=\"side:double\"><\/a-text>\n    ...\n    <a-entity position...>\n        ...\n    <\/a-entity>\n<\/a-entity>\n<\/code><\/pre>\n<\/div>\n<p>An orb\u2019s \u201cdependencies\u201d are the orbs it will toggle, when toggled: for example, say orb 1 has as dependencies orbs 2 and 3. This means that if orb 1 is toggled, orbs 2 and 3 will be toggled too. We will add visual indicators of dependencies, as follows, directly after <code>.animation-position<\/code>.<\/p>\n<div>\n<pre><code><a-animation class=\"animation-position\" ... \/>\n<a-text class=\"dep-right\" opacity=\"0.25\" rotation=\"0 -90 0\" value=\"4\" color=\"#FFF\" scale=\"10 10 10\" position=\"0 0 1\" material=\"side:double\" ><\/a-text>\n            <a-text class=\"dep-left\" opacity=\"0.25\"rotation=\"0 -90 0\" value=\"1\" color=\"#FFF\" scale=\"10 10 10\" position=\"0 0 -3\" material=\"side:double\" ><\/a-text>\n<\/code><\/pre>\n<\/div>\n<p>Verify that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step01.html\">our source code for Step 1<\/a>. Your orb should now match the following:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/d46bd309-6c38-4a16-b6d5-2e744cd21b27\/1-real-time-multiplayer-vr-game.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"https:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/1-real-time-multiplayer-vr-game-1.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/d46bd309-6c38-4a16-b6d5-2e744cd21b27\/1-real-time-multiplayer-vr-game.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/d46bd309-6c38-4a16-b6d5-2e744cd21b27\/1-real-time-multiplayer-vr-game.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/d46bd309-6c38-4a16-b6d5-2e744cd21b27\/1-real-time-multiplayer-vr-game.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/d46bd309-6c38-4a16-b6d5-2e744cd21b27\/1-real-time-multiplayer-vr-game.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/1-real-time-multiplayer-vr-game-1.png?w=900&#038;ssl=1\" sizes=\"100vw\" alt=\"Orb with visual indicators for the orb\u2019s ID and IDs of the orbs it will trigger\"><\/a><figcaption>\n      Orb with visual indicators for the orb\u2019s ID and IDs of the orbs it will trigger (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/d46bd309-6c38-4a16-b6d5-2e744cd21b27\/1-real-time-multiplayer-vr-game.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>This concludes the additional visual indicators we will need. Next, we will dynamically add orbs to the VR scene, using this template orb.<\/p>\n<h3>2. Dynamically Add Orbs<\/h3>\n<p>In this step, we will add orbs according to a JSON-esque specification of a level. This allows us to easily specify and generate new levels. We will use the orb from the <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial\/step07.html#L34\">last step in part 1<\/a> as a template.<\/p>\n<p>To start, import jQuery, as this will make DOM modifications, and thus modifications to the VR scene, easier. Directly after the A-Frame import, add the following to L8:<\/p>\n<pre><code><script src=\"https:\/\/code.jquery.com\/jquery-3.3.1.min.js\"><\/script>\n<\/code><\/pre>\n<p>Specify a level using an array. The array will contain object literals that encode each orb\u2019s \u201cdependencies\u201d. Inside the <code><head><\/code> tag, add the following level configuration, :<\/p>\n<pre><code>     <script>\nvar orbs = [\n  {left: 1, right: 4},\n  {},\n  {on: true},\n  {},\n  {on: true}\n];\n    <\/script>\n<\/code><\/pre>\n<p>For now, each orb can only have one dependency to the \u201cright\u201d of it and one to the \u201cleft\u201d of it. Immediately after declaring <code>orbs<\/code> above, add a handler that will run on page load. This handler will (1) duplicate the template orb and (2) remove the template orb, using the provided level configuration:<\/p>\n<pre><code>$(document).ready(function() {\n\n  function populateTemplate(orb, template, i, total) {}\n  \n  function remove(selector) {}\n\n  for (var i=0; i <\/code><\/pre>\n<p>Next, populate the <code>remove<\/code> function, which simply removes an item from the VR scene, given a selector. Fortunately, A-Frame observes changes to the DOM, and thus, removing the item from the DOM suffices to remove it from the VR scene. Populate the <code>remove<\/code> function as follows.<\/p>\n<pre><code>  function remove(selector) {\n    var el = document.querySelector(selector);\n    el.parentNode.removeChild(el);\n  }\n<\/code><\/pre>\n<p>Populate the <code>clickOrb<\/code> function, which simply triggers the click action on an orb.<\/p>\n<pre><code>function clickOrb(i) {\n  document.querySelector(\"#container-orb\" + i).click();\n}\n<\/code><\/pre>\n<p>Next, begin writing the <code>populateTemplate<\/code> function. In this function, begin by getting the <code>.container<\/code>. This container for the orb additionally contains the visual indicators we added in the previous step. Furthermore, we will need to modify the orb\u2019s <code>onclick<\/code> behavior, based on its dependencies. If a left-dependency exists, modify both the visual indicator and the <code>onclick<\/code> behavior to reflect that; the same holds true for a right-dependency:<\/p>\n<div>\n<pre><code>function populateTemplate(orb, template, i, total) {\n    var container = template.find('.container');\n    var onclick = 'document.querySelector(\"#light-orb' + i + '\").emit(\"switch\");';\n\n    if (orb.left || orb.right) {\n      if (orb.left) {\n        onclick += 'clickOrb(' + orb.left + ');';\n        container.find('.dep-left').attr('value', orb.left);\n      }\n      if (orb.right) {\n        onclick += 'clickOrb(' + orb.right + ');';\n        container.find('.dep-right').attr('value', orb.right);\n      }\n    } else {\n      container.find('.dep-left').remove();\n      container.find('.dep-right').remove();\n    }\n}\n<\/code><\/pre>\n<\/div>\n<p>Still in the <code>populateTemplate<\/code> function, set the orb ID correctly in all of the orb and its container\u2019s elements.<\/p>\n<pre><code>    container.find('.orb-id').attr('value', i);\n    container.attr('id', 'container-orb' + i);\n    template.find('.orb').attr('id', 'orb' + i);\n    template.find('.light-orb').attr('id', 'light-orb' + i);\n    template.find('.clickable').attr('data-id', i);\n<\/code><\/pre>\n<p>Still in the <code>populateTemplate<\/code> function, set the <code>onclick<\/code> behavior, set the random seed so that each orb is visually different, and finally, set the orb\u2019s rotational position based on its ID.<\/p>\n<pre><code>    container.attr('onclick', onclick);\n    container.find('lp-sphere').attr('seed', i);\n    template.attr('rotation', '0 ' + (360 \/ total * i) + ' 0');\n<\/code><\/pre>\n<p>At the conclusion of the function, return the <code>template<\/code> with all the configurations above.<\/p>\n<pre><code>    return template;\n<\/code><\/pre>\n<p>Inside the document load handler and after removing the template with <code>remove('#template')<\/code>, turn on the orbs that were configured to be on initially.<\/p>\n<pre><code>$(document).ready(function() {\n  ...\n  setTimeout(function() {\n    for (var i=0; i <\/code><\/pre>\n<p>This concludes the Javascript modifications. Next, we will change the template\u2019s default settings to that of an \u2018off\u2019 orb. Change the position and scale for <code>#container-orb0<\/code> to the following:<\/p>\n<pre><code>position=\"8 0.5 0\" scale=\"0.5 0.5 0.5\"\n<\/code><\/pre>\n<p>Then, change intensity for <code>#light-orb0<\/code> to 0.<\/p>\n<pre><code>intensity=\"0\"\n<\/code><\/pre>\n<p>Verify that your source code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step02.html\">our source code for Step 2<\/a>.<\/p>\n<p>Your VR scene should now feature 5 orbs, dynamically populated. One of the orbs should furthermore have visual indicators of dependencies, like below:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/3-real-time-multiplayer-vr-game.gif?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/3-real-time-multiplayer-vr-game.gif?w=900&#038;ssl=1\" alt=\"All orbs are populated dynamically, using the template orb\"><\/a><figcaption>All orbs are populated dynamically, using the template orb (<a href=\"https:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/3-real-time-multiplayer-vr-game.gif\">Large preview<\/a>)<\/figcaption><\/figure>\n<p>This concludes the first section in dynamically adding orbs. In the next section, we will spend three steps adding game mechanics. Specifically, the player will only be able to toggle specific orbs depending on the player ID.<\/p>\n<h3>3. Add Terminal State<\/h3>\n<p>In this step, we will add a terminal state. If all orbs are turned on successfully, the player sees a \u201cvictory\u201d page. To do this, you will need to track the state of all orbs. Every time an orb is toggled on or off, we will need to update our internal state. Say that a helper function <code>toggleOrb<\/code> updates state for us. Invoke the <code>toggleOrb<\/code> function every time an orb changes state: (1) add a click listener to the onload handler and (2) add a <code>toggleOrb(i);<\/code> invocation to <code>clickOrb<\/code>. Finally, (3) define an empty <code>toggleOrb<\/code>.<\/p>\n<pre><code>$(document).ready(function() {\n  ...\n  $('.orb').on('click', function() {\n    var id = $(this).attr('data-id')\n    toggleOrb(id);\n  });\n});\n\nfunction toggleOrb(i) {}\n\nfunction clickOrb(i) {\n  ...\n  toggleOrb(i);\n}\n<\/code><\/pre>\n<p>For simplicity, we will use our level configuration to indicate game state. Use <code>toggleOrb<\/code> to toggle the <code>on<\/code> state for the ith orb. <code>toggleOrb<\/code> can additionally trigger a terminal state if all orbs are turned on.<\/p>\n<pre><code>function toggleOrb(i) {\n  orbs[i].on = !orbs[i].on;\n  if (orbs.every(orb => orb.on)) console.log('Victory!');\n}\n<\/code><\/pre>\n<p>Double-check that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step03.html\">our source code for Step 3<\/a>.<\/p>\n<p>This concludes the \u201csingle-player\u201d mode for the game. At this point, you have a fully functional virtual reality game. However, you will now need to write the multiplayer component and encourage collaboration via game mechanics.<\/p>\n<div><\/div>\n<h3>4. Create Player Object<\/h3>\n<p>In this step, we will create an abstraction for a player with a player ID. This player ID will be assigned by the server later on.<\/p>\n<p>For now, this will simply be a global variable. Directly after defining <code>orbs<\/code>, define a player ID:<\/p>\n<pre><code>var orbs = ...\n\nvar current_player_id = 1;\n<\/code><\/pre>\n<p>Double-check that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step04.html\">our source code for Step 4<\/a>. In the next step, this player ID will then be used to determine which orbs the player can control.<\/p>\n<h3>5. Conditionally Toggle Orbs<\/h3>\n<p>In this step, we will modify orb toggling behavior. Specifically, player 1 can control odd-numbered orbs and player 2 can control even-numbered orbs. First, implement this logic in both places where orbs change state:<\/p>\n<pre><code>    $('.orb').on('click', function() {\n        var id = ...\n        if (!allowedToToggle(id)) return false;\n        ...\n    }\n...\n\nfunction clickOrb(i) {\n    if (!allowedToToggle(id)) return;\n    ...\n}\n<\/code><\/pre>\n<p>Second, define the <code>allowedToToggle<\/code> function, right after <code>clickOrb<\/code>. If the current player is player 1, odd-numbered ids will return a truth-y value and thus, player 1 will be allowed to control odd-numbered orbs. The reverse is true for player 2. All other players are not allowed to control the orbs.<\/p>\n<pre><code>function allowedToToggle(id) {\n  if (current_player_id == 1) {\n    return id % 2;\n  } else if (current_player_id == 2) {\n    return !(id % 2);\n  }\n  return false;\n}\n<\/code><\/pre>\n<p>Double-check that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step05.html\">our source code for Step 5<\/a>. By default, the player is player 1. This means that you as player 1 can only control odd-numbered orbs in your preview. This concludes the section on game mechanics.<\/p>\n<p>In the next section, we will facilitate communication between both players via a server.<\/p>\n<h3>6. Setup Server With WebSocket<\/h3>\n<p>In this step, you will set up a simple server to (1) keep track of player IDs and (2) relay messages. These messages will include game state, so that players can be certain each sees what the other sees.<\/p>\n<p>We will refer to your previous <code>index.html<\/code> as the client-side source code. We will refer to code in this step as the server-side source code. Navigate to glitch.com, click on \u201cnew project\u201d in the top-right, and in the dropdown, click on \u201chello-express\u201d.<\/p>\n<p>From the left-hand panel, select \u201cpackage.json,\u201d and add <code>socket-io<\/code> to <code>dependencies<\/code>. Your <code>dependencies<\/code> dictionary should now match the following.<\/p>\n<pre><code>  \"dependencies\": {\n    \"express\": \"^4.16.4\",\n    \"socketio\": \"^1.0.0\"\n  },\n<\/code><\/pre>\n<p>From the left-hand panel, select \u201cindex.js,\u201d and replace the contents of that file with the following minimal socket.io Hello World:<\/p>\n<pre><code>const express = require(\"express\");\nconst app = express();\n\nvar http = require('http').Server(app);\nvar io = require('socket.io')(http);\n\n\/**\n * Run application on port 3000\n *\/\n\nvar port = process.env.PORT || 3000;\n\nhttp.listen(port, function(){\n  console.log('listening on *:', port);\n});\n<\/code><\/pre>\n<p>The above sets up socket.io on port 3000 for a basic express application. Next, define two global variables, one for maintaining the list of active players and another for maintaining the smallest unassigned player ID.<\/p>\n<pre><code>\/**\n * Maintain player IDs\n *\/\n\nvar playerIds = [];\nvar smallestPlayerId = 1;\n<\/code><\/pre>\n<p>Next, define the <code>getPlayerId<\/code> function, which generates a new player ID and marks the new player ID as \u201ctaken\u201d by adding it to the <code>playerIds<\/code> array. In particular, the function simply marks <code>smallestPlayerId<\/code> and then updates <code>smallestPlayerId<\/code> by searching for the next smallest non-taken integer.<\/p>\n<pre><code>function getPlayerId() {\n  var playerId = smallestPlayerId;\n  playerIds.push(playerId);\n\n  while (playerIds.includes(smallestPlayerId)) {\n    smallestPlayerId++;\n  }\n  return playerId;\n}\n<\/code><\/pre>\n<p>Define the <code>removePlayer<\/code> function, which updates <code>smallestPlayerId<\/code> accordingly and frees the provided <code>playerId<\/code> so that another player may take that ID.<\/p>\n<pre><code>function removePlayer(playerId) {\n  if (playerId <\/code><\/pre>\n<p>Finally, define a pair of socket event handlers that register new players and un-register disconnected players, using the above pair of methods.<\/p>\n<pre><code>\/**\n * Handle socket interactions\n *\/\n\nio.on('connection', function(socket) {\n  socket.on('newPlayer', function() {\n    socket.playerId = getPlayerId();\n    console.log(\"new player: \", socket.playerId);\n    socket.emit('playerId', socket.playerId);\n  });\n\n  socket.on('disconnect', function() {\n    if (socket.playerId === undefined) return;\n    console.log(\"disconnected player: \", socket.playerId);\n    removePlayer(socket.playerId);\n  });\n});\n<\/code><\/pre>\n<p>Double-check that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step06.js\">our source code for Step 6<\/a>. This concludes basic player registration and de-registration. Each client can now use the server-generated player ID.<\/p>\n<p>In the next step, we will modify the client to receive and use the server-emitted player ID.<\/p>\n<div><\/div>\n<h3>7. Apply Player ID<\/h3>\n<p>In these next two steps, we will complete a rudimentary version of the multiplayer experience. To start, integrate the player ID assignment client-side. In particular, each client will ask the server for a player ID. Navigate back to the client-side <code>index.html<\/code> we were working within Steps 4 and before.<\/p>\n<p>Import <code>socket.io<\/code> in the <code>head<\/code> at L7:<\/p>\n<div>\n<pre><code><script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/socket.io\/2.1.1\/socket.io.js\"><\/script>\n<\/code><\/pre>\n<\/div>\n<p>After the document load handler, instantiate the socket and emit a <code>newPlayer<\/code> event. In response, the server-side will generate a new player ID using the <code>playerId<\/code> event. Below, use the URL for your Glitch project preview instead of <code>lightful.glitch.me<\/code>. You are welcome to use the demo URL below, but any code changes you make will of course not be reflected.<\/p>\n<pre><code>$(document).ready(function() {\n    ...\n});\n\nsocket = io(\"https:\/\/lightful.glitch.me\");\n  socket.emit('newPlayer');\n  socket.on('playerId', function(player_id) {\n    current_player_id = player_id;\n    console.log(\" * You are now player\", current_player_id);\n  });\n<\/code><\/pre>\n<p>Verify that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/tree\/master\/tutorial2\/step07.html\">our source code for Step 7<\/a>. Now, you can load your game on two different browsers or tabs to play two sides of a multiplayer game. Player 1 will be able to control odd-numbered orbs and player 2 will be able to control even-numbered orbs.<\/p>\n<p>However, note that toggling orbs for player 1 will not affect orb state for player 2. Next, we need to synchronize game states.<\/p>\n<h3>8. Synchronize Game State<\/h3>\n<p>In this step, we will synchronize game states so that players 1 and 2 see the same orb states. If orb 1 is on for player 1, it should be on for player 2 as well. On the client-side, we will both announce and listen for orb toggles. To announce, we will simply pass the ID of the orb that is toggled.<\/p>\n<p>Before both <code>toggleOrb<\/code> invocations, add the following <code>socket.emit<\/code> call.<\/p>\n<pre><code>$(document).ready(function() {\n    ...\n    $('.orb').on('click', function() {\n        ...\n        socket.emit('toggleOrb', id);\n        toggleOrb(id);\n    });\n});\n...\nfunction clickOrb(i) {\n    ...\n    socket.emit('toggleOrb', i);\n    toggleOrb(i);\n}\n<\/code><\/pre>\n<p>Next, listen for orb toggles, and toggle the corresponding orb. Directly underneath the <code>playerId<\/code> socket event listener, add another listener for the <code>toggleOrb<\/code> event.<\/p>\n<pre><code>socket.on('toggleOrb', function(i) {\n  document.querySelector(\"#container-orb\" + i).click();\n  toggleOrb(i);\n});\n<\/code><\/pre>\n<p>This concludes modifications to the client-side code. Double-check that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step08.html\">our source code for Step 8<\/a>.<\/p>\n<p>Server-side now needs to receive and broadcast the toggled orb ID. In the server-side <code>index.js<\/code>, add the following listener. This listener should be placed directly underneath the socket <code>disconnect<\/code> listener.<\/p>\n<pre><code>  socket.on('toggleOrb', function(i) {\n    socket.broadcast.emit('toggleOrb', i);\n  });\n<\/code><\/pre>\n<p>Double-check that your code matches <a href=\"https:\/\/github.com\/alvinwan\/lightful\/blob\/master\/tutorial2\/step08.js\">our source code for Step 8<\/a>. Now, player 1 loaded in one window and player 2 loaded in a second window will both see the same game state. With that, you have completed a multiplayer virtual reality game. The two players, furthermore, must collaborate to complete the objective. The final product will match the following.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/2-real-time-multiplayer-vr-game-1.gif?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/2-real-time-multiplayer-vr-game-1.gif?w=900&#038;ssl=1\" alt=\"The finished multiplayer game, synchronized across multiple clients\"><\/a><figcaption>The finished multiplayer game, synchronized across multiple clients. (<a href=\"https:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/2-real-time-multiplayer-vr-game-1.gif\">Large preview<\/a>)<\/figcaption><\/figure>\n<h3>Conclusion<\/h3>\n<p>This concludes our tutorial on creating a multiplayer virtual reality game. In the process, you\u2019ve touched on a number of topics, including 3-D modeling in A-Frame VR and real-time multiplayer experiences using WebSockets.<\/p>\n<p>Building off of the concepts we\u2019ve touched on, how would you ensure a smoother experience for the two players? This could include checking that the game state is synchronized and alerting the user if otherwise. You could also make simple visual indicators for the terminal state and player connection status.<\/p>\n<p>Given the framework we\u2019ve established and the concepts we\u2019ve introduced, you now have the tools to answer these questions and build much more.<\/p>\n<p><em>You can find the finished source code <a href=\"https:\/\/github.com\/alvinwan\/lightful\">here<\/a>.<\/em><\/p>\n<div data-component=\"FeaturePanel\" data-audience=\"non-subscriber\" data-remove=\"true\"><\/div>\n<div>\n  <img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/logo-red-5.png?w=900&#038;ssl=1\" alt=\"Smashing Editorial\"><span>(dm, il)<\/span>\n<\/div>\n<\/article>\n<p class=\"wpematico_credit\"><small>Powered by <a href=\"http:\/\/www.wpematico.com\" target=\"_blank\" rel=\"noopener noreferrer\">WPeMatico<\/a><\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00 In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series,&#8230;<a class=\"moretag\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/\"> Read the full article&#8230;<\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[371],"tags":[],"class_list":["post-73869","post","type-post","status-publish","format-standard","hentry","category-user-experience"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Guest Contribution\"\/>\n\t<meta name=\"keywords\" content=\"user experience\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies\" \/>\n\t\t<meta property=\"og:description\" content=\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-12-06T11:18:21+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-12-06T11:18:21+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies\" \/>\n\t\t<meta name=\"twitter:description\" content=\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#article\",\"name\":\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies\",\"headline\":\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)\",\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/12\\\/2-real-time-multiplayer-vr-game-1.gif?fit=%2C&ssl=1\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#articleImage\"},\"datePublished\":\"2019-12-06T04:18:21-07:00\",\"dateModified\":\"2019-12-06T04:18:21-07:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#webpage\"},\"articleSection\":\"User Experience\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"position\":2,\"name\":\"User Experience\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#listItem\",\"name\":\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#listItem\",\"position\":3,\"name\":\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/\",\"name\":\"Guest Contribution\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Guest Contribution\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#webpage\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/\",\"name\":\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies\",\"description\":\"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/12\\\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"datePublished\":\"2019-12-06T04:18:21-07:00\",\"dateModified\":\"2019-12-06T04:18:21-07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies","description":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed","canonical_url":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/","robots":"max-image-preview:large","keywords":"user experience","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#article","name":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies","headline":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)","author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/12\/2-real-time-multiplayer-vr-game-1.gif?fit=%2C&ssl=1","@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#articleImage"},"datePublished":"2019-12-06T04:18:21-07:00","dateModified":"2019-12-06T04:18:21-07:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#webpage"},"isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#webpage"},"articleSection":"User Experience"},{"@type":"BreadcrumbList","@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.taterboy.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","position":2,"name":"User Experience","item":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#listItem","name":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#listItem","position":3,"name":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)","previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}}]},{"@type":"Organization","@id":"https:\/\/www.taterboy.com\/blog\/#organization","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","url":"https:\/\/www.taterboy.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author","url":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/","name":"Guest Contribution","image":{"@type":"ImageObject","@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g","width":96,"height":96,"caption":"Guest Contribution"}},{"@type":"WebPage","@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#webpage","url":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/","name":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies","description":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/#breadcrumblist"},"author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"creator":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"datePublished":"2019-12-06T04:18:21-07:00","dateModified":"2019-12-06T04:18:21-07:00"},{"@type":"WebSite","@id":"https:\/\/www.taterboy.com\/blog\/#website","url":"https:\/\/www.taterboy.com\/blog\/","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","og:type":"article","og:title":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies","og:description":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed","og:url":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/","article:published_time":"2019-12-06T11:18:21+00:00","article:modified_time":"2019-12-06T11:18:21+00:00","twitter:card":"summary","twitter:title":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) | Design for Immersive Technologies","twitter:description":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2) Alvin Wan 2019-12-05T11:00:00+00:002019-12-06T11:06:21+00:00In this tutorial series, we will build a web-based multiplayer virtual reality game, where players will need to collaborate to solve a puzzle. In the first part of this series, we designed"},"aioseo_meta_data":{"post_id":"73869","title":null,"description":null,"keywords":null,"keyphrases":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_custom_image_width":null,"og_custom_image_height":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"created":"2021-02-07 16:23:17","updated":"2026-09-02 16:04:05","focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"primary_term":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"twitter_image_url":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"limit_modified_date":false,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/\" title=\"User Experience\">User Experience<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tHow To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.taterboy.com\/blog"},{"label":"User Experience","link":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/"},{"label":"How To Build A Real-Time Multiplayer Virtual Reality Game (Part 2)","link":"https:\/\/www.taterboy.com\/blog\/2019\/12\/how-to-build-a-real-time-multiplayer-virtual-reality-game-part-2\/"}],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8wzr5-jdr","jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/73869","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/comments?post=73869"}],"version-history":[{"count":0,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/73869\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media?parent=73869"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/categories?post=73869"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/tags?post=73869"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}