////////////////////////////////////////////////////////////////////// // XLogical - A puzzle game // // Copyright (C) 2000 Neil Brown, Tom Warkentin // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // or at the website: http://www.gnu.org // //////////////////////////////////////////////////////////////////////// #include // Application Includes #include "audio.h" #include "properties.h" #include "tiles.h" #include "graph.h" #include "gamelogic.h" #include "sound_files.h" //#define DEBUG_FUNC Ctile_track::Ctile_track( ) { #ifdef DEBUG_FUNC cerr << __FILE__ << " Ctile_track::constructor( )" << endl; #endif } Ctile_track::Ctile_track( unsigned long flags ) { #ifdef DEBUG_FUNC cerr << __FILE__ << " Ctile_track::constructor( long )" << endl; #endif exitFlags |= flags; } Ctile_track::~Ctile_track( ) { #ifdef DEBUG_FUNC cerr << __FILE__ << " Ctile_track::destructor( )" << endl; #endif } void Ctile_track::move_balls( void ) { #ifdef DEBUG_FUNC cerr << __FILE__ << " Ctile_track::move_balls( )" << endl; #endif list< Cball * >::iterator it; // Bail if there are no balls here if( balls.empty( ) ) { return; } it = balls.begin( ); while( it != balls.end( ) ) { // Clear the no move flag if it's set if( (*it)->check_no_move( ) ) { (*it)->clear_no_move( ); it++; } else { if( move_a_ball( **it ) == 1 ) { // We got an erase return value delete *it; it = balls.erase( it ); } else { // Move on it++; } } } } int Ctile_track::move_a_ball( Cball &b ) { #ifdef DEBUG_FUNC cerr << __FILE__ << " Ctile_track::move_a_ball( )" << endl; #endif float xcoord = 0; float ycoord = 0; float offset = 0; int passed = 0; dir_t dir = UP; int halfTile = CURMAP->tileSize / 2; // Get the direction the ball is moving in dir = b.get_direction( ); // Get the ball's coordinates b.get_coordinates( &xcoord, &ycoord); // Find out if the ball is going to cross the mid point of // the tile. switch( dir ) { case UP: if( (ycoord <= halfTile) && b.doMidPoint) { b.doMidPoint = false; offset = check_move_up( b, xcoord, ycoord ); } else { // Keep going UP ycoord = ycoord - CURMAP->ballSpd; if (ycoord > CURMAP->tileSize) ycoord = CURMAP->tileSize - 1; offset = ycoord; } break; case DOWN: if( (ycoord >= halfTile) && b.doMidPoint) { b.doMidPoint = false; offset = check_move_down( b, xcoord, ycoord ); } else { // Keep going DOWN ycoord = ycoord + CURMAP->ballSpd; if (ycoord < 0) ycoord = 0; offset = ycoord - CURMAP->tileSize; } break; case LEFT: if( (xcoord <= halfTile) && b.doMidPoint) { b.doMidPoint = false; offset = check_move_left( b, xcoord, ycoord ); } else { // Keep going left xcoord = xcoord - CURMAP->ballSpd; if (xcoord > CURMAP->tileSize) xcoord = CURMAP->tileSize - 1; offset = xcoord; } break; case RIGHT: if( (xcoord >= halfTile) && b.doMidPoint) { b.doMidPoint = false; offset = check_move_right( b, xcoord, ycoord ); } else { // Keep going right xcoord = xcoord + CURMAP->ballSpd; if (xcoord < 0) xcoord = 0; offset = xcoord - CURMAP->tileSize; } break; default: break; } // See if we're out of bounds if( ( xcoord < 0 ) || ( xcoord > CURMAP->tileSize - 1 ) || ( ycoord < 0 ) || ( ycoord > CURMAP->tileSize - 1 ) ) { // Time to pass the ball to the next tile passed = pass_ball( &b, dir, (int)offset ); // Uh oh - it bounced back if( ! passed ) { audioDriver->play_sound( soundFiles[SOUND_BLOCK_BALL] ); switch( dir ) { case UP: b.doMidPoint = true; b.set_direction( DOWN ); b.set_coordinates( xcoord, offset); break; case DOWN: b.doMidPoint = true; b.set_direction( UP ); b.set_coordinates( xcoord, CURMAP->tileSize - offset); break; case LEFT: b.doMidPoint = true; b.set_direction( RIGHT ); b.set_coordinates( offset, ycoord); break; case RIGHT: b.doMidPoint = true; b.set_direction( LEFT ); b.set_coordinates( CURMAP->tileSize - offset, ycoord); break; default: break; } } } else { // Keep moving as we were b.set_coordinates( xcoord, ycoord); } // Do some more range checking now if( ycoord < 0 ) { b.set_coordinates( xcoord, 0); } if( xcoord < 0 ) { b.set_coordinates( 0, ycoord); } if( ycoord > CURMAP->tileSize ) { b.set_coordinates( xcoord, CURMAP->tileSize); } if( xcoord > CURMAP->tileSize ) { b.set_coordinates( CURMAP->tileSize, ycoord); } return( passed ); } float Ctile_track::check_move_up( Cball &b, float &xcoord, float &ycoord ) { float overShoot = 0; float offset = 0; int halfTile = CURMAP->tileSize / 2; // Ball will cross the midpoint this iteration overShoot = fabs( ycoord - CURMAP->ballSpd - halfTile ); // Is there an exit LEFT that's not a blocked spinner? if( check_available_spinner( EXIT_LEFT ) ) { // Yep, let's go left b.set_direction( LEFT ); xcoord = halfTile - overShoot; ycoord = halfTile; return( 0 ); } // Is there an exit RIGHT that's not a blocked spinner? if( check_available_spinner( EXIT_RIGHT ) ) { b.set_direction( RIGHT ); xcoord = halfTile + overShoot; ycoord = halfTile; return( 0 ); } // Can we still go up?? if( exitFlags & EXIT_UP ) { // Yep - keep moving up b.set_direction( UP ); ycoord = ycoord - CURMAP->ballSpd; offset = ycoord; return( offset ); } // No way to go up, left, or right - better turn around audioDriver->play_sound( soundFiles[SOUND_BLOCK_BALL] ); b.set_direction( DOWN ); b.doMidPoint = true; xcoord = halfTile; ycoord = halfTile + overShoot; return( 0 ); } float Ctile_track::check_move_down( Cball &b, float &xcoord, float &ycoord ) { float overShoot = 0; float offset = 0; int halfTile = CURMAP->tileSize / 2; // Ball will cross the midpoint this iteration overShoot = fabs( ycoord + CURMAP->ballSpd - halfTile ); // Is there an exit RIGHT that's not a blocked spinner? if( check_available_spinner( EXIT_RIGHT ) ) { b.set_direction( RIGHT ); xcoord = halfTile + overShoot; ycoord = halfTile; return( 0 ); } // Is there an exit LEFT that's not a blocked spinner? if( check_available_spinner( EXIT_LEFT ) ) { // Yep, let's go left b.set_direction( LEFT ); xcoord = halfTile - overShoot; ycoord = halfTile; return( 0 ); } // Is there an exit down? if( exitFlags & EXIT_DOWN ) { // Yep - keep moving down b.set_direction( DOWN ); ycoord = ycoord + CURMAP->ballSpd; offset = ycoord; return( offset ); } // No way to go up, left, or right - better turn around audioDriver->play_sound( soundFiles[SOUND_BLOCK_BALL] ); b.set_direction( UP ); b.doMidPoint = true; xcoord = halfTile; ycoord = halfTile - overShoot; return( 0 ); } float Ctile_track::check_move_left( Cball &b, float &xcoord, float &ycoord ) { float overShoot = 0; float offset = 0; int halfTile = CURMAP->tileSize / 2; // Ball will cross the midpoint this iteration overShoot = fabs( ycoord - CURMAP->ballSpd - halfTile ); // Is there an exit DOWN that's not a blocked spinner? if( check_available_spinner( EXIT_DOWN ) ) { // Yep, let's go left b.set_direction( DOWN ); xcoord = halfTile; ycoord = halfTile + overShoot; return( 0 ); } // Is there an exit UP that's not a blocked spinner? if( check_available_spinner( EXIT_UP ) ) { b.set_direction( UP ); xcoord = halfTile; ycoord = halfTile - overShoot; return( 0 ); } // Is there an exit LEFT if( exitFlags & EXIT_LEFT ) { // Yep - keep moving Left b.set_direction( LEFT ); xcoord = xcoord - CURMAP->ballSpd; offset = xcoord; return( offset ); } // No way to go down left, or down - better turn around audioDriver->play_sound( soundFiles[SOUND_BLOCK_BALL] ); b.set_direction( RIGHT ); b.doMidPoint = true; xcoord = halfTile + overShoot; ycoord = halfTile; return( 0 ); } float Ctile_track::check_move_right( Cball &b, float &xcoord, float &ycoord ) { float overShoot = 0; float offset = 0; int halfTile = CURMAP->tileSize / 2; // Ball will cross the midpoint this iteration overShoot = fabs( xcoord + CURMAP->ballSpd - halfTile ); // Is there an exit UP that's not a blocked spinner? if( check_available_spinner( EXIT_UP ) ) { b.set_direction( UP ); xcoord = halfTile; ycoord = halfTile - overShoot; return( 0 ); } // Is there an exit DOWN that's not a blocked spinner? if( check_available_spinner( EXIT_DOWN ) ) { // Yep, let's go left b.set_direction( DOWN ); xcoord = halfTile; ycoord = halfTile + overShoot; return( 0 ); } // Can we go right at all? if( exitFlags & EXIT_RIGHT ) { // Yep - keep moving Right xcoord = xcoord + CURMAP->ballSpd; offset = xcoord; return( offset ); } // No way to go down right, or up - better turn around audioDriver->play_sound( soundFiles[SOUND_BLOCK_BALL] ); b.set_direction( LEFT ); b.doMidPoint = true; xcoord = halfTile - overShoot; ycoord = halfTile; return( 0 ); } void Ctile_track::draw_under( int ulX, int ulY ) { #ifdef DEBUG_FUNC1 cerr << __FILE__ << " Ctile_track::draw_under( "; cerr << ulX << ", " << ulY << " )" << endl; #endif // Draw the start track stuff draw_start_background( ulX, ulY ); draw_exit_tracks( ulX, ulY ); } void Ctile_track::draw_balls( int ulX, int ulY ) { simple_draw_balls( ulX, ulY ); } void Ctile_track::draw_over( int ulX, int ulY ) { #ifdef DEBUG_FUNC1 cerr << __FILE__ << " Ctile_track::draw_over( "; cerr << ulX << ", " << ulY << " )" << endl; #endif } // $Id: tile_track.cpp,v 1.6 2001-03-31 09:23:34 tom Exp $ // // $Log: tile_track.cpp,v $ // Revision 1.6 2001-03-31 09:23:34 tom // fixed ball disappearing bug as a result of fluctuating frame rates // // Revision 1.5 2001/03/17 00:43:31 tom // removed stray cout statement // // Revision 1.4 2001/03/15 09:54:51 tom // Changed code to set/check the doMidPoint flag on balls as they cross // the tiles. Trying to calculate when the mid point check should be done // resulted in some occasional slip ups where sometimes a tile would not do // the appropriate mid point action (e.g. painter would miss a ball, blocker // would let the wrong colored ball through, one-way wouldn't redirect a ball // in a different direction, teleporter would miss a ball, etc.). // // Revision 1.3 2001/02/19 03:03:58 tom // hard coded names and paths of builtin music and sound files to be // consistent with how image files are compiled into the executable and // to make the properties/ini file simpler to port between Unix and WIN32 // // Revision 1.2 2001/02/16 21:00:11 tom // did some WIN32 porting work on the code... just a few more files to go. // // Revision 1.1 2001/01/20 17:32:37 brown // Working toward Windows integration // // Revision 1.9 2000/11/19 03:41:57 brown // More changes -fixed teleporter // // Revision 1.7 2000/11/18 23:33:00 tom // put back default switch cases and removed a debug statement // // Revision 1.6 2000/11/18 22:38:59 tom // fixed some memory leaks and changed some stuff to try to track down the // disappearing ball phenomenon. // // Revision 1.5 2000/10/25 16:45:25 brown // Updated to build on vanilla RedHat 7.0 // // Revision 1.4 2000/10/07 18:16:35 brown // Ball movement fixes // // Revision 1.3 2000/10/06 19:29:13 brown // Added autoconf stuff // Added GPL header to files // Added WON scroller // Added GPL to about screen // // Revision 1.2 2000/10/01 05:00:27 tom // put in infrastructure for abstract audio drivers and started to code // SDL_mixer support. // // Revision 1.1.1.1 2000/09/28 02:17:53 tom // imported sources // // Revision 1.19 2000/03/28 07:31:10 tom // Added calls to play more sound effects. // // Revision 1.18 2000/02/21 23:06:37 brown // Updated a CRAPLOAD of graphics, fixed fonts and scrolling // // Revision 1.17 2000/01/10 02:53:51 brown // Bunch of changes - fixed start track, fixed order and pattern, fixed some // backgrounds. // // Revision 1.16 2000/01/01 21:51:22 brown // Mucho changes - fixed level loading and game startup screens // // Revision 1.15 1999/12/25 08:18:41 tom // Added "Id" and "Log" CVS keywords to source code. //