Complete HTML5 Totem destroyer engine using PhysicsJS

Read all posts about "" game

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!

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers