To be brief, I am working on a real-time multiplayer game. In my game, the clients send updated position and velocity data to the server at a frequency of 20Hz. In the example code below, I am converting data from a Lua table into a C struct using LuaJIT FFI. It's a nifty way of transporting data over a network:
self.dt_f = self.dt_f + dt
if self.dt_f >= self.tick_f and self.id then
self.dt_f = self.dt_f - self.tick_f
local player = self.players[self.id]
local data = {
type = packets["player_update_f"],
id = self.id,
position_x = player.position.x,
position_y = player.position.y,
position_z = player.position.z,
velocity_x = player.velocity.x,
velocity_y = player.velocity.y,
velocity_z = player.velocity.z,
}
local struct = cdata:set_struct("player_update_f", data)
local encoded = cdata:encode(struct)
self.client:send(encoded)
end
When the server receives the packet, it tries to adjust the data to compensate for the latency between that particular client and itself:
local player = self.players[id]
player.position = update.position or player.position
player.velocity = update.velocity or player.velocity
local server = self.server.connection.socket
local peer = server:get_peer(id)
local ping = peer:round_trip_time() / 2 / 1000
player.position = player.position + player.velocity * ping
Once the data is normalized, it then broadcasts the updated position info to all other clients:
local data = {
type = packets["player_update_f"],
id = id,
position_x = player.position.x,
position_y = player.position.y,
position_z = player.position.z,
velocity_x = player.velocity.x,
velocity_y = player.velocity.y,
velocity_z = player.velocity.z,
}
local struct = cdata:set_struct("player_update_f", data)
local encoded = cdata:encode(struct)
self.server:send(encoded)
When the other clients finally get the packet, they adjust the data based on their latency with the server:
if id ~= self.id then
self.players[id] = self.players[id] or {}
self.players[id].position = update.position or self.players[id].position
self.players[id].velocity = update.velocity or self.players[id].velocity
local ping = self.client.connection.peer:round_trip_time() / 2 / 1000
self.players[id].position = self.players[id].position + self.players[id].velocity * ping
end
So herein lies the problem: The objects are very jittery. Every time I receive a packet, the other players warp a little forward or a little backward, so it seems like my latency compensation is off which makes my interpolation off. Perhaps someone could point out some obvious flaw in my code, or perhaps my understanding of how the process works?