Introducing boxbox

Bocoup loves HTML5 games, so Darius Kazemi andI have been running a training calledIntro to HTML5 Game Development. We cover lots of fun stuff, including canvas animation and audio. When designing the training, we wanted trainees to make a simple game using a JavaScript physics engine. Box2dWebcame up as a good one to use, but I had a few concerns about it.

Box2dWeb is a port of Box2DFlashto JavaScript. Box2dFlash is a port of Box2D, a C++ rigid body physics simulation. You have probably played at least one game that uses Box2D, such as Angry Birds. The C++ code style persists in these ports, and what you get is distinctly non-JavaScripty code like this: (comments by me)

box2dweb-example.js

// Code from http://lib.ivank.net/?p=demos&d=box2D

// These look like imports, but in JavaScript they are just busy-work.
var
    b2Vec2          = Box2D.Common.Math.b2Vec2,
    b2BodyDef       = Box2D.Dynamics.b2BodyDef,
    b2Body          = Box2D.Dynamics.b2Body,
    b2FixtureDef    = Box2D.Dynamics.b2FixtureDef,
    b2World         = Box2D.Dynamics.b2World,
    b2PolygonShape  = Box2D.Collision.Shapes.b2PolygonShape;

// Constructor functions should use ProperCase in JavaScript.
world = new b2World(new b2Vec2(0, 10),  true);

// Someone without a programming background may not be able to guess
// what this abbreviation means.
up = new b2Vec2(0, -7);

// Here we're creating a fixture, then a body, then a shape. For
// simple learning exercises these distinctions aren't useful.
var fixDef = new b2FixtureDef();
fixDef.density = 1.0;

var bodyDef = new b2BodyDef();
bodyDef.type = b2Body.b2_staticBody; // mixed camelCase and _s
fixDef.shape = new b2PolygonShape();

// Here ProperCase is used for methods, which should be reserved
// for constructors in JavaScript.
bodyDef.position.Set(9, stage.stageHeight/100 + 1);
fixDef.shape.SetAsBox(10, 1);
world.CreateBody(bodyDef).CreateFixture(fixDef);

In a training where we have non-programmers and programmers who are new to JavaScript, this isn’t what I want people to learn from.

Don’t get me wrong: I love Box2D, Box2DFlash, and Box2dWeb. I wouldn’t use them if I didn’t. These are issues that naturally arise in semi-automated cross-language ports. Since I wanted to use Box2dWeb but with sugar, I made boxbox.

boxbox is a library that you use along with Box2dWeb. It wraps Box2dWeb and provides a simpler API and some handy new features. It is great for learning, prototyping, and simple games.

In this article, I am going to step through the process of creating a simple boxbox game. If you want to follow along, start out with the boilerplate here:

download boilerplate

This project already includes boxbox and Box2dWeb as well as a simple stylesheet. If you load up index.html in a browser you’ll see a blank slate.

Getting Started

Edit game.js. The first thing we’re going to do is create a “world”, which is a stand-alone physics simulation. It takes a canvas element as a parameter, since boxbox provides canvas rendering.

game-step-1.js

var canvas = document.getElementById("game");
var world = boxbox.createWorld(canvas);

Create the Player

The world is pretty boring without anything in it, so lets create our first entity. All entity options have defaults in boxbox, so if you create an entity without any options, you’ll get the most basic entity possible: a gray square in the middle of the screen.

game-step-2.js

var player = world.createEntity();

The world has gravity by default, so when you run the game, the square will just fall off the screen.

Try it!

Create the Ground

Let’s create an entity for the ground. This time we’ll provide some options to get the sort of entity we want.

game-step-3.js

var ground = world.createEntity({
  color: "green",
  x: 13,
  y: 18,
  width: 12,
  height: 0.5,
  type: "static"
});

This is still quite basic. We’re telling boxbox’s rendering layer to show this entity in green. We’re giving it a starting position and a width and height. Setting the type to static makes this entity immobile, so it will not be affected by gravity or collisions.

Now when you run the game, the box falls and lands on the ground.

Try it!

Keyboard Input

Let’s add keyboard input. To keep it simple, we’ll make it so that any key moves the player.

game-step-4.js

player.onKeydown(function(e) {
  this.applyImpulse(100, 45);
});

If you’re used to making websites, this should look familiar. this is set to the boxbox entity that the event was attached to. applyImpulse is a method that applies an instantaneous force on an entity. boxbox also supports continuous force with applyForce, but for now we’ll apply a swift kick to the entity each time a key is pressed. The first parameter to applyImpulse is the magnitude of the force (higher is stronger) and the second parameter is the direction of the force (in degrees). 45 degrees is to the upper right.

Create Targets

That works, but what fun is a physics engine without collisions? Let’s make a stack of targets to knock over. Here I demonstrate a boxbox feature that lets you share configuration among similar entities.

game-step-5.js

// Reusable template
var targetTemplate = {
  color: "blue",
  height: 1.5,
  width: 0.25
};

// Bottom level
world.createEntity(targetTemplate, {x: 18, y: 15});
world.createEntity(targetTemplate, {x: 21, y: 15});
world.createEntity(targetTemplate, {x: 24, y: 15});

// Bottom horizontal platform
world.createEntity({
  color: "purple",
  width: 3,
  height: 0.25,
  x: 21,
  y: 13
});

// Middle
world.createEntity(targetTemplate, {x: 23, y: 11});
world.createEntity(targetTemplate, {x: 19, y: 11});

// Top horizontal platform
world.createEntity({
  color: "purple",
  width: 2,
  height: 0.25,
  x: 21,
  y: 9
});

// Top level
world.createEntity(targetTemplate, {x: 21, y: 7});

Now you can see the beginnings of what this physics engine can do. You can also imagine what sort of game you can make from it 😉

Try it!

What’s Next

Want to take it to the next level? Try adding images instead of solid colors (boxbox takes care of rotating / scaling images), more keyboard control over the player, or tweak the density and friction of each entity to get different dynamics. If you want to report any bugs or make any changes, boxbox is MIT licensed and on Github. Happy coding!

Comments

Contact Us

We'd love to hear from you. Get in touch!

Phone

+1 617-283-2807

Mail

P.O. Box 961436
Boston, MA 02196