Sunday, July 18, 2010

Less Owiee

‹prev | My Chain | next›

Up today, I am trying to figure out SVG. Well maybe not all of SVG, but at least SVG paths.

My lack of SVG understanding caused a bit of a problem yesterday in my raphaël.js animations. Specifically, the leg on the left side of my "player" spins around in mid-air:

video

I am reasonably sure that this is caused by how I drew the leg in Inkscape. To animate SVG or raphaël.js, one supplies a start SVG path and an end path. Both paths for the leg—the leg while "standing" and the leg while "walking"—were drawn in Inkscape. For one path, I started drawing at the bottom and went up, but for the other, I started at the top and went down. Directions matter in SVG.

I can fix this simply enough by redrawing in the right direction, but I would like to see if I can figure out SVG well enough to fix this by hand. The SVG paths for the walking & standing left left are:
var standing = [
{ label: "left_leg",
d: "M 9.7001312,18.93142 C 9.4644309,22.702657 9.2287306,26.473893 8.9930303,30.24513" },
... ]

var walking = [
{ label: "left_leg",
d: "m 3.9748751,28.518101 c 2.828427,-3.88909 5.6568539,-7.77818 8.4852809,-11.66727" },
... ]
For comparison, the right leg paths are:
var standing = [
{ label: "right_leg",
d: "m 13.942752,18.93142 c 0.353552,3.653383 0.707104,7.306767 1.060656,10.96015" },
... ]

var walking = [
{ label: "right_leg",
d: "m 23.066757,17.204391 c 1.767767,3.653383 3.535533,7.306767 5.3033,10.96015" },
... ]
Interesting. So the standing version of the left leg is the only one beginning with a capital "M" and containing a capital "C". Simply switching the uppercase "M" and "C" to lowercase has no effect. I did not really expect it to, but it was worth a try.

Actually reading through the documentation I see that the initial M/m + x-y coordinates are absolute coordinates for the start of the path. It is where the pen is put down to start drawing.

Next up is the C/c stuff which is a Bezier curve. I have drawn Bezier curves in graphical packages before, but I have very little what they are. My background is in physics, not graphics. If Bezier curves were covered in physics 101, I missed that day. So I read through the documentation. The fist two points in the Bezier curve are control points, the third is the end point:
class="prettyprint">var standing = [
{ label: "left_leg",
d: "M 9.7001312,18.93142 C 9.4644309,22.702657 9.2287306,26.473893 8.9930303,30.24513" },
... ]
So I am starting at x: 9.7, y: 18.9. I then move through two control points (which should be in nearly a straight line), then end at x: 9.0, y: 30.2. That seems reasonable.

For the "walking" leg, I have:
var walking = [
{ label: "left_leg",
d: "m 3.9748751,28.518101 c 2.828427,-3.88909 5.6568539,-7.77818 8.4852809,-11.66727" },
... ]
Interesting. So I start the pen stroke at x: 4.0, y: 28.5. That is about the same y-coordinate at which the standing leg ended, so I have definitely gone in a different direction drawing things. Next up is a lowercase "c", which indicates that the coordinates are relative to the pen start coordinates. It is also fairly apparent that the coordinates are relative based on the negative y-coordinates in the Bezier curve.

I am unclear what made Inkscape describe one of the lines with absolute coordinates and the other with relative coordinates. The relative coordinates seem to be favored in the other curves so I am tempted to stick with the relative curve and fix the absolute curve. Instead, I will fix the relative. For the other three legs, I started drawing from the player's body and ended down at the feet. Since the relative coordinates are decreasing the y-coordinates, I clearly started the pen stroke at the feet.

To fix, I calculate the absolute coordinates:
m 3.9748751,28.518101
c 6.8033021,24.629011
9.631729,20.739921
12.460156,16.850831
Inverting those coordinates, my new starting point is x: 12.5, y: 16.9 and the new ending point is x: 4.0 and y: 28.5. Definitely going in the right direction now. I could go further and calculate relative coordinates at this point, but why bother? This ought to describe my Bezier curve well and, more importantly, in the right direction:
var walking = [
{ label: "left_leg",
d: "M 12.460156,16.850831 C 9.631729,20.739921 6.8033021,24.629011 3.9748751,28.518101" },
... ]
With my paths for the legs both going in the same direction, the animation stays together:

video

That is a good stopping point for tonight. Tomorrow, I think I will try to animate the player moving in addition to looking as though it is walking.


Day #168

No comments:

Post a Comment