The cSpriteComposite holds an array of cSprite pointers called _childspriteptr. The default cSpriteComposite::draw behavior is to walk the array and call draw for each of the child sprites.
for (int i=0; i< _childspriteptr.GetSize(); i++) _childspriteptr[i]->draw(pgraphics, drawflags);
We can make some nice shapes this way. We'll consider two examples in this section: the cSpriteBubble and the cPolyPolygon.
The PickNPoP game viewed in OpenGL 3D. On the left are cSpriteBubble and cSpriteBubbleGrayScale, on the right are cSpriteBubblePie
The cSpriteBubble consists of a disk with a rectangular highlight on it, meant to be mildly suggestive of the reflection of a window in the surface of a soap bubble. We implement cSpriteBubble as a cSpriteComposite with two members: a cSpriteCircle (that is, a many-sided polygon) and a cPolygon rectangle that we can access as the cSpriteBubble::paccentpoly().
void cSpriteBubble::setAccentPoly() { Real side = 0.33 * (pcirclepoly()->radius()); cVector pverts[4] = {cVector(0.0, 0.0, 0.0), cVector(2*side, 0.0, 0.0), cVector(2*side, side, 0.0), cVector(0.0, side, 0.0)}; cPolygon *prectpoly = new cPolygon(4, pverts); prectpoly->setSpriteAttitude( cMatrix::translation(cVector(side, 0.5*side, 0.1)); add(prectpoly); //Decoration rectangle. setFillColor(pcirclepoly()->fillColor()); /* Make the accent color match the circle. */ }
Figure 9.3 is a picture of the construction.
The cPolygon constructor by default centers the rectangle on the origin, which is why we need to set the rectangular accent polygon's _spriteattitude to cMatrix::translation(cVector(side, 0.5*side, 0.1)). This moves the rectangle away from the origin and into the position shown. The 0.1 translation in the z slot is so that, when viewed in 3D, the accent rectangle sticks up a bit out of the disk of the circle. You need to be careful not to draw faces of polygons in the same plane in 3D as then they 'z-fight' with each other and flicker in an ugly fashion.
Now let's say a bit about the cPolyPolygon class. A polypolygon is a cSpriteComposite which consists of a base polygon plus a secondary 'tipshape' polygon at each vertex.
The way we've implemented the polypolygons is to assume that a polypolygon will have the same tipshape at each of its vertices. We use the cPolyPolygon methods setBasePoly(cPolygon* pppoly) and setTipShape(cSprite* pshape) to set the base and the tipshape information.
You can view a bunch of these guys by opening up the Spacewar game and selecting Game | Polypolygons. Note that when the game reseeds itself, it reverts to asteroid sprites; if you want a game that sticks with polypolygon sprites, you need to code this fact into the constructors of the game's critters.
In order to make a more symmetric image, we design the cPolyPolygon::draw method so as to draw an image of the tipshape which is rotated slightly from vertex to vertex; more precisely, if a polygon has n vertices, then we draw the tipshape as is at the first vertex, and then rotate it by 2 * PI/n for each of the successive vertices, rotating it back into starting position when we're done.
Polyploygons in the Spacewar game