nengi Game pt 2: asteroids

Previous: nengi Game pt 1: space game, graphics

Please checkout: git pull and git checkout game-2.

Start with npm start

We'll be adding asteroids to the game. This is where we're really going to learn where to put code to make a new feature. You can think of the asteroid as a very simple type of creature with a very simple ai. For this particular section of the the tutorial all we're going to do is setup the boilerplate for our new type of entity.

In the common folder create Asteroid.js:

import nengi from 'nengi'

class Asteroid {
    constructor() {
        this.x = 150
        this.y = 150
        this.rotation = 0
    }
}

Asteroid.protocol = {
    x: { type: nengi.Number, interp: true },
    y: { type: nengi.Number, interp: true },
    rotation: { type: nengi.RotationFloat32, interp: true }
}

export default Asteroid

Add our new entity type to nengiConfig.js:

import Asteroid from './Asteroid.js'
    entities: [
        ['PlayerCharacter', PlayerCharacter],
        ['Asteroid', Asteroid]
    ],

Create AsteroidGraphics.js in the client/graphics/ folder:

import { Container, Sprite } from 'pixi.js'

class AsteroidGraphics extends Container {
    constructor() {
        super()

        const sprite = Sprite.from('/images/asteroid-small.png')
        sprite.scale.set(3, 3)
        sprite.anchor.set(0.5, 0.5)
        sprite.rotation = 0.5 * Math.PI
        this.addChild(sprite)
    }
}

export default AsteroidGraphics

Create asteroidHooks.js in the client/hooks/ folder:

import AsteroidGraphics from '../graphics/AsteroidGraphics.js'
import renderer from '../graphics/renderer.js'

export default (state) => {
    return {
        create({ data, entity }) {
            const graphics = new AsteroidGraphics()
            renderer.middleground.addChild(graphics)
            return graphics
        },
        delete({ nid, graphics }) {
            renderer.middleground.removeChild(graphics)
        },
        watch: {
        }
    }
}

Add our new hooks to createHooks.js:

import playerHooks from './playerHooks.js'
import asteroidHooks from './asteroidHooks.js'

export default (state) => {
    return {
        'PlayerCharacter': playerHooks(state),
        'Asteroid': asteroidHooks(state)
    }
}

That's the boilerplate done with. And now to prove it works, spawn one asteroid into the game by creating one in gameServer.js

import Asteroid from '../common/Asteroid.js'
const instance = new nengi.Instance(nengiConfig, { port: 8079 })
instanceHookAPI(instance)

/* serverside state here */
const entities = new Map()

const asteroid = new Asteroid()
instance.addEntity(asteroid)

There should now be an asteroid in the game.

This process can be repeated to stub out as many types of entities as any game would need. Some of it may seem quite repetitive when all we have is a simple stationary asteroid entity (it is). But as we begin to make something more out of this asteroid feature, we'll start to see how this design is poised to allow us to add elaborate functionality while keeping our concerns separated.

Next: nengi Game pt 3: asteroid motion, feature architecture