Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about HTML5, Javascript and Phaser.

I always try to be responsive to the feedback from my readers, so when I saw one of you was in trouble with the porting of light and dark using ray casting and visibility polygons to Phaser 3, I decided to update the script.

How could I remain unconcerned to this cry for help:

« Can’t make it work on Phaser 3. 2 weeks in it and still cant do it f*** »

This is pure poetry, LOL.

Anyway, that was an interesting experiment using ray casting merged with Byron Knoll‘s visibility polygon script, rendered with Phaser.

Have a look:

Move the mouse around the stage to see the light polygon.

As said, the source code has been ported to Phaser 3 and commented line by line:

// the game itself
let game;

// game options
let gameOptions = {

	// number of boxes in the game
	boxes: 10,

	// size of each box
	sizeRange: {

		// min size, in pixels
		min: 50,

		// max size, in pixels
		max: 120
	}
}
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
    }
    game = new Phaser.Game(gameConfig);
}
class playGame extends Phaser.Scene{
    constructor(){
        super("PlayGame");
    }
    create(){

		// graphic object used to draw walls
		this.wallGraphics = this.add.graphics();
		this.wallGraphics.lineStyle(1, 0x00ff00);

		// graphic object used to draw rays of light
		this.lightGraphics = this.add.graphics();

		// array with all polygons in game
		this.polygons = [];

		// add random boxes
		for(let i = 0; i < gameOptions.boxes; i ++){
			this.addRandomBox();
		}

		// walls around game perimeter
		this.polygons.push([[-1, -1], [game.config.width + 1, -1], [game.config.width + 1, game.config.height+1], [-1, game.config.height + 1]]);

		// listener for input movement
		this.input.on("pointermove", this.renderLight, this);
	}

	// method to add a random box
	addRandomBox(){

		// use a do...while statement because there can't be intersecting polygons
		do{

			// random x and y coordinates, width and height
			var startX = Phaser.Math.Between(10, game.config.width - 10 - gameOptions.sizeRange.max);
			var startY = Phaser.Math.Between(10, game.config.height - 10 - gameOptions.sizeRange.max);
			var width = Phaser.Math.Between(gameOptions.sizeRange.min, gameOptions.sizeRange.max);
			var height = Phaser.Math.Between(gameOptions.sizeRange.min, gameOptions.sizeRange.max);

			// check if current box intersects other boxes
		} while(this.boxesIntersect(startX, startY, width, height));

		// draw the box
		this.wallGraphics.strokeRect(startX, startY, width, height);

		// insert box vertices into polygons array
		this.polygons.push([[startX, startY], [startX + width, startY], [startX + width, startY + height], [startX, startY + height]]);
	}

	// method to check if the box intersects other boxes
	boxesIntersect(x, y, w, h){

		// loop through existing boxes
		for(let i = 0; i < this.polygons.length; i ++){

			// if the box intersects the existing i-th box...
			if(x < this.polygons[i][1][0] && x + w > this.polygons[i][0][0] && y < this.polygons[i][3][1] && y + h > this.polygons[i][0][1]){

				// return true
				return true;
			}
		}

		// if we reach the end of the loop, return false
		return false;
	}

	// method to render the light
	renderLight(pointer){

		// determine light polygon starting from pointer coordinates
		let visibility = this.createLightPolygon(pointer.x, pointer.y);

		// clear and prepare lightGraphics graphic object
		this.lightGraphics.clear();
		this.lightGraphics.lineStyle(2, 0xff8800);
		this.lightGraphics.fillStyle(0xffff00);

		// begin a drawing path
		this.lightGraphics.beginPath();

		// move the graphic pen to first vertex of light polygon
		this.lightGraphics.moveTo(visibility[0][0], visibility[0][1]);

		// loop through all light polygon vertices
     	for(let i = 1; i <= visibility.length; i ++){

			// draw a line to i-th light polygon vertex
			this.lightGraphics.lineTo(visibility[i % visibility.length][0], visibility[ i %visibility.length][1]);
		}

		// close, stroke and fill light polygon
		this.lightGraphics.closePath();
    	this.lightGraphics.fillPath();
    	this.lightGraphics.strokePath();
	}

	// method to create light polygon using visibility_polygon.js
	createLightPolygon(x, y){
		let segments = VisibilityPolygon.convertToSegments(this.polygons);
		segments = VisibilityPolygon.breakIntersections(segments);
		let position = [x, y];
		if (VisibilityPolygon.inPolygon(position, this.polygons[this.polygons.length - 1])) {
			return VisibilityPolygon.compute(position, segments);
		}
		return null;
	}
}

It could be interesting to turn it into some kind of survival horror, I am gonna give this script a twist later this week, 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.