9.4 Composite sprites

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 cSpriteBubble

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); 
        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.

Figure 9.3. The cSpriteBubble composite sprite. Accent rectangle is translated away from origin.


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


    Part I: Software Engineering and Computer Games
    Part II: Software Engineering and Computer Games Reference