First, let us introduce ourselves. Our team built Gamorlive, an HTML5 game portal dedicated to hosting games that provide a real multiplayer experience across Facebook, PC, Windows Phone, iOS and Android devices. This post outlines some of the technological challenges we faced creating solid code that could support realtime in-game interactions between players, all in a game developer-friendly way.
Many online games have been developed using definitions for new HTML5 elements aimed at interactivity, multimedia and graphics. These features, coupled with the enhanced and faster JavaScript engines available in modern browsers, enable the creation of high quality games that can be ported to almost any device with a web browser.
But what is the social effect of web gaming if games cannot be played in multiplayer mode? In recent years, there has been a need to provide networking capabilities to HTML5 games. Different transport mechanisms were available for fast exchange of data between the client and the server, including WebSockets, XHR-polling, and flash sockets. In 2009, Node.js emerged and bridged the client and server implementation.
Node.js is a platform built on Google's V8 JavaScript engine for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
The Node.js community has created a package manager and many interesting modules to help you build your games, including Socket.IO. Socket.IO is a Node module that allows the setup of a full-duplex communication channel between the client and the server, through which data can be exchanged at high speed while keeping the connection open. Here is how you can create a basic client/server communication channel:
Server side:
var express = require('express');
var app = express.createServer();
app.listen(81);
var io = require('socket.io').listen(app);
io.sockets.on('connection', function(socket){
socket.emit('message', {msg: "Hello world!"});
//On connection of client, send "Hello world" back to client
socket.on('message', function(data){
//Listens to message sent by client
socket.broadcast.emit('message', {msg: data});
//Broadcast to all clients except sender of message
});
});
Client side:
<script src='http://beta.gamorlive.com:81/socket.io/socket.io.js' />
<script>
var socket = io.connect('http://beta.gamorlive.com:81');
//connects to the server
socket.on('message', function(data){
//Listens to messages sent by the server
console.log(data);
});
socket.emit('message', 'My first message');//emits message
</script>
The same principles are applied when building a multiplayer game, where data is exchanged between the clients via the server.
The Gamorlive API offers a framework for game developers to integrate their HTML5 game to the Gamorlive platform. It contains basic functions that enable the connection to the server and the exchange of data between clients, through the server.
The asynchronous version of the API best suits multiplayer games that do not share the same game instance. The game is instantiated on every client and data is exchanged through messages among the clients, as illustrated in the above example.
The real-time version provides a framework that lets developers give players a shared game experience. The API adapts the framework developed by Mario Gonzalez, from onedayitwillmake, to fit the context of Gamorlive. The main problem when using the v1 approach for building real-time multiplayer games is the inability to represent a true motion path from the last network information received (a.k.a. the bouncing ball problem); another major issue is collision detection on a shared object.
To remedy to these issues, we have adopted another approach, whereby there is a single instance of the game that is run on the server. Node.js being JavaScript-based enables code sharing between client and server.
The true game state, held on the server, will be broadcast to the clients at a regular interval (usually 60FPS). The clients act only as renderers of the game state upon which players apply inputs (keyboard, mouse, touch). These inputs are sent back to the server to update the game state.
At this point, synchronization problems due to network latency still persist and have to be addressed. This is where the magic happens: on the client side, the game state is rendered at time T – LAG_CONSTANT, and we apply interpolation between the previous and next game state to smooth out object movement.
In the above example, new updates are broadcast every 50 milliseconds. The interpolation period is set to 150 milliseconds so that even if there are packet loss, there are always 2 valid snapshots that can be used for interpolation.
Lets assume as per the snapshots buffered, a moving 2D object is at position (10,5) at time 10.30 and at position (20,10) at time 10.35. The client is rendering at 60FPS and 620 frame ticking at 10.32 falls just between the snapshot 341 and 342. From a linear equation derived from points (10,5) and (20,10), the position of the object at time 10.32 can be calculated as follows:
The linear equation is y= 1/2 x and for each 10 milliseconds, ∆x=2,∆y=1. Therefore, relative to snapshot 341, ∆t=20ms which results in ∆x=4,∆y=2 and the position for time 10.32 to be (14, 7).
The API is a scalable OO framework with segregated modules that enable easy integration of game objects, and also includes cool multimedia libraries, for example CAAT and Soundmanager.
Multiplayer HTML5 game engines, like Isogenic Engine and PlayCraftLabs, are being developed and enhanced to provide developers with the best tools for the new generation of HTML5 games. The future is bright.
• Gamorlive API (beta)
• NodeJs for beginners by Shadowtek Hosting & Design Solutions
• The Secrets of Node’s Success by Troy Topnik
• Creating Realtime Multiplayer Games using NodeJs by onedayitwillmake