Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Totem Destroyer game, Game development, HTML5 and Javascript.

Back home and finally with a good internet connection, I am blogging again after the longest “no post” period in the story of the blog.

We are about to see a full Totem destroyer engine made using PhysicsJS, a new interesting javascript physics engine I reviewed in this post.

The engine has very nice features such as an intuitive way to create and skin bodies and a smart collision detection, but I’m finding it a bit unstable with stacked bodies, as you are about to see, because it feels a bit trembling.

Anyway, this is the totem destroyer prototype, featuring:

* Static (or “fixed”, as the engine calls them) and dynamic bodies
* Custom images applied to bodies
* Mouse interaction
* Collision detection

You should know how to play it: remove bricks by clicking on them and don’t let the totem hit the ground (anyway, make it fall to see what happens). Darker bricks cannot be removed.

As said, it looks a bit trembling, at least with 0.5.4 version. One idea would be making all bodies fixed until the first brick is removed, but I hope future versions will fix this issue without any workaround.

Here is the fully commented source code:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>PhysicsJS</title>
  		<script src="physicsjs-full.js"></script>
  		<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
		<style>
			body {
				margin:0px;
				background-color:black;
			}
			.gameover{
				background-color:red;
			}
		</style>
		<script>
			$(document).ready(function(){
				// world declaration
				var world = Physics();
				// creation of the renderer which will draw the world
				var renderer = Physics.renderer("canvas",{
    					el: "canvasid",	// canvas element id
					width: 640,		// canvas width
					height: 480,		// canvas height
					meta: false		// setting it to "true" will display FPS
				});	
				// adding the renderer to the world
				world.add(renderer);
				// what happens at every iteration step? We render (show the world)
				world.subscribe("step",function(){
    					world.render();
				});
				// this is the default gravity
				var gravity = Physics.behavior("constant-acceleration");
				// adding gravity to the world
				world.add(gravity);
  				// bodies will react to forces such as gravity
  				world.add(Physics.behavior("body-impulse-response"));
  				// enabling collision detection among bodies
  				world.add(Physics.behavior("body-collision-detection"));
				world.add(Physics.behavior("sweep-prune"));
				// adding the ground
				var ground = Physics.body("convex-polygon",{
   					x: 320,
   					y: 470,
   					fixed: true,
   					vertices: [
   						{x:0, y:0},
   						{x:0, y:20},
   						{x:640, y:20},
   						{x:640, y:0}
					],
					restitution:0.2,
					cof:1
 				});
 				// assigning a custom attribute to the ground body
 				ground.objType="ground";
 				// image representing the ground body
                    ground.view = new Image();
                    ground.view.src = "ground.png";
				world.add(ground);
				// adding bricks and totem with a function
				addBrick(380,440,[{x:0, y:0},{x:0, y:40},{x:40, y:40},{x:40, y:0}],"destroyable","brick");
				addBrick(260,440,[{x:0, y:0},{x:0, y:40},{x:40, y:40},{x:40, y:0}],"destroyable","brick");
				addBrick(320,400,[{x:0, y:0},{x:0, y:40},{x:160, y:40},{x:160, y:0}],"destroyable","brick4x1");
				addBrick(320,360,[{x:0, y:0},{x:0, y:40},{x:80, y:40},{x:80, y:0}],"unbreakable","solid2x1");
				addBrick(300,320,[{x:0, y:0},{x:0, y:40},{x:120, y:40},{x:120, y:0}],"destroyable","brick3x1");
				addBrick(320,260,[{x:0, y:0},{x:0, y:80},{x:160, y:80},{x:160, y:0}],"unbreakable","solid4x2");
				addBrick(320,190,[{x:0, y:0},{x:0, y:60},{x:40, y:60},{x:40, y:0}],"totem","totem");
 				// checking for collisions
				world.subscribe("collisions:detected", function(data){
                    	// looping through all collisions
					for (var i=0; i < data.collisions.length; i++){
                         	theCollision = data.collisions[i];
                         	// check if the totem touched the ground
                         	if (theCollision.bodyA.objType=="ground" && theCollision.bodyB.objType=="totem"){
                         		$("#canvasid").addClass("gameover");
                         	}
                         	// same as before, did not use an "or" for a layout purpose
                         	if (theCollision.bodyB.objType=="ground" && theCollision.bodyA.objType=="totem"){
                         		$("#canvasid").addClass("gameover");
						}
                    	}
                    });
			     $("#canvasid").click(function(e){
			     	// checking canvas coordinates for the mouse click
					var offset = $(this).offset();
					var px = e.pageX - offset.left;
     				var py = e.pageY - offset.top;
     				// this is the way physicsjs handles 2d vectors, similar at Box2D's b2Vec
					var mousePos = Physics.vector();
     				mousePos.set(px,py);
     				// finding a body under mouse position
     				var body = world.findOne({
						$at: mousePos
					})
					if(body && body.objType=="destroyable"){
						// there is a body under mouse position and can be destroyed, let's remove it
						world.removeBody(body);
					} 
				})
				// handling timestep
  				Physics.util.ticker.subscribe(function(time,dt){
    					world.step(time);
  				});
				Physics.util.ticker.start();
                    // function to generate bricks
                    function addBrick(x,y,vertices,type,image){
					var brick = Physics.body("convex-polygon",{
						x:x,
						y:y,
						vertices:vertices,
						restitution:0,
						cof:1,
						mass:0.5
					});
					brick.objType=type;
                         brick.view = new Image();
                         brick.view.src = image+".png";
					world.add(brick);
				}
			})
		</script>		
	</head>
<body>
	<canvas id="canvasid" width="640" height="480"></canvas>
</body>

</html>

And of course you can download the entire project with all required files.

Nice to meet you again!

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.