// -------------------------------------------------------------------------- // // Copyright (c) 2003 Thomas D. Marsh. All rights reserved. // // "SSC" is free software; you can redistribute it // and/or use it and/or modify it under the terms of // the "GNU General Public License" (GPL). // // -------------------------------------------------------------------------- #include "ship.h" #include "draw.h" #include "global.h" #include "model.h" const unsigned int SHIP_SHIELD_RADIUS = 12; const unsigned int SHIP_RADIUS = 10; const unsigned int SHIP_MAX_SPEED = 15; const double SHIP_MASS = 10.0; inline void calcRotationPoints(double *x, double *y, double rot, int radius) { *x = rint(sin(rot) * radius); *y = rint(-cos(rot) * radius); } int SPHERE; Ship::Ship(double x, double y) : ScreenObject(PLAYER_TYPE, SHIP_SHIELD_RADIUS, SHIP_MASS, SHIP_MAX_SPEED, x, y) { r = g = 1; b = 0; init(); /* make a display list containing a sphere */ SPHERE = glGenLists(1); glNewList(SPHERE, GL_COMPILE); GLUquadricObj* quad; quad = gluNewQuadric(); // -------- yellow+alpha ------------ // ship body glPushMatrix(); glScalef(1, 1, .5); gluSphere(quad, radius, 20, 20); glPopMatrix(); // thrust cylinder 1 glPushMatrix(); glTranslated(-9, -9, 0); glRotated(90, 0, 1, 0); gluCylinder(quad, 2, 2, 18, 20, 20); glPopMatrix(); // thrust cylinder 2 glPushMatrix(); glTranslated(-9, 9, 0); glRotated(90, 0, 1, 0); gluCylinder(quad, 2, 2, 18, 20, 20); glPopMatrix(); // blaster glPushMatrix(); glTranslated(9, 0, 0); glRotated(90, 0, 1, 0); gluCylinder(quad, 2, 2, 4, 20, 20); glPopMatrix(); // -------- black ------------ glColor3f(0, 0, 0); // cockpit glPushMatrix(); glTranslated(1, 0, 4.0); glScalef(1, 1, .2); gluSphere(quad, 8, 10, 10); glPopMatrix(); glColor3f(.4, .4, .4); // exhaust glPushMatrix(); glTranslated(-9, 0, 0); glRotated(-90, 0, 1, 0); glRotated(90, 0, 0, 1); gluCylinder(quad, 4, 2, 6, 20, 20); glPopMatrix(); gluDeleteQuadric(quad); glEndList(); } Ship::~Ship() { } void Ship::init() { rotation = M_PI; rx = ry = 0; calcRotationPoints(&rx, &ry, rotation, radius); setPosition(100, 100, 0); setVelocity(0, 0, 0); shield.setStrength(1); mLife = 1; setState(ALIVE); } void Ship::move(double dt) { sync(); if (getState() == ALIVE) shield.regenerate(dt); else if (getState() == DYING) { if (!explosion.finished) explosion.move(dt); else init(); } ScreenObject::move(dt); } void Ship::draw() { if (getState() == ALIVE) { if (shield.getStrength() > 0) draw::setColor(.7, .7, .1); else draw::setColor(.7, .7, .1, .5); glPushMatrix(); glTranslated(mPosition.x, -mPosition.y, mPosition.z); glRotated(DEG(-rotation)+90, 0, 0, 1); glCallList(SPHERE); glPopMatrix(); // if (mDecelFlag) // { // draw::setColor(.8, 0, 0, .2); // draw::sphere(mPosition, radius+4); // draw::setColor(0, .8, 0, .2); // draw::sphere(mPosition, radius+7); // draw::setColor(0, 0, .8, .2); // draw::sphere(mPosition, radius+10); // mDecelFlag = false; // } } else if (getState() == DYING) explosion.draw(); } void Ship::fire() { sync(); (void) new Missile(PLAYER_TYPE, rotation, mPosition.x+(radius+5)*sin(rotation), mPosition.y-(radius+5)*cos(rotation), mPosition.z, mVelocity.x, mVelocity.y, mVelocity.z); } extern bool mDrawP; void Ship::accelerate(double amt) { sync(); if (mDrawP) for (int i = 0; i < (rand() % 30); i++) { float p = RAD((rand() % 61) - 30); double r, g, b; r = 1; g = (double) (rand() % 80) / 100; b = (double) (rand() % 30) / 100; double t = (double) ((rand() % 120)) / 5.0; addParticle(mPosition.x - radius*sin(rotation) + ((rand() % 7) - 3), mPosition.y + radius*cos(rotation) + ((rand() % 7) - 3), mPosition.z + (rand() % 7) - 3, -sin(rotation+p)*mMaxSpeed*.5, cos(rotation+p)*mMaxSpeed*.5, sin(p) * mMaxSpeed * .5, r, g, b, t); } ScreenObject::accelerate(amt); } void Ship::rotate(double amt) { ScreenObject::rotate(amt); calcRotationPoints(&rx, &ry, rotation, radius); } extern bool mGodMode; void Ship::damage(double amt) { if (mGodMode) return; static float pos[3] = {0.0, 0.0, 0.0}; if (shield.getStrength() == 0) { if (amt > mLife) { if (isAlive()) { setState(DYING); Global::audio->playSound(Audio::EXPLOSION, pos); explosion.age = 0; explosion.finished = false; explosion.init(*this); } mLife = 0; } else mLife -= amt; } else { Global::audio->playSound(Audio::LIFE_LOSE, pos); shield.damage(amt); } }