Logo Search packages:      
Sourcecode: rafkill version File versions  Download package

game.cpp

#include <stdio.h>
#include "allegro.h"
#include "strings.h"

#include "trigtable.h"
#include "defs.h"
#include "game.h"
#include "level.h"
#include "spaceobj.h"
#include "explode.h"
#include "raptor.h"
#include "group.h"
#include "sound.h"
#include "pck.h"
#include "ebox.h"
#include "section.h"
#include <vector>
#include "hull_player.h"
#include "playerobj.h"
#include <aldumb.h>

#include <sys/time.h>

#define RADAR_X 100
#define RADAR_Y 80

using namespace std;

GameRunnable::GameRunnable( bool dl, DATAFILE * _snd, char * fl, SpaceObject * player ):
level_speech( 0 ),
DRAW_LAND( dl ) {

      // The datafile used for sound, probably should be global
      snd = _snd;

      // Boolean value to determine whether or not game should finish playing
      finished = false;

      blend_trans = 0;

      ((SAMPLE *)snd[ SND_SUSTAIN ].dat)->priority = 1;
      ((SAMPLE *)snd[ SND_HULL_COLLIDE ].dat)->priority = 2;

      // Make main bitmap larger than screen so that we have some buffer room to draw
      work = create_bitmap( screen_x, screen_y+Y_BLIT_OFFSET );
      //work = create_video_bitmap( screen_x, screen_y+Y_BLIT_OFFSET );
      if ( !work ) {
            printf("Supreme error with work\n");
            return;
      }
      clear( work );

      level = new LevelCreator( fl, player );

      expl = new ExplosionClass*[ MAX_EXPL ];
      for ( int q = 0; q < MAX_EXPL; q++ )
            expl[q] = NULL;

      land = NULL;
      if ( DRAW_LAND && !level->noExist() )
            LoadLand( land );

      // Counter to optimize explosion making
      last_explode = 0;

      delete_hold.clear();

      fsec_keep = 25;
      fsec = 0;

      set_trans_blender( 0, 0, 0, 168 );

      view_port = screen_x / 4;

      player_shade = new int[ 40 ];
      player_shade_color = 0;
      blend_palette( player_shade, 20, makecol(85,0,0), makecol(255,0,0) );
      blend_palette( player_shade+20, 20, makecol(255,0,0), makecol(85,0,0) );

      dumb_file = NULL;
      dumb_player = NULL;

      radar = create_bitmap( RADAR_X, RADAR_Y );
      clear_to_color( radar, makecol(10,40,10) );

}

/* LoadLand:
 * Loads a bitmap from a file to be the background.
 * .PCK is a special file format I made up myself. 
 * Look at pck.cpp for details
 */
void GameRunnable::LoadLand(RLE_SPRITE *& who) {

      pckLoader *p = new pckLoader();
      char * ff = "1.pck";
      switch ( rnd( 3 ) ) {
            case 0  :       ff = "1.pck";break;
            case 1  :       ff = "2.pck";break;
            case 2  :       ff = "3.pck";break;
      }

      /*
      land2 = p->load( ff );
      if ( !land2 ){
            DRAW_LAND = false;
            printf("Supreme error with background\n");
      }
      */

      BITMAP * ld = p->load( ff );
      if ( !ld ) {
            DRAW_LAND = FALSE;
            printf("Supreme error with land bitmap\n");
            delete p;
            return;
      }
      blit( ld, screen, 0, 0, 0, 0, GRAPHICS_X, GRAPHICS_Y );
      who = get_rle_sprite( ld );
      destroy_bitmap( ld );
      delete p;
}

/* draw_land:
 * Draws the background onto the main bitmap
 */
void GameRunnable::draw_land( int y1 ) {

      // clear( work );
      draw_rle_sprite( work, land, view_port, y1-GRAPHICS_Y+Y_BLIT_OFFSET );
      draw_rle_sprite( work, land, view_port, y1+Y_BLIT_OFFSET );

      /*
      printf("Drawing land\n");
      draw_sprite( work, land2, view_port, Y_BLIT_OFFSET );
      printf("Stage 1\n");
      unsigned char * temp_line = land2->line[ land2->h - 1 ];
      printf("Stage 2\n");
      for ( int q = 1; q < land2->h; q++ )
            land2->line[q] = land2->line[q-1];
      printf("Stage 3\n");
      land2->line[ 0 ] = temp_line;
      printf("Made it\n");
      */

}

