Friday, June 4, 2010

Size and Animation in Raphaël.js

‹prev | My Chain | next›

After a bit of fun with Cucumber and javascript (by way of v8), I am back on raphaël.js tonight. My goal is twofold: to make the look of my (fab) game slightly less craptacular and to begin thinking about an animation callback that my kids can code against.

To improve the look of the game, I would like to make the players a bit bigger (in anticipation of eventually replacing them with animated graphics). Currently the players look like this:



To make the player bigger, I simply need increase the radius of the raphaël.js element from 3 to 10:
  var c = this.paper.circle(player.x, player.y, 10);
I would also like to draw a border around the circle. This is possible through the stroke properties. It took me a while to figure it out (sadly), but the "stroke" is the "pen" mark as the element is drawn—the circle in this case. To color the player in, I had been filling the circle, but not stroking the outline as it was drawn. Now I can add a few stroke attributes to get my outline:
  c.attr({fill: color, "fill-opacity": 0.5, stroke: '#000', "stroke-width": 2, "stroke-opacity": 1.0});
Lastly, I would like to increase the text size on the player's name. This is done by invoking the attr method on the text label:
  this.label = drawable.paper
.text(this.x, this.y + 20, this.id)
.attr({"font-size": 12});
With that, I have a (slightly) prettier player:



Easy enough. There may just be something to this Raphaël.js stuff after all. To be sure of it, I would like to use it to animate the player as it walks about the room. Will Raphaël.js be able to accommodate this?

The answer, of course, is "yes", but, for a while there, I was not sure if I would be able to pull it off. My initial woes stemmed from the callback parameter to the animateAlong method. I had expected that the callback would be called at every point along the animation. It turns out that it only gets called at the end of the animation. That won't be much help in animating the player.

The answer to this problem is the onAnimation raphaël.js method which does just what I need: gets called at every point along the animation. I am already using it to shadow the player name along with the avatar. I can add a animate_with callback call in there as well:
  var animation_count = 0;
avatar.onAnimation(function(){
self.label.attr({x: avatar.attr("cx"), y: avatar.attr("cy") + 20});

if (++animation_count > 25) {
self.animate_with(this);
animation_count = 0;
}
});
(the animation count is used because I don't think that the animate_with callback need be called every millisecond of animation).

With that, I can create the player in the room with silly animation that changes the fill color randomly:
    var me = new Player(kv[1], {animate_with: function(avatar){
var color = ["#ccc", "#c00", "#0c0"][Math.floor(3*Math.random(3))];
avatar.attr({fill: color});
}
});
That yields a decent proof of concept animation:


That's a good stopping point for today. Up tomorrow: fix a few bugs that seem to have cropped up in the fab.js backend.

Day #124

No comments:

Post a Comment