Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Surfingers game, Game development, HTML5, Javascript and Phaser.

Some time ago I enjoyed “Surfingers” game by Digital Melody, available for both iOS and Android devices.

It’s an endless runner featuring a surfer, but this time you won’t control the player.

You’ll have to move the waves to let the player surf safely from one wave to another, by swiping up or down.

Have a look at the example:

Swipe up and down to move the highlighted wave up and down and let the player surf along waves of the same height.

If the player does not find to waves of the same height, it’s game over.

I used Arcade physics only to set game velocity, there isn’t any collision detection, and everything is managed by checking player and waves position.

Waves are also reused with object pooling to save resources.

The whole game consists in less than 100 lines of code, still uncommented because I have to improve a bit the game, but easily understandable:

let game;
let gameOptions = {
    platformWidth: 300,
    platformVerticalPositions: 5,
    platformVerticalGap: 50,
    platformSpeed: 150,
    playerSize: 50
}
window.onload = function() {
    let gameConfig = {
        type: Phaser.AUTO,
        backgroundColor:0x67aeeb,
        scale: {
            mode: Phaser.Scale.FIT,
            autoCenter: Phaser.Scale.CENTER_BOTH,
            parent: "thegame",
            width: 750,
            height: 500
        },
        physics: {
            default: "arcade"
        },
        scene: playGame
    }
    game = new Phaser.Game(gameConfig);
    window.focus();
}
class playGame extends Phaser.Scene{
    constructor(){
        super("PlayGame");
    }
    preload(){
        this.load.image("tile", "tile.png");
    }
    create(){
        this.platformGroup = this.physics.add.group();
        this.platformArray = [];
        this.leftmostPlatform = 0;
        this.moveablePlatform = 1;
        this.collidingPlatform = 2;
        let platformsInGame = Math.ceil(game.config.width / gameOptions.platformWidth) * 2;
        for(let i = 0; i < platformsInGame; i ++){
            let posX = gameOptions.platformWidth * i;
            let platformTopY = game.config.height / 2 - (gameOptions.platformVerticalPositions * gameOptions.platformVerticalGap) / 2;
            let posY = platformTopY + Phaser.Math.Between(0, gameOptions.platformVerticalPositions) * gameOptions.platformVerticalGap;
            let platform = this.platformGroup.create(posX, posY, "tile");
            platform.setOrigin(0, 0);
            platform.displayWidth = gameOptions.platformWidth;
            platform.displayHeight = game.config.height;
            if(i == 1){
                platform.alpha = 0.5;
                platform.y = this.platformArray[0].y
            }
            this.platformArray.push(platform);
        }
        this.platformGroup.setVelocityX(-gameOptions.platformSpeed);
        this.player = this.add.sprite(this.platformArray[this.leftmostPlatform].getBounds().right + gameOptions.playerSize, this.platformArray[this.leftmostPlatform].getBounds().top, "tile");
        this.player.setOrigin(1, 1);
        this.player.displayWidth = gameOptions.playerSize;
        this.player.displayHeight = gameOptions.playerSize;
        this.input.on("pointerup", this.endSwipe, this);
    }
    endSwipe(e) {
        let swipeTime = e.upTime - e.downTime;
        let swipe = new Phaser.Geom.Point(e.upX - e.downX, e.upY - e.downY);
        let swipeMagnitude = Phaser.Geom.Point.GetMagnitude(swipe);
        let swipeNormal = new Phaser.Geom.Point(swipe.x / swipeMagnitude, swipe.y / swipeMagnitude);
        if(swipeMagnitude > 20 && swipeTime < 1000 && (Math.abs(swipeNormal.y) > 0.8 || Math.abs(swipeNormal.x) > 0.8)) {
            if(swipeNormal.y > 0.8) {
                this.platformArray[this.moveablePlatform].y += gameOptions.platformVerticalGap;
                this.player.y += gameOptions.platformVerticalGap;
            }
            if(swipeNormal.y < -0.8) {
                this.platformArray[this.moveablePlatform].y -= gameOptions.platformVerticalGap;
                this.player.y -= gameOptions.platformVerticalGap;
            }
        }
    }
    update(){
        if(this.platformArray[this.leftmostPlatform].getBounds().right < 0){
            let rightmostPlatform = Phaser.Math.Wrap(this.leftmostPlatform - 1, 0, this.platformArray.length);
            let platformTopY = game.config.height / 2 - (gameOptions.platformVerticalPositions * gameOptions.platformVerticalGap) / 2;
            let posY = platformTopY + Phaser.Math.Between(0, gameOptions.platformVerticalPositions) * gameOptions.platformVerticalGap;
            this.platformArray[this.leftmostPlatform].y = posY;
            this.platformArray[this.leftmostPlatform].x = this.platformArray[rightmostPlatform].getBounds().right;
            this.platformArray[this.moveablePlatform].alpha = 1;
            this.leftmostPlatform = Phaser.Math.Wrap(this.leftmostPlatform + 1, 0, this.platformArray.length);
            this.moveablePlatform = Phaser.Math.Wrap(this.leftmostPlatform + 1, 0, this.platformArray.length);
            this.collidingPlatform = Phaser.Math.Wrap(this.moveablePlatform + 1, 0, this.platformArray.length);
            this.platformArray[this.moveablePlatform].alpha = 0.5;
        }
        if(this.platformArray[this.collidingPlatform].getBounds().left < this.player.getBounds().right){
            if(this.platformArray[this.collidingPlatform].y != this.platformArray[this.moveablePlatform].y){
                this.scene.start("PlayGame");
            }
        }
    }
}

Next time I am going to add an animation when the player dies, as well as some tween effect to make a smoother wave movement. Meanwhile download the source code.

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