/* HandleExplosion:
 * Move all the explosions and kill them if they should die
 */
void GameRunnable::HandleExplosion() {
      for ( int q = 0; q < MAX_EXPL; q++ )
            if( expl[q] != NULL )
            if ( expl[q]->update() ) {
                  delete expl[q];
            expl[q] = NULL;
      }
}

/* HandleSpace:
 * Move all the spaceobjects.
 * mv - objects to move
 * fight - objects that are considered mv's enemies
 * Ammo - list of objects that can be used to shoot ammo
 * onscreen - stores the coordinates of the object for fast collision detection reference
 */
void GameRunnable::HandleSpace( vector< SpaceObject * > * mv, vector< SpaceObject * > * fight, vector< SpaceObject * > * Ammo, Section * onscreen ) {

      for ( vector< SpaceObject * >::iterator it = mv->begin();
      it != mv->end(); ) {
            if ( (*it)->MoveMe( Ammo, fight, onscreen, snd ) ) {
                  SpaceObject * del = *it;
                  onscreen->dispose( *it );
                  it = mv->erase( it );
                  delete del;
            } else ++it;
      }
}

/* CheckCollision:
 * Reason this game exists. Loop through both lists of enemies and check
 * to see if each object collides using ebox for collision detection.
 */
void GameRunnable::CheckCollision( Section * good, Section * fight, SpaceObject * take, int sound, int vol ) {

      // Reset section lists. Look at section.cpp to see why this is important
      good->reset();
      fight->reset();

      vector< SpaceObject * > * good_space = good->getNext();
      vector< SpaceObject * > * fight_space = fight->getNext();

      while ( good_space != NULL && fight_space != NULL ) {

            // Loop through good objects first
            for ( vector< SpaceObject * >::iterator good_it = good_space->begin();
            good_it != good_space->end(); good_it++ ) {

                  // Loop through bad objects next
                  for ( vector< SpaceObject * >::iterator fight_it = fight_space->begin();
                  fight_it != fight_space->end(); fight_it++ ) {

                        SpaceObject * g_use = *good_it;
                        SpaceObject * f_use = *fight_it;

                        // First test to see if badobject life is less than 0
                        // and if good object has already collided with bad object
                        if ( f_use->getLife() > 0 && !g_use->haveCollide( f_use ) )
                        if ( g_use->Collide( f_use ) ) {
                              play_sound( snd, sound, vol );

                              if ( g_use->Damage( f_use->Hurt() ) )
                                    g_use->Died(take,expl,MAX_EXPL,snd);
                              if ( f_use->Damage( g_use->Hurt() ) )
                                    f_use->Died(take,expl,MAX_EXPL,snd);

                              // Let both objects know they collided with something
                              g_use->Collided( f_use, expl, MAX_EXPL );
                              f_use->Collided( g_use, expl, MAX_EXPL );

                              //g_use->addCollide( f_use );
                              //f_use->addCollide( g_use );
                        }             //if

                  }                   //for fight

            }                         //for good

            good_space = good->getNext();
            fight_space = fight->getNext();

      }                               //while

}

/* drawAll:
 * Draws all the objects passed to it, the background, and some player specific things
 */
