2013-07-29 15:12:54 -04:00
2013-07-27 16:31:42 -04:00
2013-07-26 15:37:18 -04:00
2013-07-26 09:54:50 -04:00
2013-05-05 23:50:15 -04:00
2013-06-08 16:43:37 -04:00
2013-05-05 23:00:43 -04:00
2013-07-29 15:12:54 -04:00

GarageServer.IO

A simple, lightweight, HTML multiplayer game server (and client) for Node.js

Features

  • Authoritative Game Server
  • Client Side / Input Prediciton
  • Client Side Smooting
  • Entity Interpolation
  • Server State History
  • Server and Client Messaging

Quick Start

Create a quick game whereby players simply move squares along the x-axis. I know, it's boring, but it keeps things simple and to the point. For a more thorough demonstration of how GarageServer.IO works, look at the example included in the source code.

Server

1. Create instance of GarageServer.IO - pass in a Socket.IO instance and GarageServer.IO options.

var garageServer = require('garageserver.io'),

var server = garageServer.createGarageServer(sockets, 
    {
        interpolation: true,
        clientSidePrediction: true,
        worldState: { width: '400px', height: '400px'; }
    });

2. Start GarageServer.IO instance prior to starting physics loop. This starts the clock that is used for broadcasting state and storing state history.

server.start();

3. Inside physics loop, process inputs for players, process entites and update states. Note that state is an object literal effectively offering up any grab bag of properties that pertain to your game's state.

var players = server.getPlayers(),
    entities = server.getEntities();

players.forEach(function (player) {
    var newState = {};
    if (!player.state.x) {
       player.state.x = 0;
    }
    for (i = 0; i < player.inputs.length; i ++) {
        if (player.inputs[i].input === 'left') {
            newState.x = player.state.x - (50 * deltaTime);
        } else if (inputs[i].input === 'right') {
            newState.x = player.state.x + (50 * deltaTime);
        }
    }
    server.updatePlayerState(player.id, newState);
});
entities.forEach(function (entity) {
    // Calculate new state from entity.state and send GarageServer.IO new state
    server.updateEntityState(entity.id, newState);
});

Client

1. Initialize GarageServer.IO.

