-
Notifications
You must be signed in to change notification settings - Fork 2
Realtime Multiplayer Game
netzzwerg edited this page Mar 2, 2013
·
29 revisions
node --version
0.8.21
npm --version
1.2.11
[sudo] npm install socket.io
[sudo] npm install express
[sudo] npm install node-uuid
cd node_modules
ls
node server.js
var serverPort = process.env.PORT || 1337,
express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app);
/* ------ ------ ------ Express ------ ------ ------ */
server.listen(serverPort);
console.log('\t :: Express :: Listening on port ' + serverPort );
app.get('/', function(req, res){
res.send('Hello World');
});
File Respond
app.get( '/', function( req, res ){
res.sendfile( __dirname + '/index.html' );
});
app.get( '/*' , function( req, res, next ) {
var file = req.params[0];
if(verbose) console.log('\t :: Express :: file requested : ' + file);
res.sendfile( __dirname + '/' + file );
});
<script src="/socket.io/socket.io.js"></script>
var sio = require('socket.io').listen(server);
sio.configure(function (){
sio.set('log level', 0);
sio.set('authorization', function (handshakeData, callback) {
callback(null, true); // error first callback style
});
});
Send Message
sio.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
var socket = io.connect('http://localhost:1337');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
Broadcast message
- Send to the current socket:
socket.emit('message', data);
- Send to all sockets
sio.sockets.emit('message', data);
- Send to all sockets except the current one:
socket.broadcast.emit('message', data);
client.js
socket.on('connected', function (data) {
localUID = data.uid;
for (var prop in data.clients) {
if( data.clients.hasOwnProperty(prop) ) {
var client = data.clients[prop];
var actor = new Actor(client.data.uid);
actor.targetX = client.data.x;
actor.targetY = client.data.y;
actors.push(actor);
}
}
});
socket.on('clientConnect', function (data) {
var actor = new Actor(data.uid);
if(data.uid === localUID){
actor.c = '#FF00FF';
}
actors.push(actor);
});
socket.on('clientDisconnect', function (data) {
for (var i = 0; i < actors.length; i++) {
if(actors[i].uid === data.uid) {
actors.splice(i, 1);
}
}
});
socket.on('clientMessage', function (data) {
for (var i = 0; i < actors.length; i++) {
if(actors[i].uid === data.uid) {
actors[i].setTarget(data.x, data.y);
}
}
});
socket.on('connect', function () {
console.log('server connected');
});
socket.on('disconnect', function (data) {
actors = [];
});
server.js
sio.sockets.on('connection', function (socket) {
newClient(socket);
socket.on('clientMessage', onClientMessage);
socket.on('disconnect', onDisconnect);
});
function onClientMessage (data) {
clients[data.uid].data = data;
sio.sockets.emit('clientMessage', data);
console.log(' client\t - '.blue, data);
}
function onDisconnect () {
var uid = this.id;
sio.sockets.emit('clientDisconnect', {uid:uid});
delete clients[uid];
console.log(' client\t - '.red + uid + ' disconnected');
}
function newClient(socket) {
var clientUID = socket.id;
clients[clientUID] = {'data' : {
'x' : 0,
'y' : 0,
'uid': clientUID
}};
// tell current connection that it is connected
socket.emit('connected', {
'uid' : clientUID,
'clients' : clients
});
// tell other sockets that there is a new client
sio.sockets.emit('clientConnect', {
'uid' : clientUID
});
console.log(' client\t - '.green + clientUID + ' connected');
}
Problems with the simple approach:
- Frame rate dependence
- Server is dumb (cheat protection, ...)
- At client movement the server only knows the end position
- Update position (using client prediction)
- Move the other clients based on the server position (interpolation)
Client Rendering | max. 60FPS (17ms) | Server Update | 22FPS (45ms) |
---|---|---|---|
Client Physics | 66FPS (15ms) | Server Physics | 66FPS (15ms) |