Skip to content

MonkeyBlog

Lora Noto Sans Ag

More adventures

Hello World!

A little journey back to the past and why I started this blog

Building a Game with Javascript

It all started on one of those sleepless nights. You know the kind – when your mind refuses to shut off and thoughts keep racing. One of those thoughts was, could I create a game? A little side note: together with a colleague, I have a podcast called "Pixel Paranoia: The UX Podcast." In this podcast, we sometimes have guests. On one of our latest episodes, a colleague who was a game developer in the past was our guest. His enthusiasm about games was really contagious. Myself, a gamer since I was young, started wondering... could I create a game with JavaScript?

Picking the Right Tools

To start off, there are many choices for creating a game with JavaScript, and I tried several of them. One that was at the top of my list was PhaserJS. It provides a lot of out-of-the-box tools and methods, and it also offers a visual editor called Phaser Editor. I looked at the documentation of the APIs and, I don't know... it wasn't a match for me. One issue I have is that I want fast results and complete visual control. Somehow, it seemed like I first had to learn a lot about Phaser instead of simply using good old vanilla JavaScript.

What Type of Game?

Maybe you’re reading this and thinking, "But shouldn't you know what type of game you want to build?" You’re right, of course, but I also wanted to be inspired by the possibilities of the chosen engine. Since PhaserJS didn't make the cut, I started thinking about what type of game I wanted to build.

Currently, I play a lot of Rocket League. One of the great things about Rocket League is the physics aspect of the game. As a player, you need to learn advanced controls to do a simple task: score the ball in the goal with a small car. Sounds easy, right? The thing is, the physics in this game are really advanced – one of a kind, to be honest. That triggered me: could I make a game using real-life physics?

Physics. I Love It!

I started looking for a JavaScript engine that incorporates physics, and I stumbled upon Matter.js. It's a 2D physics engine for the web, and that's it – that's all it does. And I loved it for that. Just a "simple" physics engine I could use to build something with. Matter.js supports all kinds of physics, including:

  • Rigid bodies
  • Compound bodies
  • Physical properties (mass, area, density, etc.)
  • Restitution (elastic and inelastic collisions)
  • Conservation of momentum
  • Friction and resistance
  • Gravity
  • ...and many more

Do you know how much fun it is to play with all this stuff? I had so much fun.

Start Building

Like I mentioned before, I took some inspiration from Rocket League, especially the hitbox they use. I was amazed by how simple the hitbox was – just four circles and a box, that's it! Check out the video.

With that in mind, I started a small project with Matter.js. It's actually quite simple to start. You configure the engine, draw several bodies, and add them to the world.

Here's how you do it:

// module aliases
var Engine = Matter.Engine,
    Render = Matter.Render,
    Runner = Matter.Runner,
    Bodies = Matter.Bodies,
    Composite = Matter.Composite;

// create an engine
var engine = Engine.create();

// create a renderer
var render = Render.create({
    element: document.body,
    engine: engine
});

// create two boxes and a ground
var boxA = Bodies.rectangle(400, 200, 80, 80);
var boxB = Bodies.rectangle(450, 50, 80, 80);
var ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });

// add all of the bodies to the world
Composite.add(engine.world, [boxA, boxB, ground]);

// run the renderer
Render.run(render);

// create runner
var runner = Runner.create();

// run the engine
Runner.run(runner, engine);

You now have two rectangular boxes on a piece of static ground. The engine takes care of the rest. Of course, there is no interaction just yet. I started to create a car based on the hitbox concept of Rocket League – a box with two circles connected to it. First, we create a box:

const carBody = Matter.Bodies.rectangle(100, render.options.height - 200, 300, 100, {
    collisionFilter: { group: -1 },
    density: 0.003,
    frictionAir: 0.01,
    restitution: 0.8
});

Next, we need two wheels connected to the car:

const wheelA = Matter.Bodies.circle(22, render.options.height - 125, 50, {
    collisionFilter: { group: -1 },
    density: 0.003,
    friction: 1
});

const wheelB = Matter.Bodies.circle(22, render.options.height - 125, 50, {
    collisionFilter: { group: -1 },
    density: 0.003,
    friction: 1
});

Now, we need to tie everything together to make a car. By default, these are all separate objects with no knowledge of each other. We can do this by using something called constraint. Constraints are used to specify a fixed distance between two bodies (or a body and a fixed world-space position). The stiffness of that constraint can be modified to create springs or elasticity. When I read that in the documentation, a lightbulb went off in my head – free springs for the car!

Here's how the code looks:

const constraintA = Matter.Constraint.create({
    bodyA: carBody,
    pointA: { x: -78, y: 75 },
    bodyB: wheelA,
    pointB: { x: 0, y: 0 },
    stiffness: 0.05,
    render: {
        visible: false
    }
});

const constraintB = Matter.Constraint.create({
    bodyA: carBody,
    pointA: { x: 95, y: 75 },
    bodyB: wheelB,
    pointB: { x: 0, y: 0 },
    stiffness: 0.05,
    render: {
        visible: false
    }
});

The only thing left is to add these objects back to the world. We do this with the following code:

    Matter.Composite.add(engine.world, [carBody, wheelA, wheelB]);
    Matter.Composite.addConstraint(engine.world, constraintA);
    Matter.Composite.addConstraint(engine.world, constraintB);

And there we have it – a car. But of course, it doesn't drive yet; it's only there. So let's add some controls to move the car back and forth. We'll add an eventListener to the document to check if the player presses the ArrowRight or ArrowLeft key:

document.addEventListener('keyup', function(event) {
    switch(event.code) {
        case 'ArrowRight':
            Body.applyForce(wheelA, wheelA.position, { x: 0.05, y: 0 });
            Body.applyForce(wheelB, wheelB.position, { x: 0.05, y: 0 });
            break;
        case 'ArrowLeft':
            Body.applyForce(wheelA, wheelA.position, { x: -0.05, y: 0 });
            Body.applyForce(wheelB, wheelB.position, { x: -0.05, y: 0 });
            break;
    }
});

So, every time we press the left or right arrow key, we apply a force to both wheels on the X-axis. And that makes the car drive! And yes, if you only apply it to the back wheels, we get a rear-wheel drive car. Putting this all together, it looked something like in the next video:

And there you have it – my first little game with good-looking physics. I was so thrilled with this result in such a short time!