Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Game development, HTML5, Javascript and Phaser.

Back in 2011 I tried to build a script to slice, split and cut Box2D bodies using AS3.

This happened eight years ago, which represent a couple of centuries or even more in game development.

Back to our days with current technologies, I tried to do it with Phaser and Matter.js. Before you jump to the example and the source code, I have to say the result works like a charm thanks to the awesome PolyK which is seven years old but fortunately geometry doesn’t age like software does.

Thanks to PolyK, now you can slice your physics bodies created with Matter.js in Phaser. This is quite a milestone, because it opens a door leading you to new concepts of HTML5 game design.

Ok, let’s see the example in action:

Drag the mouse to draw the line and cut that box. How does it work? You should know how to draw a line with the mouse, and it’s quite boring to explain so let’s jump straight to the point:

* Each time you draw a line, we know it start and end points

* We loop through all Matter bodies and get their vertices. At this time, bodies are just polygons

* We check if the line splits in two the polygon thanks to PolyK’s Slice method.

* If the result of Slice method consists in two – or more – polygons, then the original polygon has been sliced!

* We remove the sliced Matter body.

* We calculate the centroid of each polygon born from the sliced body

* We finally create the new Matter bodies from the vertices of the resulting poligons

Look at the source code, uncommented but quite easy to understand:

let game;
window.onload = function() {
    let gameConfig = {
        type: Phaser.AUTO,
        scale: {
            mode: Phaser.Scale.FIT,
            autoCenter: Phaser.Scale.CENTER_BOTH,
            parent: "thegame",
            width: 640,
            height: 480
        },
        scene: playGame,
        physics: {
            default: "matter",
            matter: {
                gravity: {
                    y: 1
                },
                debug: true,
            }
        }
    }
    game = new Phaser.Game(gameConfig);
    window.focus();
}
class playGame extends Phaser.Scene{
    constructor(){
        super("PlayGame");
    }
    create(){
        this.matter.world.update30Hz();
        this.matter.world.setBounds(10, 10, game.config.width - 20, game.config.height - 20);
        this.matter.add.rectangle(game.config.width / 2 - 50, game.config.width / 2, 100, 300);
        this.lineGraphics = this.add.graphics();
        this.input.on("pointerdown", this.startDrawing, this);
        this.input.on("pointerup", this.stopDrawing, this);
        this.input.on("pointermove", this.keepDrawing, this);
        this.isDrawing = false;
    }
    startDrawing(){
        this.isDrawing = true;
    }
    keepDrawing(pointer){
        if(this.isDrawing){
            this.lineGraphics.clear();
            this.lineGraphics.lineStyle(1, 0x00ff00);
            this.lineGraphics.moveTo(pointer.downX, pointer.downY);
            this.lineGraphics.lineTo(pointer.x, pointer.y);
            this.lineGraphics.strokePath();
        }
    }
    stopDrawing(pointer){
        this.lineGraphics.clear();
        this.isDrawing = false;
        let bodies = this.matter.world.localWorld.bodies;
        let toBeSliced = [];
        let toBeCreated = [];
        for(let i = 0; i < bodies.length; i++){
            let vertices = bodies[i].parts[0].vertices;
            let pointsArray = [];
            vertices.forEach(function(vertex){
                pointsArray.push(vertex.x, vertex.y)
            });
            let slicedPolygons = PolyK.Slice(pointsArray, pointer.downX, pointer.downY, pointer.upX, pointer.upY);
            if(slicedPolygons.length > 1){
                toBeSliced.push(bodies[i]);
                slicedPolygons.forEach(function(points){
                    toBeCreated.push(points)
                })

            }
        }
        toBeSliced.forEach(function(body){
            this.matter.world.remove(body)
        }.bind(this))
        toBeCreated.forEach(function(points){
            let polyObject = [];
            for(let i = 0; i < points.length / 2; i ++){
                polyObject.push({
                    x: points[i * 2],
                    y: points[i * 2 + 1]
                })
            }
            let sliceCentre = Phaser.Physics.Matter.Matter.Vertices.centre(polyObject)
            let slicedBody = this.matter.add.fromVertices(sliceCentre.x, sliceCentre.y, polyObject, {
                isStatic: false
            });
        }.bind(this))
    }
};

There are a lot of things you can do once you are able to slice physic bodies, which game would you try to build? Download the source code and don’t forget to thank PolyK for the wonderful opportunity.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.