void GameRunnable::drawAll( int Land_count, vector< SpaceObject * > * draws , SpaceObject * player ) {

      //struct timeval * start, * end;
      //start = new timeval;
      //end = new timeval;

      if ( view_port < 0 ) view_port = 0;
      if ( view_port > screen_x - GRAPHICS_X ) view_port = screen_x - GRAPHICS_X;

      // Some crazy people from allegro said you should do this
      // cuase windows directX blows and might mess up if you dont.
      acquire_bitmap( work );

      //printf("Stage 1\n");
      //gettimeofday( start, NULL );
      
      // Either draw the background or clear it
      if ( DRAW_LAND )
            draw_land(Land_count%480);
      else
            rectfill( work, view_port, Y_BLIT_OFFSET, view_port+GRAPHICS_X, GRAPHICS_Y+Y_BLIT_OFFSET, makecol(0,0,0) );

      //gettimeofday( end, NULL );
      //printf("Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

      //printf("Stage 2\n");
      //gettimeofday( start, NULL );
      if ( player != NULL ) {

            // Draw a fancy translucent red bar at the top and bottom of the screen
            // if the players life is below 30. 
            if ( player->getLife() < 30 ) {
                  rectfill( work, view_port, 0+Y_BLIT_OFFSET, view_port+GRAPHICS_X-1, 10+Y_BLIT_OFFSET, player_shade[player_shade_color] );
                  rectfill( work, view_port, GRAPHICS_Y-10+Y_BLIT_OFFSET, view_port+GRAPHICS_X-1, GRAPHICS_Y-1+Y_BLIT_OFFSET, player_shade[player_shade_color] );
                  if ( ++player_shade_color > 39 ) player_shade_color = 0;
            }

            // Show the player's score at the bottom left of the screen
            int score = player->getScore();
            char * numnum = int2normal(score);
            char * final = append("Score ",numnum);
            raptor_font->rtext(work,view_port+11,GRAPHICS_Y-raptor_font->height()+Y_BLIT_OFFSET,makecol(255,128,0),final);
            free( numnum );
            free( final );

      }
      //gettimeofday( end, NULL );
      //printf("Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

      // Helps to sort the objects being drawn becuase we have to draw them twice
      vector< SpaceObject * > draw_real;

      /*
      for ( int q = 0; q <= MAX_PLANE; q++ )
            for ( vector< SpaceObject *>::iterator it = draws->begin();
                        it != draws->end(); it++ )
                  if ( (*it)->lookPlane() == q )
                        (*it)->Shadow( work, data,q,Y_BLIT_OFFSET);
      */

      //printf("Stage 3\n");
      //gettimeofday( start, NULL );
      
      // Draw all the object's shadow according to their vertical level 
      // which is given by spaceobject->lookPlane(). 
      for ( int q = 0; q <= MAX_PLANE; q++ )
            for ( vector< SpaceObject *>::iterator it = draws->begin();
      it != draws->end(); ) {
            if ( (*it)->lookPlane() == q ) {
                  (*it)->Shadow( work, q,Y_BLIT_OFFSET);
                  draw_real.push_back( *it );
                  it = draws->erase( it );
            } else ++it;
      }
      //gettimeofday( end, NULL );
      //printf("Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

      //printf("Stage 4\n");
      //gettimeofday( start, NULL );
      
      // Objects are already in sorted order by plane becuase of shadow routine.
      // Draw all objects and their radar.
      for ( vector< SpaceObject *>::iterator it = draw_real.begin(); it != draw_real.end(); it++ ) {
            (*it)->Draw( work, expl,MAX_EXPL,(*it)->lookPlane(),Y_BLIT_OFFSET);
            (*it)->Radar( radar );
      }
      //gettimeofday( end, NULL );
      //printf("Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

      /*
      for ( int q = 0; q <= MAX_PLANE; q++ )
            for ( vector< SpaceObject *>::iterator it = draw_real.begin();
                        it != draw_real.end(); ){
                  if ( (*it)->lookPlane() == q ){
                        (*it)->Draw( work, data, expl,MAX_EXPL,q,Y_BLIT_OFFSET);
                        it = draw_real.erase( it );
                  } else ++it;
            }
      */

      //printf("Stage 5\n");
      //gettimeofday( start, NULL );
      
      // Draw all the explosions.
      for ( int q = 0; q < MAX_EXPL; q++ ) {
            if ( expl[q] != NULL )
                  expl[q]->Draw( work, Y_BLIT_OFFSET );
            //if ( npeed_counter != 0 ) q = MAX_EXPL;
      }
      //gettimeofday( end, NULL );
      //printf("Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

      //textprintf( work, font, 10 + view_port, 1+Y_BLIT_OFFSET, makecol(255,255,255), "FPS:%d", fsec_keep );
      //textprintf( work, font, 10 + view_port, 10+Y_BLIT_OFFSET, makecol(255,255,255), "VERSION: 1.0.0" );
      if ( time(NULL) != timex ) {
            fsec_keep = fsec;
            fsec = 0;
            timex = time(NULL);
      }

      // Draw a sine wave of "level #" in spiffy colors
      if ( player != NULL ) level_use = ( (PlayerObject *)player )->level;
      if ( level_speech < 120 ) {

            int * speech = new int[ 30 ];
            blend_palette( speech, 10, makecol( 255, 0, 120 ), makecol(150,220,20) );
            blend_palette( speech+10, 10, makecol(150, 220, 20), makecol(20,160,255) );
            blend_palette( speech+10+10, 10, makecol(20,160,255), makecol(255,0,120) );

            level_speech++;
            char * lose = int2str( level_use );
            char * dum = append("level ",lose);
            int vx = 300;
            int vy = 200;
            for ( int q = 0; q < length( dum ); q++ ) {
                  int sy = (int)(vy + tsine[((level_speech+q*2)*12)%360]*8 );
                  int sx = vx + q * 10;
                  int col = 32 + ((level_speech+q*2)%20);
                  col = speech[ (level_speech+q) % 30 ];
                  textprintf( work, font, sx+view_port, sy+Y_BLIT_OFFSET, col, "%c", dum[q] );
            }
            free( dum );
            free( lose );
            delete[] speech;
      }

      // Show the player's health and shield on the sides of the screen
      if ( player != NULL ) {
            PlayerHull * ph = (PlayerHull *)(player->getHull());
            ph->showAttribute( work, (int)ph->life, (int)ph->getMaxLife(), view_port+GRAPHICS_X-10, Y_BLIT_OFFSET );
            ph->showAttribute( work, (int)ph->getShield(), (int)ph->getMaxShield(), view_port+1, Y_BLIT_OFFSET );
      }

      if ( finished ) {

            //draw_trans_sprite( work, blend_bright, 0, 0 );

      }

      //printf("Stage 6\n");
      //gettimeofday( start, NULL );

      // Draw all the important things
      draw_trans_sprite( work, radar, view_port, Y_BLIT_OFFSET );
      clear_to_color( radar, makecol(10,60,30) );
      rect( radar, 0, 0, RADAR_X-1, RADAR_Y-1, makecol(200,200,200) );
      acquire_screen();
      blit( work, screen, view_port, Y_BLIT_OFFSET, 0, 0, GRAPHICS_X, GRAPHICS_Y );
      //blit( work, screen, 0, Y_BLIT_OFFSET, 0, 0, screen_x, screen_y );
      //show_video_bitmap( work );
      //request_video_bitmap( work );
      release_screen();

      //gettimeofday( end, NULL );
      //printf("Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

      //printf("Stage 7\n");
      //gettimeofday( start, NULL );

      release_bitmap( work );
      //gettimeofday( end, NULL );
      //printf("Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

      //delete start;
      //delete end;

}


