230 | Chapter 6: Composite Pattern
Theupdate( )method implements steps three and four described in Figure 6-7. Lines
18-20 access the current component’s parent and create two points that represent C1
and P2 in step 3 of Figure 6-7.
Lines 22-25 calculate the new angle for the child component, so that it can orient to
the new location of the joint. Subtracting point C1 from P2 in step 3 of Figure 6-7
provides a point whosexandyproperties represent the horizontal and vertical dis-
tance between the two points. Thus the new angle of rotation for the child can be
easily calculated by feeding these values to the arctangent function. Note that the
Math.atan2function returns the angle inradians. This has to be converted todegrees
before assigning to therotation property.
Lines 27-31 move the now correctly oriented child segment to maintain the joint and
registration point distance (shown asdin step 3 of Figure 6-7). The current distance
between points C1 and P2 is calculated first (line 28). Next, thePoint.interpolate
function is used to determine the intermediate point C2 that would maintain the cor-
rect segment lengthd. The third parameter in thePoint.interpolatefunction is a
ratio value (between 0 and 1) that represents a point between two points.
Finally, theupdate( )method calls itself in the superclass (line 33) to update its child
components.
The tail component, the last segment of the snake, is shown in Example 6-16. The
Tailclass subclassesComponent(Example 6-11), draws the tail in its constructor, and
implements theupdate( )method. The tail is drawn as a rattle, transforming our
generic snake into a rattlesnake. Unlike theBodySegmentclass, theupdate( )method
does not call itself in the superclass, as the tail is a component that can’t have any
children.
23 var tempPoint:Point = parentLoc.subtract(myLoc);
24 var angle:Number = Math.atan2(tempPoint.y, tempPoint.x);
25 this.rotation = angle * 180 / Math.PI;
26
27 // move to maintain distance
28 var currentDistance:Number = Point.distance(
29 parentLoc, myLoc);
30 var myNewLoc:Point = Point.interpolate(myLoc, parentLoc,
segLen / currentDistance);
31 this.x = myNewLoc.x;
32 this.y = myNewLoc.y;
33
34 super.update( );
35 }
36 }
37 }
Example 6-15. BodySegment.as