Progress: Interpolation

This commit is contained in:
Jeremiah Billmann
2013-06-26 20:17:55 -04:00
parent 3d8fe0790f
commit 536238e902
4 changed files with 119 additions and 21 deletions
+81 -18
View File
@@ -1,14 +1,16 @@
/*
options = {
onConnect: function()
onPlayerConnect: function()
onPlayerDisconnect: function (),
onPlayerReconnect: function (),
onPlayerUpdate: function (data),
onPlayerDisconnect: function (id),
onPlayerRemove: function (id),
onPing: function (data),
onUpdatePlayerPhysics: function (state, inputs),
onInterpolation: function(previousState, targetState, amount)
logging: true,
clientSidePrediction: true,
onUpdatePlayerPhysics: function (state, inputs),
interpolation: true,
onInterpolation: function(statePrevious, stateTarget, amount)
pingInterval: 2000
}
*/
@@ -21,23 +23,37 @@ window.GarageServerIO = (function (window, socketio) {
players = [],
inputs = [],
currentState = {},
currentTime,
currentDelta,
currentPlayerId,
options = null,
pingDelay = 100,
// TODO: DONE CALLBACK
connectToGarageServer = function (path, opts) {
socket = io.connect(path + '/garageserver.io');
options = opts;
socket = io.connect(path + '/garageserver.io');
registerSocketEvents();
registerPinger();
},
registerSocketEvents = function () {
socket.on('connect', function () {
if (options.onPlayerConnect) {
options.onPlayerConnect();
}
});
socket.on('disconnect', function () {
if (options.onPlayerDisconnect) {
options.onPlayerDisconnect();
}
});
socket.on('reconnect', function () {
if (options.onPlayerReconnect) {
options.onPlayerReconnect();
}
});
socket.on('update', function(data) {
updateState(data);
if (options.logging) {
//console.log('garageserver.io:: socket state update');
}
});
socket.on('ping', function(data) {
pingDelay = new Date().getTime() - data;
@@ -52,7 +68,7 @@ window.GarageServerIO = (function (window, socketio) {
}
});
},
registerPinger = function () {
var interval = 2000;
if (options.pingInterval) {
@@ -62,8 +78,11 @@ window.GarageServerIO = (function (window, socketio) {
socket.emit('ping', new Date().getTime());
}, interval);
},
updateState = function (data) {
currentTime = data.time - pingDelay / 2;
currentDelta = data.delta;
updatePlayerState(data);
updateEntityState(data);
},
@@ -83,6 +102,7 @@ window.GarageServerIO = (function (window, socketio) {
if (socket.socket.sessionid === playerState.id) {
currentState = playerState.state;
currentPlayerId = playerState.id;
if (options.clientSidePrediction) {
for (updateIdx = 0; updateIdx < inputs.length; updateIdx ++) {
@@ -111,6 +131,9 @@ window.GarageServerIO = (function (window, socketio) {
}
break;
}
if (players[playerIdx].updates.length > 60) {
players[playerIdx].updates.splice(0, players[playerIdx].updates.length - 60);
}
}
if (!playerFound) {
@@ -141,8 +164,8 @@ window.GarageServerIO = (function (window, socketio) {
}
}
if (options.onPlayerDisconnect) {
options.onPlayerDisconnect(id);
if (options.onPlayerRemove) {
options.onPlayerRemove(id);
}
},
@@ -162,28 +185,68 @@ window.GarageServerIO = (function (window, socketio) {
sendPlayerInput = function (clientInput) {
socket.emit('input', { input: clientInput, seq: sequenceNumber });
},
getPositions = function (playerUpdates) {
var positions = {},
range,
difference,
amount;
for (var updateIdx = 0; updateIdx < playerUpdates.length; updateIdx ++) {
var previous = playerUpdates[updateIdx];
var target = playerUpdates[updateIdx + 1];
if(currentTime > previous.time && currentTime < target.time) {
range = target.time - previous.time;
difference = currentTime - previous.time;
amount = Math.toFixed( difference / range, 3);
positions.previousState = previous.state;
positions.targetState = target.state;
positions.amount = amount;
break;
}
}
return positions;
},
getPlayerStates = function (stateCallback) {
var maxUpdate = 0;
for (var playerIdx = 0; playerIdx < players.length; playerIdx ++) {
if (players[playerIdx].updates.length > 0) {
if (options.interpolation) {
maxUpdate = players[playerIdx].updates.length - 1;
if (options.interpolation && options.onInterpolation) {
var positions = getPositions(players[playerIdx].updates);
if (positions.previousState && positions.targetState) {
stateCallback(options.onInterpolation(positions.previousState, positions.targetState, positions.amount));
}
else {
stateCallback(players[playerIdx].updates[maxUpdate].state);
}
} else {
maxUpdate = players[playerIdx].updates.length - 1;
stateCallback(players[playerIdx].updates[maxUpdate].state);
}
}
}
stateCallback(currentState);
},
getPlayerId = function () {
return currentPlayerId;
},
setPlayerState = function (state) {
socket.emit('state', state);
};
return {
connectToGarageServer: connectToGarageServer,
addPlayerInput: addPlayerInput,
getPlayerStates: getPlayerStates
getPlayerStates: getPlayerStates,
getPlayerId: getPlayerId,
setPlayerState: setPlayerState
};
}) (window, io);
+8
View File
@@ -21,6 +21,14 @@ $(function () {
}
}
return state;
},
onInterpolation: function (previousState, targetState, amount) {
var newState = {};
newState.x = (previousState.x + amount * (targetState.x - previousState.x));
newState.y = (previousState.y + amount * (targetState.y - previousState.y));
return newState;
}
});
+15
View File
@@ -9,6 +9,7 @@ options = {
onPlayerInput: function (socket, input),
onPlayerDisconnect: function (socket),
onPing: function (socket, data),
onState: function (socket, data),
onUpdatePlayerPhysics: function (state, inputs),
}
*/
@@ -48,6 +49,13 @@ GarageServer.prototype.registerSocketEvents = function (options) {
}
self.onPing(socket, data, options);
});
socket.on('state', function (data) {
if (options.logging) {
console.log('garageserver.io:: socket state ' + data);
}
self.onPing(socket, data, options);
});
});
};
@@ -80,6 +88,13 @@ GarageServer.prototype.onPing = function (socket, data, options) {
}
};
GarageServer.prototype.onState = function (socket, data, options) {
this.game.setPlayerState(socket, data);
if (options.onState) {
options.onState(socket, data);
}
};
exports.createGarageServer = function (io, options) {
return new GarageServer(io, options);
};
+15 -3
View File
@@ -5,9 +5,11 @@ function GarageServerGame(options) {
this.entities = [];
this.options = options;
this.startTime = new Date().getTime();
this.physicsInterval = options.physicsInterval ? options.physicsInterval : 15;
this.stateInterval = options.stateInterval ? options.stateInterval : 45;
this.physicsIntervalId = setInterval(function () { self.updatePhysics(options); }, options.physicsInterval ? options.physicsInterval : 15);
this.stateIntervalId = setInterval(function () { self.updateState(options); }, options.stateInterval ? options.stateInterval : 45);
this.physicsIntervalId = setInterval(function () { self.updatePhysics(options); }, this.physicsInterval);
this.stateIntervalId = setInterval(function () { self.updateState(options); }, this.stateInterval);
}
GarageServerGame.prototype.updateState = function (options) {
@@ -17,7 +19,7 @@ GarageServerGame.prototype.updateState = function (options) {
GarageServerGame.prototype.updatePlayers = function (options) {
var currentTime = new Date().getTime() - this.startTime,
state = { time: currentTime, playerStates: [] },
state = { time: currentTime, delta: this.physicsInterval, playerStates: [] },
i = 0;
for (i = 0; i < this.players.length; i ++) {
@@ -72,6 +74,16 @@ GarageServerGame.prototype.removePlayer = function (client) {
}
};
GarageServerGame.prototype.setPlayerState = function (client, state) {
for (var i = 0; i < this.players.length; i ++) {
if (this.players[i].client.id === client.id) {
this.players[i].state = state;
this.players[i].sequence += 1;
this.players[i].inputs = [];
}
}
};
GarageServerGame.prototype.addPlayerInput = function (client, input) {
for (var i = 0; i < this.players.length; i ++) {
if (this.players[i].client.id === client.id) {