Monday, August 16, 2010

Finishing (hopefully) Touches on Collisions with Faye

‹prev | My Chain | next›

I got collision handling in my (fab) game accommodating faye latency. I did so my making my player larger, slower and detecting collisions at the edge of the player in the direction in which the player is moving.

In the end, the players are a tad large (40 pixels wide in a 500 pixel room) and sluggish (requiring 10 seconds from corner to corner). So first up, I put the player on a diet and move them a little faster:
Player.radius = 15;
Player.shadow_distance = Player.radius + 10;
Player.max_walk = Math.sqrt(500*500 + 500*500);
Player.time_to_max_walk = 8 * 1000;
With that, I need to extend the collision point forward a bit—in essence signal a collision before the collision occurs. That will lead to some phantom strikes, but hopefully nothing too bad. Let's try adding about 10%:
    var c_x = avatar.attr("cx") +
$(self.avatar.paper.canvas).parent().offset().left -
$(document).scrollLeft() +
1.1 * self.direction.x * Player.radius;

var c_y = avatar.attr("cy") +
$(self.avatar.paper.canvas).parent().offset().top -
$(document).scrollTop() +
1.1 * self.direction.y * Player.radius;
That seems to work, except when the player is moving downward in the room. In that case, the extended collision point is overlapping with the player's label. To resolve that, I add an attribute to the player object:
Player.prototype.attach_avatar = function(avatar) {
//...
avatar.node.is_player_circle = true;
//...
}
And use that to ensure that the object that raphaël.js is telling me that is in collision is a player circle:
    if (!self.initial_walk &&
!self.mid_bounce &&
c_el.is_player_circle &&
c_el != self.avatar.node) {
self._bounce_away(c_x, c_y);
}
That actually solves a bit of a problem that I have had in the code for a while—how to test for collisions with "collidable" objects. If there need to be more objects that can collide, then I can test for that attribute. Previously, I had been testing there that the colliding object was not the raphaël paper itself. The new condition handles that case nicely as well (the paper does not have that attribute set).

With that, I still have one minor change that still needs to take place: the bounce away from the collision needs to be a bit further than it had been (the radius of a player). Trial and error suggests that the player radius plus 50% should do:
Player.prototype._bounce_away = function(from_x, from_y) {
this.mid_bounce = true;

var x = from_x - 1.5*Player.radius*this.direction.x,
y = from_y - 1.5*Player.radius*this.direction.y;

this.faye.publish('/players/bounce', {id: this.id, x: x, y: y});
};
That gives me fairly decent collisions, well represented in both my browser and in the browser of other players:

video

I think I will leave well enough alone at this point. The idle timeout seems to be acting up on me again, so I will look into that a bit more tomorrow before moving onto other things.


Day #197

No comments:

Post a Comment