Sunday, August 15, 2010

Mitigating Faye Latency in Games

‹prev | My Chain | next›

Today, I continue exploring ways to mitigate faye latency as it affects my (fab) game. As noted yesterday, there is a 200 millisecond delay between publishing messages to a faye channel and the message reaching a subscribing function. This has almost no effect in my (fab) game other than collision detection:



The collision is seen much earlier in my player's screen than it is seen on the screens of other players. I have already blindly moved code about in a vain attempt to solve the latency issue. Before moving more code about, a look at the problem I am facing.

As mentioned, there is a 200 millisecond latency in faye communication. Looking at the client-side code, I find some more constraints:
Player.radius = 10;
Player.shadow_distance = 20;
Player.max_walk = Math.sqrt(500*500 + 500*500);
Player.time_to_max_walk = 5 * 1000;
From that, I can determine the speed at which my players can move in the room. The max_walk distance evaluates to 707.1 pixels. If the player takes 5 seconds to make that walk, then the speed is 141.2 pixels/second. Thus, during the 200 millisecond latency, the player will travel 28.2 pixels. That is a little more than the diameter of a player. That pretty much explains the delay that I am seeing.

So how can I mitigate the problem? One thing I can do is slow down the players. If I halve the speed at which players move, then players will travel 14 pixels during the faye latency. That still seems too much since the diameter of a player is 20 pixels. Hrm... well, I could double the size of a player as well:
Player.radius = 20;
Player.shadow_distance = 30;
Player.max_walk = Math.sqrt(500*500 + 500*500);
Player.time_to_max_walk = 10 * 1000;
What will that do?



That is still not good enough. The player is almost completely overlapping the other when the bounce is signaled. It is at this point that I realize part of the problem is that I am detecting a collision at the center of my player. If it were possible to detect a collision at the edge in which the player is moving, things might work better. That is, if the player is moving to the right, then I should try detecting collisions at the center x coordinate plus the radius of the player.

As luck would have it, I am already storing the direction in which a player is moving (so that the bounce away can be in the opposite direction). I can use that to detect edge collisions:
    var c_x = avatar.attr("cx") +
$(self.avatar.paper.canvas).parent().offset().left -
$(document).scrollLeft() +
self.direction.x * Player.radius;

var c_y = avatar.attr("cy") +
$(self.avatar.paper.canvas).parent().offset().top -
$(document).scrollTop() +
self.direction.y * Player.radius;
With that my collisions are actually rather good:



That is a fine stopping for tonight. Tomorrow, I will consider alternatives I have not thought up just yet and hopefully drive toward an all-around satisfying solution. But this is pretty close.


Day #196

No comments:

Post a Comment