diff options
Diffstat (limited to 'game.cpp')
-rw-r--r-- | game.cpp | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/game.cpp b/game.cpp new file mode 100644 index 0000000..a2aa491 --- /dev/null +++ b/game.cpp @@ -0,0 +1,278 @@ +/********************************************************************* + * File: game.cpp + * Description: Contains the implementaiton of the game class + * methods. + * + *********************************************************************/ + +#include "game.h" +#include "uiDraw.h" +#include "bullet.h" +// These are needed for the getClosestDistance function... +#include <limits> +#include <iostream> +#include <algorithm> +#define CLOSE_ENOUGH 15 +using namespace std; + +// Game non-default constructor +Game :: Game ( const Point &tl , const Point &br ) : topLeft ( tl ) , bottomRight ( br ) +{ + rocks = createRocks(); + ship = new Ship ( Point() ); +} + +// Create rocks for the game +vector<Rock *> Game :: createRocks() +{ + vector<Rock *> initRocks; + for ( int i = 0; i < random ( 5 , 8 ); i++ ) + { + Point rockPoint = Point ( random( -190 , 190 ) , random ( -190 , 190 ) ); + Velocity velocity; + velocity.setDx ( random ( -3.0 , 3.0 ) ); + velocity.setDy ( random ( -2.0 , 2.0 ) ); + // Make sure spawn is safe on start by calculating if + // The rock is on a trajectory to the ship + float m = velocity.getDy() / velocity.getDx(); + + if ( fabs ( rockPoint.getY() - m * rockPoint.getX() ) >= 50 ) + { + switch ( random( 1 , 5 ) ) { + case 1: + case 2: + case 3: + initRocks.push_back ( new BigRock ( rockPoint , velocity ) ); + break; + case 4: + initRocks.push_back ( new MediumRock ( rockPoint , velocity ) ); + break; + case 5: + initRocks.push_back ( new SmallRock ( rockPoint , velocity ) ); + break; + default: + break; + } + } + } + return initRocks; +} + +// Get closest distance between two flying objects +float Game :: getClosestDistance(const FlyingObject &obj1, const FlyingObject &obj2) const +{ + // find the maximum distance traveled + float dMax = max(abs(obj1.getVelocity().getDx()), abs(obj1.getVelocity().getDy())); + dMax = max(dMax, abs(obj2.getVelocity().getDx())); + dMax = max(dMax, abs(obj2.getVelocity().getDy())); + dMax = max(dMax, 0.1f); // when dx and dy are 0.0. Go through the loop once. + + float distMin = std::numeric_limits<float>::max(); + for (float i = 0.0; i <= dMax; i++) + { + Point point1(obj1.getPoint().getX() + (obj1.getVelocity().getDx() * i / dMax), + obj1.getPoint().getY() + (obj1.getVelocity().getDy() * i / dMax)); + Point point2(obj2.getPoint().getX() + (obj2.getVelocity().getDx() * i / dMax), + obj2.getPoint().getY() + (obj2.getVelocity().getDy() * i / dMax)); + + float xDiff = point1.getX() - point2.getX(); + float yDiff = point1.getY() - point2.getY(); + + float distSquared = (xDiff * xDiff) +(yDiff * yDiff); + + distMin = min(distMin, distSquared); + } + + return sqrt(distMin); +} + +// Advance everything in the game +void Game :: advance() +{ + cleanUpZombies(); + advanceShip(); + advanceBullets(); + advanceAsteroids(); + + handleCollisions(); +} + +// Advance all asteroids in game +void Game :: advanceAsteroids() +{ + for ( int i = 0; i < rocks.size(); i++ ) + { + rocks[i]->advance(); + } +} + +// Advance all the bullets +void Game :: advanceBullets() +{ + for ( int i = 0; i < bullets.size(); i++ ) + { + bullets[i]->advance(); + } +} + +// Advance the ship +void Game :: advanceShip() +{ + if ( ship->isAlive() && ship->getFuel() >= 0 ) + { + ship->advance(); + } +} + +// Clean up memory +void Game :: cleanUpZombies() +{ + for ( int i = 0; i < bullets.size(); i++ ) + { + if ( !bullets[i]->isAlive() ) + { + delete bullets[i]; + bullets[i] = NULL; + bullets.erase( bullets.begin() + i ); + } + } + for ( int i = 0; i < rocks.size(); i++ ) + { + if ( !rocks[i]->isAlive() ) + { + delete rocks[i]; + rocks[i] = NULL; + rocks.erase( rocks.begin() + i ); + } + } +} + +// Handle all collisions +void Game :: handleCollisions() +{ + // Handle bullet collisions + for ( int i = 0; i < rocks.size(); i++ ) + { + Rock * rock = rocks[i]; + if ( rock->isAlive() ) + { + for ( int j = 0; j < bullets.size(); j++ ) + { + Bullet * bullet = bullets[j]; + if ( bullet->isAlive() ) + { + float allowedRange = rock->getSize() + CLOSE_ENOUGH; + if ( fabs( getClosestDistance( *bullet , *rock ) ) < allowedRange + || bullet->getPoint().inRange( rock->getPoint() , allowedRange ) ) + { + vector<Rock *> newRocks = rock->destroy(); + for ( int i = 0; i < newRocks.size(); i++ ) + { + rocks.push_back ( newRocks[i] ); + } + rock->kill(); + bullet->kill(); + } + } + } + } + } + + // Handle ship collisions + for ( int i = 0; i < rocks.size(); i++ ) + { + Rock * rock = rocks[i]; + if ( rock->isAlive() && ship->isAlive() ) + { + float allowedRange = rock->getSize() + CLOSE_ENOUGH; + if ( fabs( getClosestDistance( *ship , *rock ) ) < allowedRange + || ship->getPoint().inRange( rock->getPoint() , allowedRange ) ) + { + vector<Rock *> newRocks = rock->destroy(); + for ( int i = 0; i < newRocks.size(); i++ ) + { + rocks.push_back ( newRocks[i] ); + } + rock->kill(); + ship->kill(); + } + } + } + cleanUpZombies(); +} + +// Draw everything +void Game :: draw ( const Interface &ui ) +{ + drawRocks(); + drawShip(); + drawBullets(); + drawNumber ( Point ( -170 , 170 ) , (int) ship->getFuel() ); + drawText ( Point ( -170 , 180 ) , "FUEL:" ); +} + +// Draw rocks +void Game :: drawRocks() +{ + for ( int i = 0; i < rocks.size(); i++ ) + { + rocks[i]->draw(); + } +} + +// Draw ship +void Game :: drawShip() +{ + if ( ship->isAlive() ) + { + ship->draw(); + } +} + +// Draw bullets +void Game :: drawBullets() +{ + for ( int i = 0; i < bullets.size(); i++ ) + { + bullets[i]->draw(); + } +} + +// Handle in-game input +void Game::handleInput(const Interface & ui) +{ + if ( ship->isAlive() ) + { + if ( ui.isUp() ) + { + ship->setThrusting ( true ); + ship->thrust( true ); + } + if ( ui.isDown() ) + { + ship->setThrusting ( true ); + ship->thrust( false ); + } + if ( ui.isLeft() ) + { + ship->setThrusting ( true ); + ship->rotate( true ); + } + if ( ui.isRight() ) + { + ship->setThrusting ( true ); + ship->rotate( false ); + } + if ( ui.isSpace() ) + { + Bullet * newBullet = new Bullet( ship->getPoint() ); + newBullet->fire( ship->getVelocity(), ship->getAngle() ); + bullets.push_back( newBullet ); + } + if ( !ui.isRight() && !ui.isUp() && !ui.isDown() && !ui.isLeft() ) + { + ship->setThrusting ( false ); + } + } + +} |