1) Profile mode now works, and is now completely implemented

in ProfileWorld only (no more m_profile in UserConfig)
2) Added some more virtual functions to the modes to simply
   code a bit.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3909 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2009-08-23 15:42:58 +00:00
parent 96e2c28799
commit c1d69986b0
13 changed files with 148 additions and 92 deletions

View File

@ -232,11 +232,6 @@ namespace UserConfigParams
PARAM_PREFIX IntUserConfigParam m_track_debug PARAM_DEFAULT( IntUserConfigParam(false, "track_debug") );
PARAM_PREFIX bool m_bullet_debug PARAM_DEFAULT( false );
PARAM_PREFIX bool m_print_kart_sizes PARAM_DEFAULT( false );
// Used to profile AI. Not saved to file.
// Positive: time in seconds; Negative: # laps; 0: no profiling.
PARAM_PREFIX int m_profile PARAM_DEFAULT( 0 );
// ---- Networking
PARAM_PREFIX StringUserConfigParam m_server_address

View File

@ -110,6 +110,10 @@ public:
void changeResolution();
void showPointer();
void hidePointer();
/** Returns the current real time, which might not be 0 at start of the
* application. Value in msec.
*/
unsigned int getRealTime() {return m_device->getTimer()->getRealTime(); }
void renderToTexture(ptr_vector<scene::IMesh, REF>& mesh,
std::vector<Vec3>& mesh_location,

View File

@ -90,7 +90,6 @@ void Attachment::clear()
// -----------------------------------------------------------------------------
void Attachment::hitBanana(const Item &item, int new_attachment)
{
if(UserConfigParams::m_profile) return;
float leftover_time = 0.0f;
switch(getType()) // If there already is an attachment, make it worse :)

View File

@ -58,6 +58,7 @@
#include "items/projectile_manager.hpp"
#include "karts/kart_properties_manager.hpp"
#include "karts/kart.hpp"
#include "modes/profile_world.hpp"
#include "network/network_manager.hpp"
#include "race/grand_prix_manager.hpp"
#include "race/highscore_manager.hpp"
@ -402,21 +403,24 @@ int handleCmdLine(int argc, char **argv)
UserConfigParams::m_log_errors=true;
} else if( sscanf(argv[i], "--profile=%d", &n)==1)
{
UserConfigParams::m_profile=n;
if(n<0)
{
fprintf(stdout,"Profiling %d laps\n",-n);
race_manager->setNumLaps(-n);
}
else
if(n<0)
{
printf("Profiling: %d seconds.\n", (int)UserConfigParams::m_profile);
printf("Profiling %d laps\n",-n);
ProfileWorld::setProfileModeLaps(-n);
race_manager->setNumLaps(-n);
}
else
{
printf("Profiling: %d seconds.\n", n);
ProfileWorld::setProfileModeTime(n);
race_manager->setNumLaps(999999); // profile end depends on time
}
}
else if( !strcmp(argv[i], "--profile") )
{
UserConfigParams::m_profile=20;
printf("Profiling: %d seconds.\n", n);
ProfileWorld::setProfileModeTime(20);
race_manager->setNumLaps(999999); // profile end depends on time
}
else if( sscanf(argv[i], "--history=%d", &n)==1)
{
@ -451,7 +455,7 @@ int handleCmdLine(int argc, char **argv)
return 0;
}
} // for i <argc
if(UserConfigParams::m_profile)
if(ProfileWorld::isProfileMode())
{
UserConfigParams::m_sfx = false; // Disable sound effects
UserConfigParams::m_music = false;// and music when profiling
@ -655,7 +659,7 @@ int main(int argc, char *argv[] )
}
// Not replaying
// =============
if(!UserConfigParams::m_profile)
if(!ProfileWorld::isProfileMode())
{
if(UserConfigParams::m_no_start_screen)
{

View File

@ -26,12 +26,13 @@
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "guiengine/engine.hpp"
#include "states_screens/state_manager.hpp"
#include "input/input_manager.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp"
#include "network/network_manager.hpp"
#include "race/history.hpp"
#include "race/race_manager.hpp"
#include "states_screens/state_manager.hpp"
MainLoop* main_loop = 0;
@ -91,23 +92,6 @@ float MainLoop::getLimitedDt()
dt *= 0.001f;
return dt;
}
//-----------------------------------------------------------------------------
/** Updates the profiling frame counter, and if the end of the profiling
* period is reached prints the results and aborts STK.
*/
void MainLoop::updateProfiling()
{
m_frame_count++;
if (RaceManager::getWorld()->getTime()>UserConfigParams::m_profile)
{
IrrlichtDevice* device = irr_driver->getDevice();
printf("Number of frames: %d time %f, Average FPS: %f\n",
m_frame_count, device->getTimer()->getRealTime()*0.001,
(float)m_frame_count/(device->getTimer()->getRealTime()));
if(!history->replayHistory()) history->Save();
std::exit(-2);
} // if profile finished
} // updateProfiling
//-----------------------------------------------------------------------------
/** Updates all race related objects.
@ -121,7 +105,7 @@ void MainLoop::updateRace(float dt)
// messages can be mixed up in the race manager)
if(!race_manager->getWorld()->isFinishPhase())
network_manager->sendUpdates();
if(UserConfigParams::m_profile) dt=1.0f/60.0f;
if(ProfileWorld::isProfileMode()) dt=1.0f/60.0f;
// Again, only receive updates if the race isn't over - once the
// race results are displayed (i.e. game is in finish phase)
@ -134,8 +118,6 @@ void MainLoop::updateRace(float dt)
{
history->update(dt);
RaceManager::getWorld()->update(dt);
if(UserConfigParams::m_profile>0) updateProfiling();
} // phase != limbo phase
} // updateRace

View File

@ -44,7 +44,6 @@ private:
Uint32 m_prev_time;
float getLimitedDt();
void updateRace(float dt);
void updateProfiling();
public:
MainLoop();
~MainLoop();

View File

@ -25,19 +25,18 @@
//-----------------------------------------------------------------------------
TimedRace::TimedRace()
{
m_mode = CHRONO;
m_time = 0.0f;
m_mode = CHRONO;
m_time = 0.0f;
m_auxiliary_timer = 0.0f;
m_phase = SETUP_PHASE;
m_previous_phase = SETUP_PHASE; // initialise it just in case
// for profiling AI
m_phase = UserConfigParams::m_profile ? RACE_PHASE : SETUP_PHASE;
m_phase = SETUP_PHASE;
m_previous_phase = SETUP_PHASE; // initialise it just in case
m_phase = SETUP_PHASE;
// FIXME - is it a really good idea to reload and delete the sound every race??
m_prestart_sound = sfx_manager->newSFX(SFXManager::SOUND_PRESTART);
m_start_sound = sfx_manager->newSFX(SFXManager::SOUND_START);
}
m_prestart_sound = sfx_manager->newSFX(SFXManager::SOUND_PRESTART);
m_start_sound = sfx_manager->newSFX(SFXManager::SOUND_START);
} // TimedRace
//-----------------------------------------------------------------------------
void TimedRace::reset()
{
@ -45,19 +44,22 @@ void TimedRace::reset()
m_auxiliary_timer = 0.0f;
m_phase = READY_PHASE; // FIXME - unsure
m_previous_phase = SETUP_PHASE;
}
} // reset
//-----------------------------------------------------------------------------
TimedRace::~TimedRace()
{
sfx_manager->deleteSFX(m_prestart_sound);
sfx_manager->deleteSFX(m_start_sound);
}
} // ~TimedRace
//-----------------------------------------------------------------------------
void TimedRace::setClockMode(const ClockType mode, const float initial_time)
{
m_mode = mode;
m_time = initial_time;
}
} // setClockMode
//-----------------------------------------------------------------------------
void TimedRace::enterRaceOverState(const bool delay)
{
@ -73,7 +75,8 @@ void TimedRace::enterRaceOverState(const bool delay)
if(network_manager->getMode()==NetworkManager::NW_SERVER)
network_manager->sendRaceResults();
}
} // enterRaceOverState
//-----------------------------------------------------------------------------
void TimedRace::update(const float dt)
{

View File

@ -17,9 +17,15 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/irr_driver.hpp"
#include "modes/profile_world.hpp"
#include "robots/default_robot.hpp"
ProfileWorld::ProfileType ProfileWorld::m_profile_mode=PROFILE_NONE;
int ProfileWorld::m_num_laps = 0;
float ProfileWorld::m_time = 0.0f;
//-----------------------------------------------------------------------------
/** The constructor sets the number of (local) players to 0, since only AI
* karts are used.
@ -28,27 +34,35 @@ ProfileWorld::ProfileWorld()
{
race_manager->setNumPlayers(0);
race_manager->setNumLocalPlayers(0);
// Set number of laps so that the end of the race can be detected by
// quering the number of finished karts from the race manager (in laps
// based profiling) - otherwise just a high number.
race_manager->setNumLaps(m_profile_mode==PROFILE_LAPS ? m_num_laps : 99999);
m_phase = RACE_PHASE;
m_frame_count = 0;
m_start_time = irr_driver->getRealTime();
} // ProfileWorld
//-----------------------------------------------------------------------------
/** Prints the profile statistic and exits!!
/** Enables profiling for a certain amount of time.
* \param time Time to profile a race for.
*/
ProfileWorld::~ProfileWorld()
void ProfileWorld::setProfileModeTime(float time)
{
float min_t=999999.9f, max_t=0.0, av_t=0.0;
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
{
max_t = std::max(max_t, m_kart[i]->getFinishTime());
min_t = std::min(min_t, m_kart[i]->getFinishTime());
av_t += m_kart[i]->getFinishTime();
printf("%s start %d end %d time %f\n",
m_kart[i]->getName().c_str(),(int)i,
m_kart[i]->getPosition(),
m_kart[i]->getFinishTime());
}
printf("min %f max %f av %f\n",min_t, max_t, av_t/m_kart.size());
std::exit(-2);
} // ~ProfileWorld
m_profile_mode = PROFILE_TIME;
m_time = time;
} // setProfileModeTime
//-----------------------------------------------------------------------------
/** Enables profiling for a certain number of laps. The race will end when all
* karts have done (at least) this number of laps.
* \param laps The number of laps.
*/
void ProfileWorld::setProfileModeLaps(int laps)
{
m_profile_mode = PROFILE_LAPS;
m_num_laps = laps;
} // setProfileModeLaps
//-----------------------------------------------------------------------------
/** Creates a kart, having a certain position, starting location, and local
@ -81,3 +95,47 @@ Kart *ProfileWorld::createKart(const std::string &kart_ident, int index,
return newkart;
} // createKart
//-----------------------------------------------------------------------------
/** The race is over if either the requested number of laps have been done
* or the requested time is over.
*/
bool ProfileWorld::isRaceOver()
{
if(m_profile_mode==PROFILE_TIME)
return getTime()>m_time;
// Now it must be laps based profiling:
return race_manager->getFinishedKarts()==race_manager->getNumKarts();
} // isRaceOver
//-----------------------------------------------------------------------------
/** Counts the number of framces and aborts if the end condition is fulfilled.
*/
void ProfileWorld::update(float dt)
{
StandardRace::update(dt);
m_frame_count++;
} // update
//-----------------------------------------------------------------------------
void ProfileWorld::enterRaceOverState(const bool delay)
{
float runtime = (irr_driver->getRealTime()-m_start_time)*0.001f;
printf("Number of frames: %d time %f, Average FPS: %f\n",
m_frame_count, runtime, (float)m_frame_count/runtime);
float min_t=999999.9f, max_t=0.0, av_t=0.0;
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
{
max_t = std::max(max_t, m_kart[i]->getFinishTime());
min_t = std::min(min_t, m_kart[i]->getFinishTime());
av_t += m_kart[i]->getFinishTime();
printf("%s start %d end %d time %f\n",
m_kart[i]->getName().c_str(),(int)i,
m_kart[i]->getPosition(),
m_kart[i]->getFinishTime());
}
printf("min %f max %f av %f\n",min_t, max_t, av_t/m_kart.size());
std::exit(-2);
} // enterRaceOverState