bool GameRunnable::end_level( vector< SpaceObject * > * PlayerTemp, double Land_real, double Land_speed ) {
      return true;
}


/* DeleteSpace
 * Erases an object from a list if its life is less than 0. Takes the object
 * out of the section it is currently in and out of the vector that contains it.
 * If it can become a powerup, there is a chance a new powerup will be pushed onto the
 * same list it came off of.
 */
void GameRunnable::DeleteSpace( vector< SpaceObject *> * objs, Section * sec, SpaceObject * _player ) {

      // extra vector to store special objects
      vector< SpaceObject * > objs_special;
      
      for ( vector< SpaceObject * >::iterator it = objs->begin();
      it != objs->end(); ) {

            if ( (*it)->getLife() <= 0 ) {

                  //printf("D: %p from %p\n", *it, objs );

                  sec->dispose( *it );

                  // If object can become a powerup, it may in fact do so
                  // Can only become a powerup if it was the last in its group
                  // which is known when group->size() is 1.
                  if ( (*it)->powerUp() ) {
                        if ( (*it)->getGroup() != NULL ) {
                              if ( (*it)->getGroup()->size() == 1 ){
                                    if ( rnd(3)  ) {
                                          int x = (*it)->getX();
                                          int y = (*it)->getY();

                                          // The following line used to cuase a bug
                                          // objs->push_back( level->special(x,y,_player) );

                                          objs_special.push_back( level->special(x,y,_player) );
                                    }
                              }
                        }
                  }

                  SpaceObject * del = *it;
                  it = objs->erase( it );
                  delete del;

                  // Dont delete the object becuase I think the program will crash if we do
                  // Instead, store the object in a list that will delete it later.
                  // delete_hold.push_back( del );

            } else ++it;

      }

      vectorAdd( objs, &objs_special );

}


