Particularly in three dimensions, we very often want to represent our critters by colored polygons, perhaps by just one polygon, perhaps by a few, or perhaps by a whole mesh of them. Computer graphics systems draw polygons in an entirely different way from how they draw bitmaps. A bitmap is based on discrete pixel-by-pixel information, while a polygon is based on coordinates in continuous space. In drawing a polygon, we convert its space coordinates into pixel coordinates, use fill algorithms to color it in, and use line-drawing algorithms to draw its edges.

Windows has a built-in `CDC::Polygon(POINT * vertices, int vertexcount)`
method which makes it easy to rapidly draw polygons on the screen. Our `cPolygon`
class is designed to create polygon structures that can take advantage of this function call.

We can create an empty polygon with the default polygon constructor `cPolygon()`, and then we can put some structure onto it by using one of our special mutators. Note that as usual you can leave out the trailing arguments which have default values defined.

void setRegularPolygon(int vertexcount); void setStarPolygon(int vertexcount, int step); void setRandomStarPolygon(int mincount, int maxcount); void setRandomRegularPolygon(int mincount, int maxcount); void setRandomAsteroidPolygon(int mincount = 5, int maxcount = 30, Real spikiness = 0.3);

The `setRegularPolygon`
and `setStarPolygon`
mutators produce polygons with a user-selected `vertexcount`. The `step`
argument to the star polygon controls the kind of star that is drawn. In general, choosing a step smaller than the vertex count which has no divisors in common with the vertex count produces the nicest stars. At present the stars look good in `cGraphicsMFC`, but `cGraphicsOpenGL`
still needs to be tweaked to draw them properly.

The `setRandomRegularPolygon`
and the `setRandomStarPolygon`
are methods for randomly making a regular or a star polygon with its vertex count and its radius within specified ranges.

The Spacewar game is something like the traditional Asteroids. So it will be useful to have some `setRandomAsteroidPolygon`
to create random irregular polygons. To make the asteroid polygons look solid, we add their vertices in successive counterclockwise order ? if we add them out of order we'll get something like a star. Stars look nice if they're regular, but an irregular star just looks like a scribble. We use the spikiness parameter to control the difference between minimum radius and maximum radius used for the various asteroid vertices.

Another approach, which we use when we want a particular shape, is to use the `cPolygon(n)`
constructor and then use `n`
calls to `setVertex (int n, cVector v)`
to build up the polygon a step at a time. Note that by default, we assume we have a closed polygon in which the last point is automatically connected to the first point.

Once we have a polygon, we can adjust its interior with various mutators that you find in `polygon.h`. One easy way to vary a polygon sprite is to call the randomize method with the `MF_` flags defined in `polygon.h`. For instance the `ppolygon->randomize(cPolygon::MF_COLOR)` will randomize the `ppolygon` fill color, and the `cPolygon::MF_ALL`
flag will randomize everything.

We can adjust the lines around the edges of the polygon with the _`edged`
and _`reallinewidth`
fields. The _`reallinewidth`
field controls the ratio of the thickness of the line to the polygon's radius. A value of, say, 0.2 will give a fat line. We state this quantity as a real number ratio rather than a pixel width so that the polygon will still have the same appearance when drawn at different size scales. But if the converted pixel width of the line would be less than one, we still draw a line of pixel width one, assuming that _`edged`
is `TRUE`. Drawing lines of width greater than one slows the Windows `Polygon`
function down inordinately, so we recommend sticking to the default _`reallinewidth`
of 0.0, which will produce a line one pixel in width, which is what Windows really 'prefers' to draw. (`spritepolygon.h`
also has a `#define`
for a name for 0.0 to use in this 'line width' context: LW_ONEPIXEL.)

As a non-standard extra, we can also draw dots at our polygon vertices, using the _`dotted`
and _`realdotradius`
fields. The _`realdotradius`
field controls the ratio of the radius of the vertex dots of the polygon's radius. A value of, say, 0.2 will give fat dots. We state this quantity as a real number ratio rather than a pixel width so that the polygon will still have the same appearance when drawn at different size scales. The dots look quite nice; they are drawn after the polygon so they seem to sit on top of it. We have the option of filling the dots or not, and of selecting their fill colors. Dots aren't implemented for `OpenGL`.

A related class is `cSpriteCircle`, which is simply a `cPolygon`
with some static `int`
`cSpriteCircle::CIRCLESLICES` number of sides. If you don't make the 'circles' too big, a reasonable value for `CIRCLESLICES` is 16.

We could have implemented `cSpriteCircle`
to have an `imagedraw`
that calls something like an ellipse method, but it was quicker and easier to just treat the circles as many-sided polygons.

There are some differences between the implementations of `cGraphicsOpenGL`
and `cGraphicsMFC::drawpolygon`. As of August, 2002, the dots only show up with `cGraphicsMFC`, and the star-shaped polygons aren't as nicely drawn in `cGraphicsOpenGL`. These are 'bad' differences that could be fixed.

A 'good' difference between the two graphics implementations of `drawpolygon`
is that, to enhance the three-dimensionality of the view with OpenGL, the `cGraphicsOpenGL`
actually draws a polygon as a thick prism, that is, as a base polygon with vertical sides extending upwards to an identical cap polygon. The exact thickness of the prism can be controlled via the `cSprite`
field `Real _prismdz`, and this field can in turn be controlled either directly or by setting the `cCritter`
`_defaultprismdz`
field before adding the sprite. By default the various child critter classes use the following `_prismdz`
values.

Real cSprite::WALLPRISMDZ = 0.75; Real cSprite::PLAYERPRISMDZ = 0.5; Real cSprite::CRITTERPRISMDZ = 0.3; Real cSprite::BULLETPRISMDZ = 0.2; Real cSprite::MAXPRISMDZ = 1.0;

Thus, if you open up Dambuilder in the 3D view, you'll see the walls as taller than the player, the player as taller than the other critters, and the bullets as the thinnest of all.