// xsc: Copyright (c) 1993-2005 by Mark B. Hanson (mbh@panix.com). static const char *const file_id = "@(#)$Id: buzzer.C,v 3.11 2005/01/02 19:11:17 mark Exp $"; #include "global.h" #include "random.h" #include "trig.h" #include "util.h" #include "xsc.h" #include "buzzer.h" using namespace Trig; namespace { const coords buzzer_points[] = { { 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 }, }; } // namespace Buzzer::Buzzer(void) { //fprintf(stderr, "Buzzer::Buzzer()\n"); set_scale(60.0); flying = false; paused = false; points = buzzer_points; num_points = sizeof(buzzer_points) / sizeof(coords); xpoints = new XPoint[num_points]; randomizer = new float[num_points]; riding_on = new bool[3]; // castle->get_numrings(); set_gc(fetch_gc(GC_GREEN)); speed = (wwidth / (10.0 + (Random::get() % 6)) / args.fps); } // Buzzer::Buzzer Buzzer::~Buzzer(void) { //fprintf(stderr, "Buzzer::~Buzzer()\n"); delete[] randomizer; delete[] riding_on; } // Buzzer::~Buzzer void Buzzer::set_randomizer(void) { if (paused) { return; } for (int i = 0; i < num_points; i++) { randomizer[i] = (Random::get() % 900) / 1000.0 + 0.10; } } // Buzzer::setrandomizer void Buzzer::render(const bool ink) { if (!alive()) { return; } if (ink) { set_randomizer(); set_xpoints(); } paint_points(ink); } // Buzzer::render void Buzzer::move(Castle *castle, Ship *ship) { if (!alive()) { return; } int i; const int numrings = castle->get_numrings(); float ring_radius; const float to_ship = xatan2(ship->get_y() - y, x - ship->get_x()); const float direction = (get_radius() < castle->ring_size(numrings - 1) / 2.0) ? get_angle() : to_ship; // see if we are riding on any of the rings for (i = 0; i < numrings; i++) { if (!riding_on[i]) { continue; } if (castle->hole(i, get_angle()) || (ship->alive() && Random::get() % (int)(2 * args.fps) == 0)) { riding_on[i] = false; set_gc(fetch_gc(GC_GREEN)); ring_radius = castle->ring_size(i) / 2.0; float angle = (i == numrings - 1) ? get_angle() : to_ship; x = wwidth2 + (xcos(get_angle()) * ring_radius) + (xcos(angle) * speed * 2); y = gwheight2 + (-xsin(get_angle()) * ring_radius) + (-xsin(angle) * speed * 2); } else { castle->seg_center(i, get_angle(), &x, &y); } if (ship->hit(this)) { snuff(); } return; } dx = xcos(direction) * speed; dy = -xsin(direction) * speed; // check to see if we should attach to a ring segment for (i = 0; i < numrings; i++) { ring_radius = castle->ring_size(i) / 2.0; bool segment_exists = !castle->hole(i, get_angle()); bool am_outside = get_radius() > ring_radius; bool am_inside = get_radius() < ring_radius; float new_radius = hypot(wwidth2 - (x + dx), gwheight2 - (y + dy)); bool going_inside = new_radius <= ring_radius; bool going_outside = new_radius >= ring_radius; if (segment_exists && ((am_outside && going_inside) || (am_inside && going_outside))) { riding_on[i] = true; set_gc(castle->get_gc(i)); castle->seg_center(i, get_angle(), &x, &y); return; } } x += dx; y += dy; // check for collision with ship if (ship->hit(this)) { snuff(); } } // Buzzer::move void Buzzer::upgrade(Castle *castle) { const int numrings = castle->get_numrings(); bool *new_riding = new bool[numrings]; int i; for (i = 0; i < numrings; i++) { new_riding[i] = false; } for (i = numrings - 1; i >= 0; i--) { if (!riding_on[i]) { continue; } if (i > 0) { new_riding[i - 1] = true; set_gc(castle->get_gc(i - 1)); castle->seg_center(i - 1, get_angle(), &x, &y); } else { set_gc(fetch_gc(GC_GREEN)); float deg = get_angle(); float ring_radius = castle->ring_size(i) / 2.0; x = wwidth2 + (xcos(deg) * ring_radius); y = gwheight2 + (-xsin(deg) * ring_radius); } } for (i = 0; i < numrings; i++) { riding_on[i] = new_riding[i]; } delete[] new_riding; } // Buzzer::upgrade void Buzzer::launch(King *king, Castle *castle) { const float deg = normalize(king->get_theta() + 180); const int numrings = castle->get_numrings(); // find a location near the back end of the king x = wwidth2 + (xcos(deg) * (wwidth / 30.0)); y = gwheight2 + (-xsin(deg) * (wwidth / 30.0)); for (int i = 0; i < numrings; i++) { riding_on[i] = false; } set_gc(fetch_gc(GC_GREEN)); flying = true; } // Buzzer::launch bool Buzzer::hit(Laser *laser) { if (alive() && hypot(laser->get_x() - x, laser->get_y() - y) < (diag + laser->get_diag()) / 2.0) { snuff(); return true; } return false; } // Buzzer::hit void Buzzer::set_xpoints(void) { for (int i = 0; i < num_points; i++) { float nsize = randomizer[i] * size; xpoints[i].x = (int)((nsize * points[i].x) + x); xpoints[i].y = (int)((nsize * points[i].y) + y); } } // Buzzer::set_xpoints void Buzzer::resize(const int nwidth, const int nheight) { speed *= (float)nwidth / wwidth; Xything::resize(nwidth, nheight); } // Buzzer::resize