Build your First Web VR Game for the Absolute Beginner
This is source and tutorial for building your first website and first web vr game - all in one!
Create index.html and index.js files
- Open VS code and create a new file called index.html
- Copy and paste this html and css into the file.
<html>
<head>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
text-align: center;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
<!-- Babylon.js -->
<script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/gltf_validator.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script src="index.js"></script>
</body>
</html>
- Now create the index.js file and copy and paste this code into it.
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
function createScene() {
// Create scene
var scene = new BABYLON.Scene(engine);
// Add Camera
var camera = new BABYLON.UniversalCamera("UniversalCamera", new BABYLON.Vector3(0, 0, -10), scene);
// Targets the camera to a particular position. In this case the scene origin
camera.setTarget(BABYLON.Vector3.Zero());
// Attach the camera to the canvas
camera.attachControl(canvas, true);
// Add Light
var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);
// Create sphere
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 5 }, scene);
sphere.position.y = 10;
sphere.position.x = -10;
sphere.position.z = -10;
sphere.material = new BABYLON.StandardMaterial("sphere material", scene);
// Create Ground
var ground = BABYLON.Mesh.CreateBox("Ground", 1, scene);
ground.scaling = new BABYLON.Vector3(100, 1, 100);
ground.position.y = -10.0;
ground.checkCollisions = true;
//Ground material
var groundMat = new BABYLON.StandardMaterial("groundMat", scene);
groundMat.diffuseColor = new BABYLON.Color3(0.5, 0.5, 0.5);
groundMat.emissiveColor = new BABYLON.Color3(0.2, 0.2, 0.2);
groundMat.backFaceCulling = false;
ground.material = groundMat;
// Enable VR
var vrHelper = scene.createDefaultVRExperience();
vrHelper.enableInteractions();
return scene;
}
var scene = createScene();
engine.runRenderLoop(() => {
scene.render();
});
- Save file and navigate to the file explorer. Double click the index.html (browswer will open ooo ahhh I made a site)
Now lets add gravlity to our site
- To add gravity to our game we need to add the physics engine. The physics engine we will use is Cannonjs and we already imported the library with our script tags.
<script src="https://preview.babylonjs.com/cannon.js"></script>
- Add gravity to the camera by pasting this code below
camera.attachControl(canvas, true);
online 16
// Apply Gravity to Camera
camera.applyGravity = true;
- Enable physics and set the gravitational force with a vector on
line 22
// Enable Physics and set gravtiy force with a vector
var gravityVector = new BABYLON.Vector3(0, -1, 0);
scene.enablePhysics(gravityVector, new BABYLON.CannonJSPlugin());
- Add a
physicsImposter
to thesphere
online 32
sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1, restitution: 0.9 }, scene);
- Add a
physicsImposter
to theground
online 46
ground.physicsImpostor = new BABYLON.PhysicsImpostor(ground, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 0, friction: 0.5, restitution: 0.7 }, scene);
- Save the changes and refresh the browser. You should now see the sphere fall from the sky and bounce on the ground. NOTE: If you are having any issues check out this commit to the repo. Its what your files should look like after this step: Link to commit
This is kinda cool. We now have one sphere falling from the sky and bouncing onto the ground. But wouldnt it be way cooler if you had lets say 10 spheres falling? Lets do that next!
- Add
addSpheres
function online 56
below ourcreateScene
function
var addSpheres = function (scene, amount) {
for (let index = 0; index < amount; index++) {
let sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 1 }, scene);
sphere.position = new BABYLON.Vector3(Math.random() * 20 - 10, 10, Math.random() * 10 - 5);
sphere.material = new BABYLON.StandardMaterial("sphere material", scene);
sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1 }, scene);
}
}
- Delete or comment out the code that was creating the sphere in the
createScene
function onlines 27-32
.
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 5 }, scene);
sphere.position.y = 10;
sphere.position.x = -10;
sphere.position.z = -10;
sphere.material = new BABYLON.StandardMaterial("sphere material", scene);
sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1 }, scene);
- Add a call to the
addSpheres
function we just created. This goes online 27
. This is calling the function we created, passing in the scene we want to add the spheres to and defining how many spheres we want.
addSpheres(scene, 10);
Lets add a button to trigger the spheres falling from the sky
- Copy and paste the below script on
line 43
below theground.physicsImpostor
variable. - This block of code is doing multiple things:
a. Creating a button and the button attributes.
b. Creating a full screen canvas texture to add our button to.
c. Then we moved theaddSpheres
method inside of the button event that fires on click. This will add the spheres and remove the button visibility to make the game start.
// GUI
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
var button = BABYLON.GUI.Button.CreateSimpleButton("button", "Start Game");
button.width = 0.2;
button.height = "40px";
button.color = "white";
button.background = "blue";
button.onPointerUpObservable.add(function () {
addSpheres(scene,10);
button.isVisible = false;
});
advancedTexture.addControl(button);
Make the spheres disappear on click (shoot) event
- Add event with the
actionManager
to spheres so they disappear when shot. Copy and paste below online 70
//add click event to sphere
sphere.actionManager = new BABYLON.ActionManager(scene);
sphere.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickUpTrigger, function () {
scene.removeMesh(sphere);
score++;
console.log("score: " + score);
}));
- We added score in the event so lets define the variable on
line 63
.
var score = 0;
- Now we have spheres falling and we can click on them to disappear. The problem here is that if the spheres just sit on the ground the player can keep shooting them. Lets remove the
ground.physicsImpostor
so spheres fall through instead of piling up. We can do this by commenting on the below code online 39
//ground.physicsImpostor = new BABYLON.PhysicsImpostor(ground, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 0, friction: 0.5, restitution: 0.7 }, scene);
- Uncomment the enable VR block so that we can run our game in VR.
var vrHelper = scene.createDefaultVRExperience();
vrHelper.enableInteractions();
Congrats! You built a game!
Now you have the basic workings of a game and the source for what you created is here in this repo. You can pick up right where you left off on any computer and continue to build out your game and add features.
How to host a static site on azure
- Go to https://portal.azure.com
- Click
Create a resource
- Click
Storage account
- Select
Create new
Resource Group - Give your storage account a name. Something like
myawesomegame
- Select a Location (this is the location of the data center that has all the servers ready for us to use)
- Leave the defaults for all the other fields the click
Review + create
- Click Create. It will take a minute to deploy and create your resource
- Go to the resource when you get the confirmation that it has been created
- Click
Static website
from the left hand navigation then clickEnabled
- Index document name is
index.html
then clickSave
- Select the
$Web
link that appears after your save. This will bring us to the blob storage we want to upload our files to. - Click
Upload
- Click the Folder Icon to navigate to your
index.html
andindex.js
files that we created in this tutorial - Select both the
index.html
andindex.js
files and click open - Click
Upload
- Exit out of the upload pane by clicking the
X
in the upper right corner. - Select
Change access level
from the top nav - Select
Container (anonymous read access for containers and blobs)
- Select
OK
- Use the bread crumbs nav at the very top to navigate back to the static website pane.
- Copy the
Primary endpoint
url and paste it into the browser. (Make sure the Index Document name is set toindex.html
) - TADA! Your game is hosted! Thanks Azure! :D
Here are ideas and code snippets for how you could continue to expand on the game.
Add label to keep score
var scoreText = new BABYLON.GUI.TextBlock();
scoreText.text = "Score: " + currentScore.toString();
scoreText.color = "white";
scoreText.fontSize = 24;
advancedTexture.addControl(scoreText);
Play with colors
- One way to change the colors of meshes (spheres and ground) is to add light effects to the scenes light varible. Use Color3 which takes Red, Green, Blue (RGB) numbers to create a color. Add the below block of code on
line 20
and see how it changes the colors in your scene!
//Diffuse - the basic color or texture of the material as viewed under a light;
light.diffuse = new BABYLON.Color3(1, 0, 0);
//Specular - the highlight given to the material by a light;
light.specular = new BABYLON.Color3(0, 1, 0);
light.groundColor = new BABYLON.Color3(0, 1, 0);
Play with gravity to make the spheres fall faster or slower
var gravityVector = new BABYLON.Vector3(0, -10, 0);
Add Sound when sphere disappears
Docs to add sound: https://doc.babylonjs.com/how_to/playing_sounds_and_music
Helpful Links
BabylonJS playground https://www.babylonjs-playground.com/
Live example can be found at https://cloudvr.games