void GameRunnable::DeleteAll( vector< SpaceObject * > * objs ) {

      /*
      for ( vector<SpaceObject *>::iterator it = objs->begin();
      it != objs->end(); ) {
            //SpaceObject * del = *it;
            //it = objs->erase( it );
            //delete del;
            delete_hold.push_back( *it );
            it = objs->erase( it );
      }
      */
      vectorAdd( &delete_hold, objs );

}

/* vectorAdd:
 * Adds all the elements from one vector of type SpaceObject * to another.
 */
void GameRunnable::vectorAdd( vector< SpaceObject * > * stable, vector< SpaceObject * > * state ) {

      for ( vector< SpaceObject * >::iterator it = state->begin();
            it != state->end(); it++ )
      stable->push_back( *it );

}

/* clearCollide:
 * Clears each objects collision list. During collision detection, each object
 * remembers what objects it collided with.
 */
void GameRunnable::clearCollide( vector< SpaceObject * > * contain ) {

      for ( vector< SpaceObject * >::iterator it = contain->begin();
      it != contain->end(); it++ ) {
            (*it)->clearCollide();
      }

}

/* load_music:
 * Loads one of the songs to play during the game.
 */
DUH * GameRunnable::load_music() {

      char * music_file = NULL;
      DUH * who = NULL;
      switch( rnd( 4 ) ) {
            case 0  :       music_file = data_file( "song1.xm" );break;
            case 1  :       music_file = data_file( "song2.xm" );break;
            case 2  :       music_file = data_file( "song3.xm" );break;
            case 3  :       music_file = data_file( "song4.xm" );break;
      }
      who = dumb_load_xm( music_file );
      free( music_file );

      return who;

}

/* RunGame:
 * Main game loop. Too complicated to give a detailed description here
 */
