Squirrel! Testing PlayCanvas

One of the benefits of having attended the JS Game Developers Conference was that I learned a bit about a bunch of game engines written in or designed for use with Javascript. Although I hadn’t intended Project Galaxy to use a graphical game engine, in working with the data management project I thought that maybe I might be able to benefit from being able to visualize my sector layout and connections…somehow. Considering the galaxy is basically an evenly-spaced grid I don’t know what I’m looking for but at any rate it’s a good excuse to kick the tires on PlayCanvas.

I was aware of PlayCanvas before the conference, having stumbled across it a few years ago, well before I even considered making Javascript a focus of my development efforts (as a career web developer, that’s a difficult thing to imagine, but I had a lot of ways to get around it). Now, however, with a few years of additional development, and my interest in JS thanks to Node and React, I figured that PlayCanvas might be the go-to option if I wanted a graphical design and rendering engine.

I hate to say it, but PC operates very much with the same philosophy as Unity (which is the only other game engine I have experience with) in that games are made up of scenes, and in those scenes live entities. Entities can have components hung on them to give them functionality, and some of those components can be scripts (in addition to being things like rigidbodies for physics, and containers for UI elements and such). When an entity has a script component, that script can act on that entity to provide movement, behaviors, and can be used to respond to events from other entities and the game world itself.

I don’t need that kind of functionality, but what I did want was to see how quickly I could throw out some data points and spawn some entities in the world. Using a dummy dataset, I concocted this:

var Spawner = pc.createScript('spawner');

//Attributes
Spawner.attributes.add('red', {
    type:"asset"
});

Spawner.attributes.add('blue', {
    type:"asset"
});

Spawner.attributes.add('yellow', {
    type:"asset"
});

const pos = [
    {id: 0, x: 0, y: 1, z: 0, type: 'blue'},
    {id: 1, x: 1, y: 1, z: 2, type: 'red'},
    {id: 2, x: 3, y: 1, z: 7, type: 'blue'},
    {id: 3, x: 7, y: 1, z: 10, type: 'red'},
    {id: 4, x: 12, y: 1, z: 12, type: 'yellow'},
    {id: 5, x: 8, y: 1, z: 15, type: 'yellow'},
    {id: 6, x: 20, y: 1, z: 10, type: 'yellow'}
];

// initialize code called once per entity
Spawner.prototype.initialize = function() {

    pos.forEach(itm=>{
        var ent;
        switch(itm.type){
            case "red":
                ent = this.red.resource.instantiate();
                break;
            case "blue":
                ent = this.blue.resource.instantiate();
                break;
            case "yellow":
                ent = this.yellow.resource.instantiate();
                break;
            default:
        }
        this.app.root.addChild(ent);
        ent.setPosition(itm.x, itm.y, itm.z);
        const x = 0;
    });

};

The attributes definitions at the top are properties exposed in the PlayCanvas editor for a scene controller entity. This scene controller will fire this script when the game starts and will execute the initialize function for all attached scripts in the order in which they are attached. As this is the only script on the controller, all it does is take the data in the “pos” array and create instances of templates based on the “type” property. Each type refers to one of the templates that I have assigned to the controller properties for “red”, “blue”, and “yellow”. The script then positions the instanced templates according to the X, Y, and Z values in the data object. Note that in PlayCanvas, the Z-axis is parallel to the plane you see in the screenshot below. I had to swap Y and Z, as the camera begins from a top-down perspective and all of the templates ended up aligned in a row (I did add a fly-by controller script to the camera to allow me to move around to get the screenshot).

All in all, this was extremely painless. I spent most of the time just figuring out how to adapt the instance spawning process to templates (rather than rote entities, which the documentation talks about). One issue I ran into was the issue of scale. My original [x,y,z] values were out where I thought they should be, so the values ran from 1 all the way up to 300 or so. At first, I wasn’t sure my script was correct since I didn’t see any instances rendered at play-time, but it turned out that at positional values beyond 10, things get placed way away from the [0,0,0] origin point, and were therefor outside of the range of the camera. I had to scale the [x,y,z] down to single or low double-digits in order to get things visible.

The goal, now, would be to use the admin API that I have already set for loading sectors adapted to PlayCanvas so it can load all of the sectors. The templates would be colored according to the sector’s star types, and would be arranged on a grid so I can see exactly which stars are where. Then I would need to figure out how to draw connections…maybe only when I click on a specific sector with the mouse. First, though, I need to figure out how to access my local Node server from the PlayCanvas project, which will require me to download the project after it’s been written. I might be able to expose the local Node project from my PC through a port and set up some kind of DDNS service so I could work with the PlayCanvas project “live” against the server, or I could spin up a Node server online somewhere…but then I’d need to get hosting for the SQLServer which is currently holding the data.

Nothing is easy these days, is it?

Scopique

Owner and author.

Leave a Reply

Your email address will not be published. Required fields are marked *