Build a HTML5 game like “Mikey Hooks” using Phaser and Matter.js

Read all posts about "" game

Mikey Hooks is a great game. Fullstop.

I liked so much the way the player used the hook, and I built prototypes using Flash + Box2D, Flash + Nape (Nape seems to be discontinued), Phaser + Box2D and Unity.

No matter the language, engine or framework you are using to build your hooks, they will all rely on a constraint called distance joint.

A constraint on a system is a parameter that the system must obey. In this case, the constraint is a distance joint which says “no matter what happens, there must be a given distance between two bodies”.

And that’s all:

Click on a box and hold to create a distance joint from the ball to the box working like a hook and start swinging by clicking and holding on different boxes.

The code is just a matter of checking if we clicked on a box, then create the joint until the mouse is released or a collision occurred.

Here it is, fully commented:

let game;
let gameOptions = {
    gravity: 1,             // game gravity
    terrainObjects: 20,     // amount of terrain objects
    ballRadius: 20,         // radius of the ball
    constraintSpeed: 4,     // constraint shrinkage speed
    minBoxSize: 50,        // minimum box size
    maxBoxSize: 200         // maximum box size
}
const WALL = 0;
const BALL = 1;
window.onload = function() {

    // game configuration
    let gameConfig = {
        type: Phaser.AUTO,
        scale: {
            mode: Phaser.Scale.FIT,
            autoCenter: Phaser.Scale.CENTER_BOTH,
            parent: "thegame",
            width: 1334,
            height: 750
        },
        scene: playGame,
        physics: {
            default: "matter",
            matter: {
                gravity: {
                    y: gameOptions.gravity
                },
                debug: true
            }
        }
    }
    game = new Phaser.Game(gameConfig);
    window.focus();
}
class playGame extends Phaser.Scene{
    constructor(){
        super("PlayGame");
    }
    create(){

        // I want physics world to be updated 30 times per second
        this.matter.world.update30Hz();

        // adding world bounds. Basically four walls
        this.matter.world.setBounds(10, 10, game.config.width - 20, game.config.height - 20);

        // placing some random static boxes labeled as WALL
        for (let i = 0; i < gameOptions.terrainObjects; i++){
            let posX = Phaser.Math.Between(0, game.config.width);
            let posY = Phaser.Math.Between(0, game.config.height);
            let width = Phaser.Math.Between(gameOptions.minBoxSize, gameOptions.maxBoxSize);
            let height = Phaser.Math.Between(gameOptions.minBoxSize, gameOptions.maxBoxSize);
            let poly = this.matter.add.rectangle(posX, posY, width, height, {
                isStatic: true
            });
            poly.label = WALL;
        }

        // adding a bouncing ball labeled as BALL
        this.ball = this.matter.add.circle(game.config.width / 2, game.config.height / 2, gameOptions.ballRadius, {
            restitution: 0.5
        });
        this.ball.label = BALL;

        // event listeners
        this.input.on("pointerdown", this.fireHook, this);
        this.input.on("pointerup", this.releaseHook, this);

        // no ropes at the beginning
        this.rope = null;

        // when the ball collides on something, we'll remove the hook
        this.matter.world.on("collisionstart", function(e, b1, b2){
            if(b2.label == BALL){
                this.releaseHook();
            }
        }, this)
    }

    // method to fire the hook
    fireHook(e){

        // getting all bodies
        let bodies = this.matter.world.localWorld.bodies;

        // looping through bodies
        for(let i = 0; i < bodies.length; i++){

            // getting body vertices
            let vertices = bodies[i].parts[0].vertices;

            // do the vertices contain the pointer AND the body is labeled as WALL?
            if(Phaser.Physics.Matter.Matter.Vertices.contains(vertices, e.position) &amp;&amp; bodies[i].label == WALL){

                // calculate the distance between the ball and the body
                let distance = Phaser.Math.Distance.Between(this.ball.position.x, this.ball.position.y, bodies[i].position.x, bodies[i].position.y)

                // is the distance greater than ball radius?
                if(distance > gameOptions.ballRadius){

                    // add the constraint
                    this.rope = this.matter.add.constraint(this.ball, bodies[i], distance, 0);
                }
                break;
            }
        }
    }

    // method to remove the hook
    releaseHook(){

        // is there a constraint? Remove it
        if(this.rope){
            this.matter.world.removeConstraint(this.rope);
            this.rope = null;
        }
    }

    // method to be executed at every frame
    update(){

        // is there a constraint? Shrink it
        if(this.rope){
            this.rope.length -= gameOptions.constraintSpeed;
        }
    }
};

At the moment the hook always starts from the center of the box, but I am working on a more interesting way using raycasting… stay tuned and meanwhile download the source code of this example.

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

214 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
// 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