View File

@ -27,7 +27,19 @@ class Kart;
class ProfileWorld : public StandardRace
{
private:
int m_frame_count;
/** Profiling modes. */
enum ProfileType {PROFILE_NONE, PROFILE_TIME, PROFILE_LAPS};
/** If profiling is done, and if so, which mode. */
static ProfileType m_profile_mode;
/** In laps based profiling: number of laps to run. */
static int m_num_laps;
/** In time based profiling only: time to run. */
static float m_time;
/** Return value of real time at start of race. */
unsigned int m_start_time;
/** Number of frames. For statistics only. */
int m_frame_count;
protected:
virtual Kart *createKart(const std::string &kart_ident, int index,
@ -35,10 +47,18 @@ protected:
const btTransform &init_pos);
public:
ProfileWorld();
virtual ~ProfileWorld();
ProfileWorld();
virtual ~ProfileWorld() {};
/** Returns identifier for this world. */
virtual std::string getInternalCode() const {return "PROFILE"; }
virtual void update(float dt);
virtual bool isRaceOver();
virtual void enterRaceOverState(const bool delay=false);
static void setProfileModeTime(float time);
static void setProfileModeLaps(int laps);
/** Returns true if profile mode was selected. */
static bool isProfileMode() {return m_profile_mode!=PROFILE_NONE; }
};
#endif

