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.