Creation of an HTML5 3D Sokoban level with Babylon.js
Talking about Sokoban game, 3D, Game development, HTML5 and Javascript.
Babylon.js is a 3D engine based on webgl and javascript which allows you to do a lot of interesting stuff thanks to its enormous list of features you can see in the official site.
To show you some basic concepts, I am going to build a 3D Sokoban level like I did some years ago with Unity and some Flash 3D engines, look at these posts:
* Flash 3D Sokoban prototype with Flare3D
* Flash 3D Sokoban prototype with Away3D
* 3D Sokoban prototype with Unity
During the creation of this little level, we are going to learn these concepts:
* Create a scene
* Create an environmental fog
* Create a Box primitive
* Create a Sphere primitive
* Apply a diffuse color to a primitive (that is, paint it the color you want)
* Create a light
* Modify the size of primitives
* Add and control a camera – touch controls are managed by hands.js
This what we are going to do:
You can move the can along fixed arcs with mouse or arrow keys.
And this is the source code, first the HTML part:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="babylon.1.12.js"></script>
<script src="hand.js"></script>
<style>
html, body, canvas {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<script src="game.js"></script>
</body>
</html>
Then, the fully commented javascript part, which is game.js file:
// array representation of a classic Sokoban level
var level=[[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,1,1,1,1,0,0,0,0,0],[0,1,0,0,1,1,1,1,1,0],[0,1,0,2,0,0,3,0,1,0],[0,1,0,3,0,0,2,4,1,0],[0,1,1,1,0,0,1,1,1,0],[0,0,0,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]];
// identifying the canvas id
var canvas = document.getElementById("gameCanvas");
// creation of the engine itself
var engine = new BABYLON.Engine(canvas,true);
// attaching a scene to the engine. This is where our game will take place
var scene = new BABYLON.Scene(engine);
// adding a little fog to the scene, to give some kind of "depth" to the scene
scene.fogMode = BABYLON.Scene.FOGMODE_EXP;
// the density is very high, so a low value is recommended
scene.fogDensity = 0.05;
// creation of a camera, the type is "AcrRotate".
// this mean the camera is bound along two arcs, one running from north to south, the other from east to west
// the first argument is the came of the camera instance
// the second argument is the angle along the north-south arc, in radians (3 * Math.PI / 2)
// the 3rd argumentis the angle along the east-west arc, in radians (3*Math.PI/4)
// the 4th argument is the radius of such arcs (20)
// the 5th argument is the camera target (BABYLON.Vector3.Zero()) in this case the origin
// finally, the scene where to attach the camera ("scene")
var camera = new BABYLON.ArcRotateCamera("camera",3 * Math.PI / 2, 3*Math.PI/4, 20, BABYLON.Vector3.Zero(), scene);
// adding touch controls to camera, that's where hand.js come into play
camera.attachControl(canvas, false);
// adding a point light to the scene at posiiton 0, -5, -10
var light = new BABYLON.PointLight("light",new BABYLON.Vector3(0,-5,-10),scene);
// looping through the array to build the level
for(i=0;i<10;i++){
for(j=0;j<10;j++){
// creation of a box with a side of 1 and adding it to the scene
var box = BABYLON.Mesh.CreateBox("floorBox", 1, scene);
// creation of a basic material
var boxMaterial = new BABYLON.StandardMaterial("material", scene);
// this is just a random number
var randomColorOffset = Math.random()*0.1
// if we are dealing with a target tile...
if(level[j][i]==2||level[j][i]==5||level[j][i]==6){
// ... give the box a red diffuse color
boxMaterial.diffuseColor = new BABYLON.Color3(0.45+randomColorOffset,0,0);
}
else{
// otherwise give it a grey diffuse color
boxMaterial.diffuseColor = new BABYLON.Color3(0.45+randomColorOffset,0.45+randomColorOffset,0.45+randomColorOffset);
}
// assigning the box the material
box.material=boxMaterial;
// placing the box in the right position
box.position = new BABYLON.Vector3(-4.5+j,-4.5+i,0);
// scaling the box along z axis, making it look like a tile
box.scaling.z = 0.25;
if(level[j][i]==1){
// creation of a wall, not that different, but we don't scale it and we assign it a darker color
box = BABYLON.Mesh.CreateBox("wallBox", 1, scene);
boxMaterial.diffuseColor = new BABYLON.Color3(0.25+randomColorOffset,0.25+randomColorOffset,0.25+randomColorOffset);
box.material=boxMaterial;
box.position = new BABYLON.Vector3(-4.5+j,-4.5+i,-0.5);
}
if(level[j][i]==3){
// same thing for a crate, paint it by orange
box = BABYLON.Mesh.CreateBox("crateBox", 1, scene);
var crateMaterial = new BABYLON.StandardMaterial("material", scene);
crateMaterial.diffuseColor = new BABYLON.Color3(0.45+randomColorOffset,0.25+randomColorOffset,0);
box.material=crateMaterial;
box.position = new BABYLON.Vector3(-4.5+j,-4.5+i,-0.5);
}
if(level[j][i]==4||level[j][i]==6){
// we want the player to be a ball, so here is how we create a ball:
// the second argument is the detail (10) - the lower the detail, the lighter the rendering
// the 3rd argument is the diameter
var sphere = BABYLON.Mesh.CreateSphere("sphere", 10, 1, scene);
// and we paint it green
sphere.position = new BABYLON.Vector3(-4.5+j,-4.5+i,-0.5);
var sphereMaterial = new BABYLON.StandardMaterial("material", scene);
sphereMaterial.diffuseColor = new BABYLON.Color3(0,0.5,0);
sphere.material=sphereMaterial;
}
}
}
engine.runRenderLoop(function () {
scene.render();
});
Next time, I am going to add interactivity and textures, meanwhile you can download the source code with all required libraries.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.