// xsc: Copyright (c) 1993-2005 by Mark B. Hanson (mbh@panix.com). static const char *const file_id = "@(#)$Id: ring.C,v 3.8 2005/01/02 19:11:17 mark Exp $"; #include "global.h" #include "trig.h" #include "util.h" #include "xsc.h" #include "ring.h" using namespace Trig; namespace { const coords ring_points[] = { { COS00 / 2.0, -SIN00 / 2.0 }, { COS30 / 2.0, -SIN30 / 2.0 }, { COS30 / 2.0, -SIN30 / 2.0 }, { COS60 / 2.0, -SIN60 / 2.0 }, { COS60 / 2.0, -SIN60 / 2.0 }, { COS90 / 2.0, -SIN90 / 2.0 }, { COS90 / 2.0, -SIN90 / 2.0 }, { -COS60 / 2.0, -SIN60 / 2.0 }, { -COS60 / 2.0, -SIN60 / 2.0 }, { -COS30 / 2.0, -SIN30 / 2.0 }, { -COS30 / 2.0, -SIN30 / 2.0 }, { -COS00 / 2.0, -SIN00 / 2.0 }, { -COS00 / 2.0, -SIN00 / 2.0 }, { -COS30 / 2.0, SIN30 / 2.0 }, { -COS30 / 2.0, SIN30 / 2.0 }, { -COS60 / 2.0, SIN60 / 2.0 }, { -COS60 / 2.0, SIN60 / 2.0 }, { -COS90 / 2.0, SIN90 / 2.0 }, { -COS90 / 2.0, SIN90 / 2.0 }, { COS60 / 2.0, SIN60 / 2.0 }, { COS60 / 2.0, SIN60 / 2.0 }, { COS30 / 2.0, SIN30 / 2.0 }, { COS30 / 2.0, SIN30 / 2.0 }, { COS00 / 2.0, -SIN00 / 2.0 }, }; } // namespace Ring::Ring(const float nscale, const float speed, const unsigned int v, const GC *const gclist, const int ngcs) { //fprintf(stderr, "Ring::Ring()\n"); set_scale(nscale); points = ring_points; num_points = sizeof(ring_points) / sizeof(coords); xpoints = new XPoint[num_points]; numsegments = num_points / 2; hits = new hitstatus[numsegments]; refresh(); dtheta = speed; theta = 0.0; x = wwidth2; y = gwheight2; value = v; gcs = new GC[ngcs]; for (int i = 0; i < ngcs; i++) { gcs[i] = gclist[i]; } } // Ring::Ring Ring::~Ring(void) { //fprintf(stderr, "Ring::~Ring()\n"); delete[] hits; delete[] gcs; } // Ring::~Ring void Ring::render(const bool ink) { if (ink) { set_xpoints(); } const GC blackgc = fetch_gc(GC_BLACK); for (int i = 1; i < num_points; i += 2) { const GC drawgc = ink ? gcs[hits[i/2]] : blackgc; if (!ink || drawgc != blackgc) { XDrawLine(display, window, drawgc, xpoints[i - 1].x, xpoints[i - 1].y, xpoints[i].x, xpoints[i].y); } } } // Ring::render inline int Ring::which_seg(const float degrees) const { return (int)(normalize(wedge(theta, degrees)) / (360.0 / numsegments)); } // Ring::which_seg void Ring::seg_center(const float degrees, float *const xptr, float *const yptr) const { const int segment = which_seg(degrees) * 2; *xptr = (xpoints[segment].x + xpoints[segment + 1].x) / 2.0; *yptr = (xpoints[segment].y + xpoints[segment + 1].y) / 2.0; } // Ring::seg_center bool Ring::hole(const float degrees) const { if (hits[which_seg(degrees)] < RING_DEAD) { return false; } return true; } // Ring::hole bool Ring::hit(Laser *laser, Stats *stats) { const int segment = which_seg(laser->get_angle()); switch (hits[segment]) { case RING_DULL: hits[segment] = RING_BRIGHT; return true; case RING_BRIGHT: hits[segment] = RING_DEAD; stats->score += value; return true; case RING_DEAD: return false; } return false; } // Ring::hit int Ring::remaining(void) const { int retval = 0; for (int i = 0; i < numsegments; i++) { if (hits[i] < RING_DEAD) { retval++; } } return retval; } // Ring::remaining void Ring::refresh(void) { for (int i = 0; i < numsegments; i++) { hits[i] = RING_DULL; } } // Ring::refresh