Category Archives: html5

Using Rot.js with PlayCanvas

Ananas aus Caracas in PlayCanvas!
———————————————————————————

After milling around the RoguelikeDev subreddit this weekend I stumbled upon Rot.js, a JavaScript Roguelike Toolkit made by Ondrej Zara.

Rot.js has a nice tutorial which helps you learn the toolkit buy making a roguelike game covering map generation, AStar pathfinding, the game engine, and other such good stuff. By the end of the tutorial I had made something that was functionally a game and looked like this:

rl

This is all well and good for those hardcore roguelike players who love the ascii graphics, but those are not for me, so I ported the tutorial outcome to my favourite HTML5 game engine; PlayCanvas. After a little changing of the code, it looked like this (click inside the game to play):

Movement – Arrow Keys
Open Box – Space or Enter

 

The changes required to port it to PlayCanvas mostly revolved around the draw and displaying of the map and entities. The Rot.js tools handle the drawing of the entities themselves using the ROT.Display, which draws the ascii characters directly onto the canvas.

This is not much use in PlayCanvas as the Player and Pedro are 3D entities who need to be moved in the PlayCanvas way, so the draw functions turn from the Rot.js tutorial draw:

    Game.display.draw(this._x, this._y, "@", "#ff0");

to the PlayCanvas entity move:

    this.entity.setPosition(this.x, 0.5, this.y);

 

The draw function for the Game object had to change a bit more drastically. In the tutorial, the way to draw the map is to iterate over every floor tile and box and then call display.draw with the relevant ascii character:

    _drawWholeMap: function() {
        for (var key in this.map) {
            var parts = key.split(",");
            var x = parseInt(parts[0]);
            var y = parseInt(parts[1]);
            this.display.draw(x, y, this.map[key]);
        }
    }

In PlayCanvas this became a bit more complex. The map must still be iterated over, but now instead of calling a simple draw function with an ascii character you need to clone a new entity for every floor tile and box and set their positions:

    _drawWholeMap: function(){
        //Draw map
        var floorTemplate = app.root.findByName('Template_Floor');
        for(var key in this.map){
            var floor = floorTemplate.clone();
            var parts = key.split(",");
            var x = parseInt(parts[0], 10);
            var y = parseInt(parts[1], 10);
                
            floor.setPosition(x, 0, y);
            app.root.addChild(floor);
        }
            
        //Draw boxes
        var boxTemplate = app.root.findByName('Template_Box');
        for(var i = 0; i < this.boxPositions.length; i++){
            var box = boxTemplate.clone();
            box.setPosition(this.boxPositions[i][0], 0, this.boxPositions[i][1]);
            app.root.addChild(box);
        }
    }

 

In the tutorial all of the output text is displayed via alerts:

    alert("There is no box here!");

Though this would still have worked in PlayCanvas, I thought a better solution would have been to display the text on-screen. For this I used another JavaScript library called Raphael.js. With this I could easily write the text directly onto the game screen instead of using alerts:

    this.outputPaper = Raphael(10, 10, 800, 50);
    this.outputPaper.text(5, 10, string).attr({
        font: 25 + "px Indie Flower, Helvetica, cursive, sans-serif",
        fill: "#fff",
        "text-anchor": "Start"
    });

 

There were a few other small changes I made to get this working in PlayCanvas. The full project and code can be seen here. Note that at the end of the tutorial it mentions some issues with the game, such as it not ending when it should and the pathfinding breaking if the Player stands on the same tile as Pedro. These issues are still in the PlayCanvas version as I just directly ported the tutorial without attempting to fix any of these issues.