Updated GarageServer.IO API calls to support client side prediction for entities - #20

This commit is contained in:
Jeremiah Billmann
2015-05-20 02:10:07 +00:00
parent 21d8fb2884
commit fbdcfe3da5
12 changed files with 48 additions and 25 deletions
+24 -9
View File
@@ -10,7 +10,7 @@ options = {
onEvent(callback(data)),
onWorldState(callback(state)),
onPing(callback(pingDelay)),
onUpdateClientPredictionReady(callback(playerId, playerCurrentState, inputs, deltaTime)),
onUpdateClientPredictionReady(callback(playerId, playerCurrentState, entityCurrentStates, inputs, deltaTime)),
onInterpolation(callback(previousState, targetState, amount) : newState),
onReady(callback),
logging: true
@@ -88,10 +88,12 @@ var GarageServerIO = (function (socketio) {
this.time = time;
}
function Entity(id, maxUpdateBuffer) {
function Entity(id, referrerId, referrerSeq, maxUpdateBuffer) {
this.updates = [];
this.maxUpdateBuffer = maxUpdateBuffer;
this.id = id;
this.referrerId = referrerId;
this.referrerSeq = referrerSeq;
this.state = {};
this.inputController = new InputController();
}
@@ -142,7 +144,7 @@ var GarageServerIO = (function (socketio) {
};
function Player(id, maxUpdateBuffer) {
Entity.call(this, id, maxUpdateBuffer);
Entity.call(this, id, null, null, maxUpdateBuffer);
}
Player.prototype = Object.create(Entity.prototype);
@@ -151,8 +153,9 @@ var GarageServerIO = (function (socketio) {
this.maxUpdateBuffer = maxUpdateBuffer;
}
EntityController.prototype = {
add: function (id) {
var entity = new Entity(id, this.maxUpdateBuffer);
add: function (id, referrerId) {
var referrerSeq = this.entities.filter(function (value) { return value.referrerId === referrerId; }).length;
var entity = new Entity(id, referrerId, referrerSeq, this.maxUpdateBuffer);
this.entities.push(entity);
return entity;
},
@@ -303,9 +306,16 @@ var GarageServerIO = (function (socketio) {
addInput = function (clientInput) {
_playerController.entities.some(function (player) {
if (player.id === _stateController.id) {
if (_stateController.clientSidePrediction && _options.onUpdatePlayerPrediction) {
if (_stateController.clientSidePrediction && _options.onUpdateClientPredictionReady) {
var entityCurrentStates = [];
_entityController.entities.forEach(function(entity) {
if (entity.referrerId === player.id) {
entityCurrentStates.push({ id: entity.id, state: entity.state });
}
});
player.inputController.add(clientInput);
_options.onUpdateClientPredictionReady(player.state, [{ input: clientInput }], _stateController.physicsDelta);
_options.onUpdateClientPredictionReady(player.id, player.state, entityCurrentStates, [{ input: clientInput }], _stateController.physicsDelta);
}
_socket.emit('i', [ clientInput, player.inputController.sequenceNumber, _stateController.renderTime ]);
}
@@ -358,11 +368,16 @@ var GarageServerIO = (function (socketio) {
},
addEntity = function (id, state) {
_entityController.add(id, _stateController.id).state = state;
},
updateEntityState = function (id, state) {
_entityController.entities.some(function(entity) {
if (entity.id === id) {
entity.state = state;
return true;
}
});
},
removeEntity = function (id) {
+4 -1
View File
@@ -113,7 +113,7 @@ The current ping in milliseconds.
---
```js
options.onUpdateClientPredictionReady(callback(playerId, playerCurrentState, inputs, deltaTime))
options.onUpdateClientPredictionReady(callback(playerId, playerCurrentState, entityCurrentStates: [, {id, state}], inputs, deltaTime))
```
If using client side prediction, this callback will fire when you should update player and entity states, based on the current states for player and entities, inputs to be processed, and the delta time.
@@ -126,6 +126,9 @@ The id of the player.
`playerCurrentState` **object literal**
The current state of the player.
`entityCurrentStates` **array**
The list of all entities and their current state that were invoked by the player.
`inputs` **array**
List of all the inputs to be processed.
+1 -1
View File
@@ -52,7 +52,7 @@ GarageServerIO.initializeGarageServer('http://insertmygameserverurlhere.com', {
onReady: function () {
// Call your game loop
},
onUpdateClientPredictionReady: function (playerId, playerCurrentState, inputs, deltaTime) {
onUpdateClientPredictionReady: function (playerId, playerCurrentState, entityCurrentStates, inputs, deltaTime) {
var newState = {};
if (!playerCurrentState.x) {
playerCurrentState.x = 0;
+3 -1
View File
@@ -202,13 +202,15 @@ New state of the entity containing all of the properties specific to an entity f
#### addEntity
---
```js
GarageServerIO.addEntity(id)
GarageServerIO.addEntity(id, referrerId)
```
Notify GarageServer.IO that a new entity has been added to the game.
`id` **string**
Id of the entity to be added.
`referrerId` **string**
Id of the player who invoked/create the entity - optional and used primarily for client side prediction.
#### removeEntity
---
```js
+1 -1
View File
@@ -29,7 +29,7 @@ Game.prototype.update = function () {
self = this;
players.forEach(function (player) {
var newState = gamePhysics.getNewPlayerState(player.state, player.inputs, self.physicsDelta, self.server);
var newState = gamePhysics.getNewPlayerState(player.id, player.state, player.inputs, self.physicsDelta, self.server);
self.server.updatePlayerState(player.id, newState);
});
+2 -2
View File
@@ -10,8 +10,8 @@ $(function () {
GarageServerIO.initializeGarageServer('', {
logging: true,
onReady: startGame,
onUpdateClientPredictionReady: function(playerId, playerCurrentState, inputs, deltaTime) {
GarageServerIO.updatePlayerState(playerId, GamePhysics.getNewPlayerState(playerCurrentState, inputs, deltaTime));
onUpdateClientPredictionReady: function(playerId, playerCurrentState, entityCurrentStates, inputs, deltaTime) {
GarageServerIO.updatePlayerState(playerId, GamePhysics.getNewPlayerState(playerId, playerCurrentState, inputs, deltaTime));
},
onInterpolation: GamePhysics.getInterpolatedState
});
+2 -2
View File
@@ -1,6 +1,6 @@
(function(exports){
exports.getNewPlayerState = function (state, inputs, deltaTime, garageServer) {
exports.getNewPlayerState = function (id, state, inputs, deltaTime, garageServer) {
var i = 0, distance = 0, newState = {};
if (!state.ang && state.ang !== 0) {
@@ -28,7 +28,7 @@
} else if (inputs[i].input === 'space') {
if (garageServer && (new Date().getTime() - newState.lastFire) > 1000) {
var newId = guid();
garageServer.addEntity(newId);
garageServer.addEntity(newId, id);
garageServer.updateEntityState(newId, { x: newState.x, y: newState.y, ang: newState.ang } );
newState.lastFire = new Date().getTime();
}
+3 -2
View File
@@ -8,7 +8,7 @@ function EntityController (maxHistorySecondBuffer) {
}
EntityController.prototype = {
add: function (id) {
add: function (id, referrerId) {
var newEntity, entityFound = false;
this.entities.some(function (entity) {
@@ -20,7 +20,8 @@ EntityController.prototype = {
});
if (!entityFound) {
newEntity = new entity(id, this.maxHistorySecondBuffer);
var referrerSeq = this.entities.filter(function (value) { return value.referrerId === referrerId; }).length;
newEntity = new entity(id, referrerId, referrerSeq, this.maxHistorySecondBuffer);
this.entities.push(newEntity);
}
return newEntity;
+3 -1
View File
@@ -2,10 +2,12 @@ var history = require('./history');
exports = module.exports = Entity;
function Entity (id, maxHistorySecondBuffer) {
function Entity (id, referrerId, referrerSeq, maxHistorySecondBuffer) {
this.state = {};
this.sequence = 1;
this.id = id;
this.referrerId = referrerId;
this.referrerSeq = referrerSeq;
this.maxHistorySecondBuffer = maxHistorySecondBuffer;
this.stateHistory = [];
this.region = '';
+1 -1
View File
@@ -3,7 +3,7 @@ var entity = require('./entity');
exports = module.exports = Player;
function Player (socket, maxHistorySecondBuffer) {
entity.call(this, socket.id, maxHistorySecondBuffer);
entity.call(this, socket.id, null, null, maxHistorySecondBuffer);
this.socket = socket;
this.inputs = [];
}
+2 -2
View File
@@ -150,8 +150,8 @@ GarageServer.prototype.updateEntityState = function (id, state) {
this.game.updateEntityState(id, state);
};
GarageServer.prototype.addEntity = function (id) {
this.game.addEntity(id);
GarageServer.prototype.addEntity = function (id, referrerId) {
this.game.addEntity(id, referrerId);
};
GarageServer.prototype.removeEntity = function (id) {
+2 -2
View File
@@ -103,8 +103,8 @@ GarageServerGame.prototype.removePlayer = function (id) {
this.playerController.remove(id);
};
GarageServerGame.prototype.addEntity = function (id) {
this.entityController.add(id);
GarageServerGame.prototype.addEntity = function (id, referrerId) {
this.entityController.add(id, referrerId);
};
GarageServerGame.prototype.removeEntity = function (id) {