int GameRunnable::RunGame( SpaceObject * player, int lev ) {

      // If level says we should quit, then we should do so
      if ( level->noExist() )
            return 2;

      // Normal game FPS will be about 25
      fsec = 25;

      int Land_count = 0;
      double Land_speed = 2.7;
      double Land_real = Land_count;

      bool quit = false;
      int return_code = 0;

      timex = time(NULL);

      // Set up all object lists for game
      vector< SpaceObject * > * GoodAmmo = new vector< SpaceObject * >;
      vector< SpaceObject * > * BadAmmo = new vector< SpaceObject * >;
      vector< SpaceObject * > * PlayerTemp = new vector< SpaceObject * >;
      vector< SpaceObject * > * Monster = new vector< SpaceObject * >;

      Section * player_section = new Section();
      Section * monster_section = new Section();
      Section * goodammo_section = new Section();
      Section * badammo_section = new Section();

      int score = player->getScore();
      // Player is the only object in PlayerTemp, but PlayerTemp is useful to have
      // for homogeniousity( sp? )
      PlayerTemp->push_back( player );

      // Make a copy of the player hull in case he dies. If he dies during the game,
      // his hull is replaced with the original copy so that any new powerups are not gained
      // even after death.
      HullObject * reserve = player->getHull()->copy();

      // Dont need this structures, only used for debugging purposes.
      //struct timeval * start, * end;
      //start = new timeval;
      //end = new timeval;

      //DUH * dumb_file = NULL;
      //AL_DUH_PLAYER * dumb_player = NULL;
      
      // Dont load music if music is set to 0. Otherwise, dance away!
      if ( music_vol != 0.0 ) {
            dumb_file = load_music();
            dumb_player = al_start_duh( dumb_file, 2, 0, music_vol, 4096, 22050 );
      }

      #define SCROLL_VIEW 210

      // Make sure game doesnt start running game loops without the player knowing
      speed_counter = 0;

      while ( !quit ) {

            // Allow user to change the background if they dont like the current one
            if ( key[KEY_L] ) {
                  if ( DRAW_LAND )
                        LoadLand( land );
                  while ( key[KEY_L] ){
                        YIELD();
                        if ( dumb_file != NULL )
                              al_poll_duh( dumb_player );

                  }
                  speed_counter = 0;
            }

            // Quit!
            if ( key[KEY_ESC] ) {
                  return_code = 4;
                  quit = true;
            }

            //if ( key[KEY_R] ) quit = true;

            //puasy puasy
            if ( key[KEY_P] ) {
                  BITMAP * pause = create_bitmap( screen_x, screen_y );
                  clear( pause );
                  set_trans_blender( 0, 0, 0, 128 );
                  draw_trans_sprite( screen, pause, 0, 0 );
                  raptor_font->rtext(screen,200,200,makecol(255,50,10),"Paused");
                  while ( key[KEY_P] ) {
                        YIELD();
                        if ( dumb_file != NULL )
                              al_poll_duh( dumb_player );
                  }
                  /*
                  while ( !key[KEY_P] ){
                        YIELD();
                        if ( dumb_file != NULL )
                              al_poll_duh( dumb_player );
                  }
                  */

                  while ( !key[KEY_P] ) {
                        YIELD();
                        if ( dumb_file != NULL )
                              al_poll_duh( dumb_player );
                  }
                  while ( key[KEY_P] ) {
                        YIELD();
                        if ( dumb_file != NULL )
                              al_poll_duh( dumb_player );
                  }
                  set_trans_blender( 0, 0, 0, 168 );
                  destroy_bitmap( pause );
                  speed_counter = 0;
            }

            // Play the music
            if ( dumb_file != NULL )
                  al_poll_duh( dumb_player );

            bool did_something = false; // Set to true if game logic has run
            int max_loop = 0; // Enforce max loops that game logic can run
            while ( speed_counter > 0 && max_loop < 3 ) {
                  max_loop++;

                  did_something = true;

                  if ( finished && !quit )
                        quit = end_level( PlayerTemp, Land_real, Land_speed );

                  // If level is done making monsters, game should end when monster list is empty
                  if ( !finished && level->done() ) {
                        finished = Monster->empty();
                  }

                  // Create more monsters
                  level->create( Monster, lev, Land_real );
                  //if ( player->getLife() < 30 )
                  //    level->emergency( Monster );

                  HandleExplosion();        //this has to go here

                  for ( int z = 0; z < USE_AMMO; z++ ) {

                        // If player's life is 0 or less, hes dead!
                        // Run the game for a few more animations cuase it looks neato
                        if ( player->getLife() <= 0 ) {

                              speed_counter = 0;
                              for ( int play = 0; play < 60; ) {

                                    if ( dumb_file != NULL )
                                          al_poll_duh( dumb_player );

                                    bool get_dirty = false;
                                    max_loop = 0;
                                    while ( speed_counter > 0 && max_loop < 3 ) {
                                          max_loop++;
                                          play++;
                                          get_dirty = true;
                                          //this has to go here
                                          HandleExplosion();
                                          for ( int ma = 0; ma < USE_AMMO; ma++ ) {

                                                goodammo_section->clear();
                                                badammo_section->clear();

                                                HandleSpace(GoodAmmo,Monster,GoodAmmo,goodammo_section);
                                                HandleSpace(BadAmmo,PlayerTemp,BadAmmo,badammo_section);

                                                CheckCollision(goodammo_section,monster_section,player,SND_SUSTAIN,50);

                                                DeleteSpace(GoodAmmo,goodammo_section,NULL);
                                                DeleteSpace(BadAmmo,badammo_section,NULL);
                                                DeleteSpace(Monster,monster_section,player);

                                          }

                                          monster_section->clear();

                                          HandleSpace(Monster,PlayerTemp,BadAmmo,monster_section);

                                          DeleteSpace(Monster,monster_section,player);

                                          speed_counter--;
                                    }

                                    if ( get_dirty ) {
                                          fsec++;
                                          Land_real += Land_speed;
                                          if ( Land_real > 480 )
                                                Land_real -= 480;
                                          Land_count = (int)( Land_real + 1 ) % 480;

                                          if ( player->getX() < view_port + SCROLL_VIEW )
                                                view_port = player->getX() - SCROLL_VIEW;
                                          if ( player->getX() > view_port + GRAPHICS_X - SCROLL_VIEW )
                                                view_port += player->getX() - ( view_port + GRAPHICS_X - SCROLL_VIEW );

                                          vector< SpaceObject * > * draws = new vector< SpaceObject * >();

                                          vectorAdd( draws, GoodAmmo );
                                          vectorAdd( draws, BadAmmo );
                                          vectorAdd( draws, Monster );
                                          drawAll( Land_count, draws, NULL );

                                          delete draws;
                                    }

                                    if ( speed_counter == 0 ) YIELD();

                              }       //for

                              //player->score -= 20000 * lev * 2 / 5;

                              PlayerTemp->clear();
                              speed_counter = 0;
                              z = USE_AMMO;
                              return_code = 1;
                              quit = true;
                        }             //if

                        // Clear sections lists.
                        goodammo_section->clear();
                        badammo_section->clear();

                        // Move good and bad ammo
                        HandleSpace(GoodAmmo,Monster,GoodAmmo,goodammo_section);
                        HandleSpace(BadAmmo,PlayerTemp,BadAmmo,badammo_section);

                        // Clear object collision lists
                        clearCollide( GoodAmmo );
                        clearCollide( BadAmmo );
                        clearCollide( Monster );
                        clearCollide( PlayerTemp );

                        // Check to see if good ammo hit enemies and bad ammo hit player
                        CheckCollision(badammo_section,player_section,player,SND_SUSTAIN,50);
                        CheckCollision(goodammo_section,monster_section,player,SND_SUSTAIN,50);

                        // Delete objects that have less than 0 life
                        DeleteSpace(GoodAmmo,goodammo_section,NULL);
                        DeleteSpace(BadAmmo,badammo_section,NULL);
                        DeleteSpace(Monster,monster_section,player);

                  }                   //for USE_AMMO

                  player_section->clear();
                  monster_section->clear();

                  HandleSpace(PlayerTemp,Monster,GoodAmmo,player_section);
                  HandleSpace(Monster,PlayerTemp,BadAmmo,monster_section);

                  clearCollide( PlayerTemp );
                  clearCollide( Monster );

                  CheckCollision(monster_section,player_section,player,SND_HULL_COLLIDE,50);
                  DeleteSpace(Monster,monster_section,player);

                  speed_counter--;
            }

            // If game logic has run, draw everything
            if ( did_something && !quit ) {
                  fsec++;
                  Land_real += Land_speed;
                  if ( Land_real > 480 )
                        Land_real -= 480;
                  Land_count = (int)( Land_real ) % 480;

                  // Viewport allows the screen to be larger than 640. 
                  // Only show from viewport to viewport+640
                  if ( player->getX() < view_port + SCROLL_VIEW )
                        view_port = player->getX() - SCROLL_VIEW;
                  if ( player->getX() > view_port + GRAPHICS_X - SCROLL_VIEW )
                        view_port += player->getX() - ( view_port + GRAPHICS_X - SCROLL_VIEW );
                  /*
                  if ( player->actualx > last_view ){

                        int md = (player->actualx - last_view) / 2;

                        //last_view++;
                        //view_port++;
                        last_view += md;
                        view_port += md;
                  }
                  if ( player->actualx < last_view ){
                  last_view--;
                  view_port--;
                  }
                  */
                  /*
                  int md = (player->actualx - last_view ) / 4;
                  last_view += md;
                  view_port += md;
                  */

                  // Combine all objects into one giant list
                  vector< SpaceObject * >* draws = new vector< SpaceObject * >();
                  vectorAdd( draws, GoodAmmo );
                  vectorAdd( draws, BadAmmo );
                  vectorAdd( draws, Monster );
                  vectorAdd( draws, PlayerTemp );

                  //gettimeofday( start, NULL );
                  drawAll( Land_count, draws, player );
                  //gettimeofday( end, NULL );
                  //printf("Total Time to draw = %0.1f\n", (double)(end->tv_usec - start->tv_usec) );

                  delete draws;
            }

            if ( speed_counter == 0 )YIELD();
            if ( speed_counter > 1 ) speed_counter = 1;

            //while ( speed_counter == 0 )yield_timeslice();

      }

      //delete start;
      //delete end;

      DeleteAll( Monster );
      DeleteAll( GoodAmmo );
      DeleteAll( BadAmmo );

      delete GoodAmmo;
      delete BadAmmo;
      delete Monster;
      delete PlayerTemp;

      delete goodammo_section;
      delete badammo_section;
      delete player_section;
      delete monster_section;

      // If player died, give old score and hull back
      if ( return_code != 0 ) {
            player->giveHull( reserve );
            player->setScore( score );
            // player->score = score;
      } else delete reserve;

      // Have we deleted everything!!?!? Probably not,. memory leak city!

      return return_code;

}