GarageServerIO.initializeGarageServer('http://insertmygameurlhere.com', {
    onReady: function () {
        // Call your game loop
    },
    onUpdatePlayerPrediction: function (state, inputs, deltaTime) {
        var newState = {};
        if (!player.state.x) {
        player.state.x = 0;
        }
        for (i = 0; i < player.inputs.length; i ++) {
            if (player.inputs[i].input === 'left') {
                newState.x = player.state.x - (50 * deltaTime);
            } else if (inputs[i].input === 'right') {
                newState.x = player.state.x + (50 * deltaTime);
            }
        }
        return newState;
    },
    onInterpolation: function (previousState, targetState, amount) {
        return { x: (previousState.x + amount * (targetState.x - previousState.x)) };
    },
    onWorldState: function (state) {
        document.getElementById('gameCanvas').style.width = state.width;
        document.getElementById('gameCanvas').style.height = state.height;
    }
};

2. Inside physics loop, capture and send input via GarageServer.IO.

GarageServerIO.addInput(myInput);

3. Inside render loop, extract player and entity states.

var playerStates = GarageServerIO.getPlayerStates(),
    entityStates = GarageServerIO.getEntityStates();  
    playerStates.forEach(function (player) {
        ctxCanvas.fillRect(player.state.x, 0, 5, 5);
    });
    entityStates.forEach(function (entity) {
        ctxCanvas.fillRect(entity.state.x, 0, 5, 5);
    });

API

Client

initializeGarageServer


GarageServerIO.initializeGarageServer(path, options)

Establish connection to GarageServer.IO on the server via Socket.IO and register events.
path string
The URL that points to where GarageServer.IO is running at on the server.
options object literal
Configure the different options, events, callbacks that you would like to consume on the client.

options.onPlayerConnect(callback)  

Once the client has made a connection to the server, this event will fire.
callback function Function to be invoked upon event firing.

options.onPlayerDisconnect(callback)  

If client has has disconnected from the server, this event will fire.
callback function Function to be invoked upon event firing.

options.onPlayerReconnect(callback)  

If client has has disconnects and reconnects to the server, this event will fire.
callback function Function to be invoked upon event firing.

options.onPlayerUpdate(callback(state))  

callback
Type: function Function to be invoked upon event firing.
state
Type: object literal

options.onEntityUpdate(callback(state))  

callback
Type: function Function to be invoked upon event firing.

state
Type: object literal

options.onPlayerRemove(callback(id))  

callback
Type: function

id
Type: string

options.onEntityRemove(callback(id))  

callback
Type: function

id
Type: string

options.onEvent(callback(data))  

callback
Type: function

data
Type: object literal

options.onWorldState(callback(state))  

callback
Type: function

state
Type: object literal

options.onPing(callback(pingDelay))  

callback
Type: function

pingDelay
Type: number

options.onUpdatePlayerPrediction(callback(state, inputs, deltaTime) : newState)  

Returns: object literal

callback
Type: function

state
Type: object literal

inputs
Type: array

deltaTime
Type: number

options.onInterpolation(callback(previousState, targetState, amount) : newState)  

Returns: object literal

callback
Type: function

previousState
Type: object literal

targetState
Type: object literal

amount
Type: number

options.onReady(callback)  

callback
Type: function

options.logging: true  

logging
Type: boolean

addInput


GarageServerIO.addInput(input)

input
Type: object literal

getPlayerStates


GarageServerIO.getPlayerStates() : [, {id, state}]

Returns: array

id
Type: string

state
Type: object literal

getEntityStates


GarageServerIO.getEntityStates() : [, {id, state}]

Returns: array

id
Type: string

state
Type: object literal

getId


GarageServerIO.getId() : playerid

Returns: string

playerid
Type: string

sendServerEvent


GarageServerIO.sendServerEvent(data)

data
Type: object literal

Server

createGarageServer


require('garageserver.io').createGarageServer(io, options) : GarageServerIO

io
Type: Socket.IO instance

options
Type: object literal

options.stateInterval

Type: number

options.logging

Type: boolean

options.clientSidePrediction

Type: boolean

options.interpolation

Type: boolean

options.interpolationDelay

Type: number

options.smoothingFactor

Type: number

options.pingInterval

Type: number

options.maxUpdateBuffer

Type: number

options.maxHistorySecondBuffer

Type: number

options.worldState

Type: object literal

options.onPlayerConnect(callback(socket))

callback
Type: function

socket
Type: Socket

options.onPlayerInput(callback(socket, input))

callback
Type: function

socket
Type: Socket

input
Type: object literal

options.onPlayerDisconnect(callback(socket))

callback
Type: function

socket
Type: Socket

options.onPing(callback(socket, data))

callback
Type: function

socket
Type: Socket

data
Type: object literal

options.onEvent(callback(data))

callback
Type: function

data
Type: object literal

start


GarageServerIO.start()

stop


GarageServerIO.stop()

getPlayers


GarageServerIO.getPlayers() : [, {id, state, [, inputs], [, {states, executionTimes}]}]

Returns: array

id
Type: string

state
Type: object literal

inputs
Type: array of object literals

stateHistory
Type: array of object literals

getEntities


GarageServerIO.getEntities() : [,{id, state, [, {state, executionTime }]}]

Returns: array

id
Type: string

state
Type: object literal

stateHistory
Type: array of object literals

updatePlayerState


GarageServerIO.updatePlayerState(id, state)

id
Type: string

state
Type: object literal

updateEntityState


GarageServerIO.updateEntityState(id, state)

id
Type: string

state
Type: object literal

addEntity


GarageServerIO.addEntity(id)

id
Type: string

removeEntity


GarageServerIO.removeEntity(id)

id
Type: string

sendPlayerEvent


GarageServerIO.sendPlayerEvent(id, data)

id
Type: string

data
Type: object literal

sendPlayersEvent


GarageServerIO.sendPlayersEvent(data)

data
Type: object literal

License

MIT License

S
Description
A simple, lightweight, HTML multiplayer game server (and client) for Node.js
Readme 593 KiB
Languages
JavaScript 97.7%
Pug 1.5%
CSS 0.8%