View File

@ -74,13 +74,13 @@ void StandardRace::update(float delta)
// All karts are finished
if(race_manager->getFinishedKarts() >= race_manager->getNumKarts() )
{
TimedRace::enterRaceOverState();
enterRaceOverState();
unlock_manager->raceFinished();
} // if all karts are finished
// All player karts are finished, but computer still racing
// ===========================================================
else if(race_manager->allPlayerFinished())
else if(isRaceOver())
{
// Set delay mode to have time for camera animation, and
// to give the AI some time to get non-estimated timings

View File

@ -171,23 +171,14 @@ void ThreeStrikesBattle::updateKartRanks()
} // updateKartRank
//-----------------------------------------------------------------------------
void ThreeStrikesBattle::update(float delta)
void ThreeStrikesBattle::enterRaceOverState(const bool delay)
{
World::update(delta);
// check if over
if(isRaceOver())
{
// Add the results for the remaining kart
for(int i=0; i<(int)race_manager->getNumKarts(); i++)
if(!m_kart[i]->isEliminated())
race_manager->RaceFinished(m_kart[i], TimedRace::getTime());
if(!RaceManager::getWorld()->isFinishPhase())
TimedRace::enterRaceOverState();
return;
}
} // update
World::enterRaceOverState(delay);
// Add the results for the remaining kart
for(int i=0; i<(int)race_manager->getNumKarts(); i++)
if(!m_kart[i]->isEliminated())
race_manager->RaceFinished(m_kart[i], TimedRace::getTime());
} // enterRaceOverState
//-----------------------------------------------------------------------------
/** The battle is over if only one kart is left, or no player kart.

View File

@ -48,8 +48,9 @@ public:
virtual void terminateRace();
// overriding World methods
virtual void update(float delta);
virtual void restartRace();
virtual void enterRaceOverState(const bool delay=false);
//virtual void getDefaultCollectibles(int& collectible_type, int& amount);
//virtual bool enableBonusBoxes();
virtual bool useFastMusicNearEnd() const { return false; }

View File

@ -253,7 +253,7 @@ void RaceManager::startNextRace()
// variable world. Admittedly a bit ugly, but simplifies
// handling of objects which get created in the constructor
// and need world to be defined.
if (UserConfigParams::m_profile)
if (ProfileWorld::isProfileMode())
m_world = new ProfileWorld();
else if(m_minor_mode==MINOR_MODE_FOLLOW_LEADER)
m_world = new FollowTheLeaderRace();