GameRunnable::~GameRunnable() {

      destroy_rle_sprite( land );

      // Fade screen
      if ( !level->noExist() ) {
            BITMAP * fade_work = create_bitmap( GRAPHICS_X, GRAPHICS_Y );
            clear( fade_work );

            float mv = music_vol;
            blit( screen, work, 0, 0, 0, 0, GRAPHICS_X, GRAPHICS_Y );
            for ( int fade = 0; fade < 20; ) {
                  if ( mv > 0 ) mv -= 0.1;
                  al_duh_set_volume( dumb_player, mv );
                  fade += speed_counter;
                  if ( dumb_file != NULL )
                        al_poll_duh( dumb_player );
                  while ( speed_counter == 0 ) {
                        YIELD();
                        if ( dumb_file != NULL )
                              al_poll_duh( dumb_player );
                  }
                  if ( fade > 127 ) fade = 127;
                  set_trans_blender( 0, 0, 0, fade );
                  draw_trans_sprite( work, fade_work, 0, 0 );
                  blit( work, screen, 0, 0, 0, 0, 640, 480 );
            }
            set_trans_blender(0,0,0,255);
            draw_trans_sprite(screen,fade_work,0,0);
            destroy_bitmap( fade_work );
      }

      if ( dumb_file != NULL ) {
            al_stop_duh( dumb_player );
            unload_duh( dumb_file );
      }

      destroy_bitmap( work );
      destroy_bitmap( radar );

      // Finally delete all the objects that were supposed to be killed in the deleteSpace routine
      // If anything, the crash should occur here.
      printf("Deleting %d objects\n", delete_hold.size() );
      for ( vector< SpaceObject * >::iterator it = delete_hold.begin(); it != delete_hold.end(); ){
            //printf("%p\n", *it );
            //++it;
            /*
            for ( vector< SpaceObject * >::iterator sit = delete_hold.begin(); sit != delete_hold.end(); ++sit )
                  if ( *sit == *it && sit != it )
                        printf("%p == %p at it = %p\n", *it, *sit, it );
                        */
            SpaceObject * del = *it;
            it = delete_hold.erase( it );
            delete del;
      }

      if ( level )
            delete level;
      for ( int q = 0; q < MAX_EXPL; q++ )
            if ( expl[q] != NULL )
                  delete expl[q];
      delete[] expl;
      delete[] player_shade;

}

Generated by  Doxygen 1.6.0   Back to index