Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Concentration game, 3D, Game development, HTML5 and Javascript.

Earlier this week I showed you the creation of a 3D Sokoban level with Babylon.js, now it’s time to create something interactive, like a Concentration game.

In this step, I will only focus on the creation and selection of a single tile, but the topics covered are quite a number and pretty advanced, such as:

* Texture mapping
* Using different textures on different meshes of the same body
* Directional lights
* Shadows
* Selection of bodies with the mouse
* Animations and keyframes

This is what you are going to build:

Click on the yellow tile to turn it and reveal its hidden color.

The concept behind the script continues where the creation of 3D Sokoban level with Babylon.js ended, so I recommend to start from the previous example if you are new to Babylon.

The new, fully commented content of game.js used to make this example is:

// just a Boolean variable to say if we picked the tile
var picked=false;
// 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, 11*Math.PI/16, 20, BABYLON.Vector3.Zero(), scene);
// adding touch controls to camera, that's where hand.js come into play
camera.attachControl(canvas, false);
// we need a directional light in order to cast a shadow
var light = new BABYLON.DirectionalLight("light", new BABYLON.Vector3(5,0,20), scene);
light.position = new BABYLON.Vector3(1,1,-10);
 
// this is the table material. We will map an image called "wood.jpg" on it
var tableMaterial = new BABYLON.StandardMaterial("tableMaterial", scene);
tableMaterial.diffuseTexture = new BABYLON.Texture("wood.jpg", scene);

// card material will be made with 2 different materials.
// The first material is "cardMaterial", a yellow color
var cardMaterial = new BABYLON.StandardMaterial("cardMaterial", scene); 
cardMaterial.diffuseColor = new BABYLON.Color3(1,1,0);
// the second material is "cardBackMaterial", a purple color
var cardBackMaterial = new BABYLON.StandardMaterial("cardBackMaterial", scene); 
cardBackMaterial.diffuseColor = new BABYLON.Color3(1,0,1);

// with these two colors in mind, let's built a multi material
var cardMultiMat = new BABYLON.MultiMaterial("cardMulti", scene);
// here is how we push the materials into a multimaterial
cardMultiMat.subMaterials.push(cardMaterial);
cardMultiMat.subMaterials.push(cardBackMaterial);
// this is the content of our multi material - 0: CardMaterial, 1: CardBackMaterial

// THE TABLE
var table = BABYLON.Mesh.CreateBox("table", 10, scene);
table.scaling.z = 0.025;
table.scaling.x = 2;
table.material=tableMaterial
// we must specify that the table is receving shadows
table.receiveShadows = true;

// THE CARD
var card = BABYLON.Mesh.CreateBox("card", 2, scene);
card.scaling.z = 0.125;
card.position = new BABYLON.Vector3(0,0,-0.25);
// defining two different meshes, one for the bottom face and one for the rest of the card
card.subMeshes=[];
// arguments of Submesh are:
// 1: the index of the material to use
// 2: the index of the first vertex
// 3: the number of verices used
// 4: index of the first indice to use
// 5: the number of indices
// 6: the main mesh 
card.subMeshes.push(new BABYLON.SubMesh(0, 4, 20, 6, 30, card));
card.subMeshes.push(new BABYLON.SubMesh(1, 0, 4, 0, 6, card));

// finally assigning the multi material to the card
card.material=cardMultiMat

// attaching the light to shadow generator
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
// here is how we say the card should cast shadows
shadowGenerator.getShadowMap().renderList.push(card);
   
engine.runRenderLoop(function () {
     scene.render();
});

// a simple click listener
window.addEventListener("click", function (evt) {
	// with "scene.pick" we can obtain information about the stuff we picked/clicked 
	var pickResult = scene.pick(evt.clientX, evt.clientY);
	// if we haven't already picked anything and we are picking a mesh and that mesh is called "card"...
	if(!picked && pickResult.pickedMesh!=null && pickResult.pickedMesh.name=="card"){
		// set "picked" to true as we won't be able to pick it again
		picked=true;
		// let's start the animation
		var moveAnimation = new BABYLON.Animation(
			"moveAnimation", // name I gave to the animation 
			"position.z", // property I am going to change
			30, // animation speed
			BABYLON.Animation.ANIMATIONTYPE_FLOAT, // animation type
               BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT // animation loop mode
			// play with BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE,
			// BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
			// BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
		);

        	var rotateAnimation = new BABYLON.Animation(
			"rotateAnimation",
			"rotation.y", // this time I rotate the tile around y axis
			30,
			BABYLON.Animation.ANIMATIONTYPE_FLOAT,
               BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
		);

		// now let's add keyframes to our animations
		var moveKeys = [
			{
				frame: 0,
				value: -0.25
			},
			{
				frame: 20,
				value: -2
			}
		];
    		
    		var rotateKeys = [
			{
				frame: 0,
        			value: 0
			},
			{
				frame: 20,
        			value: 0
			},
			{
				frame: 40,
        			value: Math.PI
			}			    
		]
    
    		// adding keyframes to animation
    		moveAnimation.setKeys(moveKeys);
    		rotateAnimation.setKeys(rotateKeys);

    		// adding animations to the card
    		card.animations.push(moveAnimation);
    		card.animations.push(rotateAnimation);

    		// launching animation
		scene.beginAnimation(card, 0, 40, true);     	
    }
});

As you can see, everything is easy and intuitive with Babylon, next time I will show you a complete 3D Concentration game, meanwhile 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.