2007-05-27 12:01:53 -04:00
|
|
|
//
|
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
|
|
|
// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
2008-06-12 20:53:52 -04:00
|
|
|
// as published by the Free Software Foundation; either version 3
|
2007-05-27 12:01:53 -04:00
|
|
|
// 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.
|
|
|
|
|
2008-09-15 00:34:46 -04:00
|
|
|
#include "main_loop.hpp"
|
2007-05-27 12:01:53 -04:00
|
|
|
|
|
|
|
#include <assert.h>
|
2009-06-02 08:37:29 -04:00
|
|
|
|
2010-04-21 13:24:02 -04:00
|
|
|
#include "audio/music_manager.hpp"
|
2009-06-11 06:00:43 -04:00
|
|
|
#include "config/user_config.hpp"
|
2009-02-10 00:30:59 -05:00
|
|
|
#include "graphics/irr_driver.hpp"
|
2009-06-02 08:37:29 -04:00
|
|
|
#include "graphics/material_manager.hpp"
|
2009-07-18 13:48:36 -04:00
|
|
|
#include "guiengine/engine.hpp"
|
2009-06-02 08:37:29 -04:00
|
|
|
#include "input/input_manager.hpp"
|
2012-01-01 16:19:13 -05:00
|
|
|
#include "input/wiimote_manager.hpp"
|
2009-08-23 11:42:58 -04:00
|
|
|
#include "modes/profile_world.hpp"
|
2009-02-10 00:30:59 -05:00
|
|
|
#include "modes/world.hpp"
|
2008-09-07 09:38:46 -04:00
|
|
|
#include "network/network_manager.hpp"
|
2009-06-02 21:36:48 -04:00
|
|
|
#include "race/race_manager.hpp"
|
2009-08-23 11:42:58 -04:00
|
|
|
#include "states_screens/state_manager.hpp"
|
2011-07-09 15:13:17 -04:00
|
|
|
#include "utils/profiler.hpp"
|
2007-05-27 12:01:53 -04:00
|
|
|
|
2008-09-15 00:34:46 -04:00
|
|
|
MainLoop* main_loop = 0;
|
2007-05-27 12:01:53 -04:00
|
|
|
|
2008-09-15 00:34:46 -04:00
|
|
|
MainLoop::MainLoop() :
|
2007-05-27 12:01:53 -04:00
|
|
|
m_abort(false),
|
2009-04-25 13:55:39 -04:00
|
|
|
m_frame_count(0)
|
2007-05-27 12:01:53 -04:00
|
|
|
{
|
2009-04-25 13:55:39 -04:00
|
|
|
m_curr_time = 0;
|
|
|
|
m_prev_time = 0;
|
2008-09-15 00:34:46 -04:00
|
|
|
} // MainLoop
|
2007-05-27 12:01:53 -04:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2008-09-15 00:34:46 -04:00
|
|
|
MainLoop::~MainLoop()
|
2007-05-27 12:01:53 -04:00
|
|
|
{
|
2008-09-15 00:34:46 -04:00
|
|
|
} // ~MainLoop
|
2007-05-27 12:01:53 -04:00
|
|
|
|
2009-07-12 07:54:21 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Returns the current dt, which guarantees a limited frame rate. If dt is
|
|
|
|
* too low (the frame rate too high), the process will sleep to reach the
|
|
|
|
* maxium frame rate.
|
|
|
|
*/
|
|
|
|
float MainLoop::getLimitedDt()
|
|
|
|
{
|
|
|
|
IrrlichtDevice* device = irr_driver->getDevice();
|
|
|
|
m_prev_time = m_curr_time;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2009-07-12 07:54:21 -04:00
|
|
|
float dt; // needed outside of the while loop
|
|
|
|
while( 1 )
|
|
|
|
{
|
|
|
|
m_curr_time = device->getTimer()->getRealTime();
|
|
|
|
dt = (float)(m_curr_time - m_prev_time);
|
|
|
|
|
|
|
|
// don't allow the game to run slower than a certain amount.
|
|
|
|
// when the computer can't keep it up, slow down the shown time instead
|
|
|
|
static const float max_elapsed_time = 3.0f*1.0f/60.0f*1000.0f; /* time 3 internal substeps take */
|
2010-12-05 17:24:01 -05:00
|
|
|
if(dt > max_elapsed_time) dt=max_elapsed_time;
|
2009-07-12 07:54:21 -04:00
|
|
|
|
2013-05-29 18:04:35 -04:00
|
|
|
// Throttle fps if more than maximum, which can reduce
|
2009-07-12 07:54:21 -04:00
|
|
|
// the noise the fan on a graphics card makes.
|
|
|
|
// When in menus, reduce FPS much, it's not necessary to push to the maximum for plain menus
|
2012-04-01 10:48:26 -04:00
|
|
|
const int max_fps = (StateManager::get()->throttleFPS() ? 35 : UserConfigParams::m_max_fps);
|
2009-07-12 07:54:21 -04:00
|
|
|
const int current_fps = (int)(1000.0f/dt);
|
2011-08-02 20:41:28 -04:00
|
|
|
if( current_fps > max_fps && !ProfileWorld::isNoGraphics())
|
2009-07-12 07:54:21 -04:00
|
|
|
{
|
|
|
|
int wait_time = 1000/max_fps - 1000/current_fps;
|
|
|
|
if(wait_time < 1) wait_time = 1;
|
|
|
|
|
|
|
|
irr_driver->getDevice()->sleep(wait_time);
|
|
|
|
}
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
dt *= 0.001f;
|
|
|
|
return dt;
|
2009-09-16 01:32:17 -04:00
|
|
|
} // getLimitedDt
|
2009-07-12 07:54:21 -04:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Updates all race related objects.
|
|
|
|
* \param dt Time step size.
|
|
|
|
*/
|
|
|
|
void MainLoop::updateRace(float dt)
|
|
|
|
{
|
|
|
|
// Server: Send the current position and previous controls to all clients
|
|
|
|
// Client: send current controls to server
|
2013-05-29 18:04:35 -04:00
|
|
|
// But don't do this if the race is in finish phase (otherwise
|
2009-07-12 07:54:21 -04:00
|
|
|
// messages can be mixed up in the race manager)
|
2010-02-11 02:11:52 -05:00
|
|
|
if(!World::getWorld()->isFinishPhase())
|
2009-07-12 07:54:21 -04:00
|
|
|
network_manager->sendUpdates();
|
2009-08-23 11:42:58 -04:00
|
|
|
if(ProfileWorld::isProfileMode()) dt=1.0f/60.0f;
|
2009-07-12 07:54:21 -04:00
|
|
|
|
|
|
|
// Again, only receive updates if the race isn't over - once the
|
2013-05-29 18:04:35 -04:00
|
|
|
// race results are displayed (i.e. game is in finish phase)
|
|
|
|
// messages must be handled by the normal update of the network
|
2009-07-12 07:54:21 -04:00
|
|
|
// manager
|
2010-02-11 02:11:52 -05:00
|
|
|
if(!World::getWorld()->isFinishPhase())
|
2009-07-12 07:54:21 -04:00
|
|
|
network_manager->receiveUpdates();
|
|
|
|
|
2010-05-10 19:53:32 -04:00
|
|
|
World::getWorld()->updateWorld(dt);
|
2009-07-12 07:54:21 -04:00
|
|
|
} // updateRace
|
|
|
|
|
2007-05-27 12:01:53 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2008-09-15 00:34:46 -04:00
|
|
|
/** Run the actual main loop.
|
|
|
|
*/
|
|
|
|
void MainLoop::run()
|
2007-05-27 12:01:53 -04:00
|
|
|
{
|
2009-04-25 14:25:08 -04:00
|
|
|
IrrlichtDevice* device = irr_driver->getDevice();
|
2010-05-10 19:53:32 -04:00
|
|
|
|
2009-05-02 20:50:09 -04:00
|
|
|
m_curr_time = device->getTimer()->getRealTime();
|
2007-05-27 12:01:53 -04:00
|
|
|
while(!m_abort)
|
|
|
|
{
|
2011-09-05 18:55:55 -04:00
|
|
|
PROFILER_PUSH_CPU_MARKER("Main loop", 0xFF, 0x00, 0xF7);
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2008-02-12 20:02:02 -05:00
|
|
|
m_prev_time = m_curr_time;
|
2009-07-12 07:54:21 -04:00
|
|
|
float dt = getLimitedDt();
|
2008-03-17 01:18:26 -04:00
|
|
|
|
2008-09-07 09:27:00 -04:00
|
|
|
network_manager->update(dt);
|
2008-09-07 10:34:04 -04:00
|
|
|
|
2010-02-11 02:11:52 -05:00
|
|
|
if (World::getWorld()) // race is active if world exists
|
2007-05-27 12:01:53 -04:00
|
|
|
{
|
2008-09-07 09:58:37 -04:00
|
|
|
// Busy wait if race_manager is active (i.e. creating of world is done)
|
|
|
|
// till all clients have reached this state.
|
2009-09-01 14:11:26 -04:00
|
|
|
if (network_manager->getState()==NetworkManager::NS_READY_SET_GO_BARRIER) continue;
|
2009-07-12 07:54:21 -04:00
|
|
|
updateRace(dt);
|
2008-06-09 22:35:10 -04:00
|
|
|
} // if race is active
|
2007-05-27 12:01:53 -04:00
|
|
|
|
2010-09-11 12:54:45 -04:00
|
|
|
// We need to check again because update_race may have requested
|
|
|
|
// the main loop to abort; and it's not a good idea to continue
|
|
|
|
// since the GUI engine is no more to be called then.
|
2011-07-27 08:11:11 -04:00
|
|
|
// Also only do music, input, and graphics update if graphics are
|
|
|
|
// enabled.
|
|
|
|
if (!m_abort && !ProfileWorld::isNoGraphics())
|
2010-09-11 12:54:45 -04:00
|
|
|
{
|
2011-07-09 15:13:17 -04:00
|
|
|
PROFILER_PUSH_CPU_MARKER("Music manager update", 0x7F, 0x00, 0x00);
|
2010-09-11 12:54:45 -04:00
|
|
|
music_manager->update(dt);
|
2011-07-09 15:13:17 -04:00
|
|
|
PROFILER_POP_CPU_MARKER();
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-07-09 15:13:17 -04:00
|
|
|
PROFILER_PUSH_CPU_MARKER("Input manager update", 0x00, 0x7F, 0x00);
|
2010-09-11 12:54:45 -04:00
|
|
|
input_manager->update(dt);
|
2011-07-09 15:13:17 -04:00
|
|
|
PROFILER_POP_CPU_MARKER();
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2012-01-01 16:19:13 -05:00
|
|
|
#ifdef ENABLE_WIIUSE
|
|
|
|
wiimote_manager->update();
|
|
|
|
#endif
|
2013-02-27 20:05:27 -05:00
|
|
|
PROFILER_PUSH_CPU_MARKER("Update GUI widgets", 0x7F, 0x7F, 0x00);
|
|
|
|
GUIEngine::update(dt);
|
|
|
|
PROFILER_POP_CPU_MARKER();
|
|
|
|
|
2011-07-09 20:04:12 -04:00
|
|
|
PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F);
|
2010-09-11 12:54:45 -04:00
|
|
|
irr_driver->update(dt);
|
2011-07-09 15:13:17 -04:00
|
|
|
PROFILER_POP_CPU_MARKER();
|
2010-09-11 12:54:45 -04:00
|
|
|
}
|
2013-07-17 18:37:45 -04:00
|
|
|
PROFILER_SYNC_FRAME();
|
2011-09-05 18:55:55 -04:00
|
|
|
PROFILER_POP_CPU_MARKER();
|
2007-05-27 12:01:53 -04:00
|
|
|
} // while !m_exit
|
2009-07-12 07:54:21 -04:00
|
|
|
|
2007-05-27 12:01:53 -04:00
|
|
|
} // run
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2008-09-15 00:34:46 -04:00
|
|
|
/** Set the abort flag, causing the mainloop to be left.
|
|
|
|
*/
|
|
|
|
void MainLoop::abort()
|
2007-05-27 12:01:53 -04:00
|
|
|
{
|
|
|
|
m_abort = true;
|
2008-09-15 00:34:46 -04:00
|
|
|
} // abort
|
2007-05-27 12:01:53 -04:00
|
|
|
|
|
|
|
/* EOF */
|