Back story
The original version of this project was built using a Daydream controller.
To make it accessible to more people, I've spent some time changing it so you can use your phone instead.
However, FIY, you can also build your own controller using something like an Arduino, accelerometer and bluetooth module if you feel like it! 😃
For the 1st version of this project, I used Web Bluetooth to connect the Daydream controller directly to the browser and I was hoping the code would stay quite similar, but I realised phones cannot connect to laptops using the Web Bluetooth API. Both phone and laptop can only be "central" devices, and not "peripheral", so I've had to change this demo to use Web Sockets instead to communicate between the phone and the laptop.
How does it work?
This version of the experiment works by having the main webpage open on your computer and another webpage open on your mobile phone to get the accelerometer data.
Using the DeviceOrientation Web API, the orientation of the phone is detected and sent to the browser on your laptop via WebSockets.
By placing your phone on a skateboard, it can become a controller. You can use the orientation data to apply it to the 3D environment and interact with the game as if you were on a hoverboard.
What this tutorial is about
I'm not gonna go through the whole code as I don't think going through it line by line will be very beneficial. Instead, i'm going to explain the core parts of the prototype.
If you want to skip all this and just check out the Github repo, the CodeSandbox or try the live demo, feel free.
Material needed:
- A modern mobile phone (any phone that has an accelerometer built-in).
- A computer.
- A projector (optional).
Tech stack:
- HTML
- CSS
- JavaScript (Vanilla JS, no framework knowledge needed!).
- DeviceOrientation Web API
- Node.js with Socket.io
Step 1: Setup the Node.js server and web sockets
To get started, we need to set up a server to serve our files, expose routes and set up socket.io.
In the code sample above, we require some modules, start an Express server and indicate the path and routes to serve our files.
We also set up a basic socket.io connection that will wait for the communication between the server and front-end to be established. Once connected, socket.io will wait for certain messages from the front-end.
The 1st message should be received when the user visits the mobile page so we can confirm that they are ready to interact with the game. When this message is received, we emit one that the page on desktop will be listening to so we can start the game.
The 2nd message will be received when the mobile starts streaming orientation data. This message will emit an event to the desktop browser with the data so it can be applied to the hoverboard.
Now that our server is set up, let's work on the front-end.
Step 2: Getting and streaming orientation data
Using the DeviceOrientation Web API, we're able to get orientation data from the mobile phone.
To set this up and send it back to the server, we need code that looks like this:
Here, we're instantiating socket.io and when the page loads, we're sending a first message to the server to indicate that the mobile page has been visited.
Then, we have an event listener that checks for deviceorientation
events. On change, we call the handleOrientation
function that sends another event to the server with the data on a certain axis. This data represents the change of position from left to right as you tilt the skateboard.
Now that the page on mobile is sending orientation data to the server, let's see how the desktop page is listening to it.
Step 3: Listen to the orientation data in the game
To be able to use the orientation data from the phone on the laptop, we need to be listening to the message sent by the server.
Again, we instantiate socket.io, and when we receive the message mobile orientation
from the server, we're able to use the tilt data in our game.
In the code sample above, I also added a previousValue
variable so we would only be using the orientation data if it is different from the one previously received.
Now that we set up a basic communication between the server and front-ends, as well as got the orientation data from the phone, we can start building the game around it using Three.js.
Step 4: Setting up the game
Loading the libraries
The 3D environment built in this project is using Three.js. To start using it as well as a few add-ons, we need to include them in our HTML.
Not all of these are needed if you want to create a basic game. The files CopyShader
, DigitalGlitch
, EffectComposer
, ShaderPass
and GlitchPass
are only used for the effect I added on collision with an obstacle.
The main resources needed here are the Three.js library, the noiseSimplex
script to generate the plane and the OBJ
and MTL
loaders to load the 3D assets used for the hoverboard and obstacles.
Creating a 3D scene
To create a scene, you need to write the following lines:
In the code above, we're creating the scene, the camera, the renderer and appending everything to the body.
You can also add lights to your scene. There are different types of lights you can use but in my current prototype, I used an ambient light and spotlight:
Now we have a basic scene but there's nothing in it. Let's start by generating the landscape we can see in the demo.
Generating a terrain
Setting up the landscape is a little more complex. It starts with a simple PlaneGeometry
and WireframeGeometry
.
However, we can see in the demo that we have an effect of generative "mountains". To do this, we need to play with the vertices of our PlaneGeometry
.
Using our geometries previously defined, we're going to use the SimplexNoise
script to help us create an effect of wavy terrain by manipulating the vertices.
To have this effect be continuous throughout the game, we need to call this function with requestAnimationFrame
.
Now that we have a terrain, we also need to add some rocks (obstacles) and the hoverboard.
Loading 3D models
The rocks and the skateboard are 3D models. To load them, we need the following lines:
With the lines above, we create an OBJLoader
, we give it the path to our .obj
file and we set its size & position in the scene. We also set a color material, and finally, we add it to the scene.
The code for the rocks is pretty much the same.
So, we've covered how to create a simple scene, add a procedural terrain, 3D models, but we're missing the interactive part.
Making it interactive
Now that we have our scene set up, we can use the orientation data we talked about previously to update the position of the hoverboard model in our scene.
To do so, we need code like this:
This code sample is similar to the one showed a bit earlier in this tutorial except that now we have our skateboard
available in our scene so we are able to change its position based on the data coming back from our phone!
As said before, there's a bit more code than this for the full experience but in terms of core concepts, that's it! 😃🎉
If you want to check the code, here's the Github repo. Otherwise here's the live demo!
Hope you find it fun! 😊👋
Top comments (6)
This is SO cool, thanks for sharing! I'm hoping to find some time to tinker around with it soon... definitely bookmarking for now. 💜
Nice share, I am playing about 15 minutes your game, really interesting to learn about this.
Nice, lets hack the time
thepracticaldev.s3.amazonaws.com/i...
This is so cool... Thanks for sharing.. I'll try it out and share my thoughts
Am not able to run this on local server. Whenever I click the start button after starting the server, it does nothing.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.