diff --git a/src/BlobbyApp.cpp b/src/BlobbyApp.cpp index 0016c45c..3f24d033 100644 --- a/src/BlobbyApp.cpp +++ b/src/BlobbyApp.cpp @@ -49,8 +49,13 @@ const char* BlobbyApp::getCurrenStateName() const return mCurrentState->getStateName(); } -void BlobbyApp::step() +bool BlobbyApp::step() { + mInputMgr->updateInput(); + bool running = mInputMgr->running(); + + mIMGUI->begin(); + // perform a state step mCurrentState->step_impl(); @@ -66,6 +71,8 @@ void BlobbyApp::step() mIMGUI->resetSelection(); mCurrentState->init(); } + + return running; } BlobbyApp::BlobbyApp(std::unique_ptr initState, const IUserConfigReader& config) : diff --git a/src/BlobbyApp.h b/src/BlobbyApp.h index 822f9daa..8eada1e8 100644 --- a/src/BlobbyApp.h +++ b/src/BlobbyApp.h @@ -34,7 +34,7 @@ class BlobbyApp { public: explicit BlobbyApp(std::unique_ptr initState, const IUserConfigReader& config); - void step(); + bool step(); void switchToState(std::unique_ptr newState); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 766486a0..49423215 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,7 +28,7 @@ set(common_SRC Color.cpp Color.h NetworkMessage.cpp NetworkMessage.h PhysicWorld.cpp PhysicWorld.h - SpeedController.cpp SpeedController.h + RateController.cpp RateController.h UserConfig.cpp UserConfig.h PhysicState.cpp PhysicState.h DuelMatchState.cpp DuelMatchState.h diff --git a/src/DuelMatch.cpp b/src/DuelMatch.cpp index 850e8012..4a4b91eb 100644 --- a/src/DuelMatch.cpp +++ b/src/DuelMatch.cpp @@ -47,7 +47,7 @@ DuelMatch::DuelMatch(bool remote, const std::string& rules, int score_to_win) : setInputSources(std::make_shared(), std::make_shared()); if(!mRemote) - mPhysicWorld->setEventCallback( [this]( const MatchEvent& event ) { mEvents.push_back(event); } ); + mPhysicWorld->setEventCallback( [this]( const MatchEvent& event ) { mNewEvents.push_back(event); } ); } void DuelMatch::setPlayers(PlayerIdentity left_player, PlayerIdentity right_player) @@ -108,7 +108,7 @@ void DuelMatch::step() // process events // process all physics events and relay them to logic - for( const auto& event : mEvents ) + for( const auto& event : mNewEvents ) { switch( event.event ) { @@ -138,7 +138,7 @@ void DuelMatch::step() auto errorside = mLogic->getLastErrorSide(); if(errorside != NO_PLAYER) { - mEvents.emplace_back( MatchEvent::PLAYER_ERROR, errorside, 0 ); + mNewEvents.emplace_back( MatchEvent::PLAYER_ERROR, errorside, 0 ); mPhysicWorld->setBallVelocity( mPhysicWorld->getBallVelocity().scale(0.6) ); } @@ -150,12 +150,12 @@ void DuelMatch::step() { resetBall( mLogic->getServingPlayer() ); mLogic->onServe(); - mEvents.emplace_back( MatchEvent::RESET_BALL, NO_PLAYER, 0 ); + mNewEvents.emplace_back( MatchEvent::RESET_BALL, NO_PLAYER, 0 ); } // reset events - mLastEvents = mEvents; - mEvents.clear(); + std::move(begin(mNewEvents), end(mNewEvents), std::back_inserter(mLastEvents)); + mNewEvents.clear(); } void DuelMatch::setScore(int left, int right) @@ -280,7 +280,7 @@ void DuelMatch::setState(const DuelMatchState& state) void DuelMatch::trigger( const MatchEvent& event ) { - mEvents.push_back( event ); + mNewEvents.push_back( event ); } DuelMatchState DuelMatch::getState() const @@ -350,6 +350,6 @@ PlayerIdentity& DuelMatch::getPlayer(PlayerSide player) void DuelMatch::updateEvents() { /// \todo more economical with a swap? - mLastEvents = mEvents; - mEvents.clear(); + mLastEvents = mNewEvents; + mNewEvents.clear(); } diff --git a/src/DuelMatch.h b/src/DuelMatch.h index 4a09c311..5fbfd997 100644 --- a/src/DuelMatch.h +++ b/src/DuelMatch.h @@ -128,6 +128,9 @@ class DuelMatch : public ObjectCounter void setServingPlayer(PlayerSide side); const std::vector& getEvents() const { return mLastEvents; } + std::vector fetchEvents() { + return std::move(mLastEvents); + } // this function will move all events into mLastEvents, so they will be returned by get events. // use this if no match step is performed, but external events have to be processed. void updateEvents(); @@ -146,7 +149,7 @@ class DuelMatch : public ObjectCounter bool mPaused; // accumulation of physic events since last event processing - std::vector mEvents; + std::vector mNewEvents; std::vector mLastEvents; // events that were generated in the last processed frame bool mRemote; diff --git a/src/RateController.cpp b/src/RateController.cpp new file mode 100644 index 00000000..0ea0968d --- /dev/null +++ b/src/RateController.cpp @@ -0,0 +1,52 @@ +/*============================================================================= +Blobby Volley 2 +Copyright (C) 2023 Daniel Knobe (daniel-knobe@web.de) +Copyright (C) 2023 Erik Schultheis (erik-schultheis@freenet.de) + +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 +=============================================================================*/ + +/* header include */ +#include "RateController.h" + +/* includes */ +#include + +/* implementation */ +using namespace std::chrono; + +RateController::RateController() : mFrameDuration(0) { + +} + +void RateController::start(int frames_per_second) { + mFrameDuration = duration_cast(seconds(1)) / frames_per_second; + mLastTicks = clock_t::now(); +} + +bool RateController::handle_next_frame() { + assert(mFrameDuration.count() != 0); + if(wants_next_frame()) { + mLastTicks += mFrameDuration; + return true; + } + return false; +} + +bool RateController::wants_next_frame() const +{ + assert(mFrameDuration.count() != 0); + return clock_t::now() > mLastTicks + mFrameDuration; +} diff --git a/src/RateController.h b/src/RateController.h new file mode 100644 index 00000000..37097895 --- /dev/null +++ b/src/RateController.h @@ -0,0 +1,37 @@ +/*============================================================================= +Blobby Volley 2 +Copyright (C) 2023 Daniel Knobe (daniel-knobe@web.de) +Copyright (C) 2023 Erik Schultheis (erik-schultheis@freenet.de) + +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 +=============================================================================*/ + +#pragma once + +#include + +class RateController { + public: + RateController(); + using clock_t = std::chrono::steady_clock; + + void start(int frames_per_second); + bool handle_next_frame(); + bool wants_next_frame() const; + + private: + std::chrono::nanoseconds mFrameDuration; + clock_t::time_point mLastTicks; +}; diff --git a/src/SpeedController.cpp b/src/SpeedController.cpp deleted file mode 100644 index 236e8e99..00000000 --- a/src/SpeedController.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/*============================================================================= -Blobby Volley 2 -Copyright (C) 2006 Jonathan Sieber (jonathan_sieber@yahoo.de) -Copyright (C) 2006 Daniel Knobe (daniel-knobe@web.de) - -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 -=============================================================================*/ - -/* header include */ -#include "SpeedController.h" - -/* includes */ -#include - -#include - -/* implementation */ -/// this is required to reduce rounding errors. now we have a resolution of -/// 1�s. This is much better than SDL_Delay can handle, but we prevent -/// accumulation errors. -const int PRECISION_FACTOR = 1000; - -SpeedController* SpeedController::mMainInstance = nullptr; - -SpeedController::SpeedController(float gameFPS) -{ - mGameFPS = gameFPS; - mFramedrop = false; - mDrawFPS = true; - mFPSCounter = 0; - mOldTicks = SDL_GetTicks(); - mFPS = 0; - mBeginSecond = mOldTicks; - mCounter = 0; -} - -SpeedController::~SpeedController() = default; - -void SpeedController::setGameSpeed(float fps) -{ - if (fps < 5) - fps = 5; - mGameFPS = fps; - - /// \todo maybe we should reset only if speed changed? - mBeginSecond = mOldTicks; - mCounter = 0; -} - -bool SpeedController::doFramedrop() const -{ - return mFramedrop; -} - -void SpeedController::update() -{ - int rateTicks = std::max( static_cast(PRECISION_FACTOR * 1000 / mGameFPS), 1); - - static int lastTicks = SDL_GetTicks(); - - if (mCounter == mGameFPS) - { - const int delta = SDL_GetTicks() - mBeginSecond; - int wait = 1000 - delta; - if (wait > 0) - SDL_Delay(wait); - } - if (mBeginSecond + 1000 <= SDL_GetTicks()) - { - mBeginSecond = SDL_GetTicks(); - mCounter = 0; - } - - const int delta = SDL_GetTicks() - mBeginSecond; - if ( (PRECISION_FACTOR * delta) / rateTicks <= mCounter) - { - int wait = ((mCounter+1)*rateTicks/PRECISION_FACTOR) - delta; - if (wait > 0) - SDL_Delay(wait); - } - - // do we need framedrop? - // if passed time > time when we should have drawn next frame - // maybe we should limit the number of consecutive framedrops? - // for now: we can't do a framedrop if we did a framedrop last frame - if ( delta * PRECISION_FACTOR > rateTicks * (mCounter + 1) && !mFramedrop) - { - mFramedrop = true; - } else - mFramedrop = false; - - mCounter++; - - //calculate the FPS of drawn frames: - if (mDrawFPS) - { - if (lastTicks >= mOldTicks + 1000) - { - mOldTicks = lastTicks; - mFPS = mFPSCounter; - mFPSCounter = 0; - } - - if (!mFramedrop) - mFPSCounter++; - } - - //update for next call: - lastTicks = SDL_GetTicks(); -} - - diff --git a/src/SpeedController.h b/src/SpeedController.h deleted file mode 100644 index cc4f67d4..00000000 --- a/src/SpeedController.h +++ /dev/null @@ -1,77 +0,0 @@ -/*============================================================================= -Blobby Volley 2 -Copyright (C) 2006 Jonathan Sieber (jonathan_sieber@yahoo.de) -Copyright (C) 2006 Daniel Knobe (daniel-knobe@web.de) - -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 -=============================================================================*/ - -/** - * @file SpeedController.h - * @brief Contains a class which determine the framerate - */ - -#pragma once - -#include "BlobbyDebug.h" - -/// \brief class controlling game speed -/// \details This class can control the game speed and the displayed FPS. -/// It is updated once a frame and waits the necessary time. -/// A distinction is made between game FPS and real FPS. -/// Game FPS is the number of game loop iterations per second, -/// real FPS is the number of screen updates per second. The real -/// FPS is reached with framedropping -/// The class can report how much time is actually waited. If this value -/// is close to zero, the real speed can be altered. - - -class SpeedController : public ObjectCounter -{ - public: - explicit SpeedController(float gameFPS); - ~SpeedController(); - - void setGameSpeed(float fps); - float getGameSpeed() const{return mGameFPS;} - - /// This reports whether a framedrop is necessary to hold the real FPS - bool doFramedrop() const; - - /// gives the caller the fps of the drawn frames: - int getFPS() const { return mFPS; } - void setDrawFPS(bool draw) { mDrawFPS = draw; } //help methods - bool getDrawFPS() const { return mDrawFPS; } - - /// This updates everything and waits the necessary time - void update(); - - static void setMainInstance(SpeedController* inst) { mMainInstance = inst; } - static SpeedController* getMainInstance() { return mMainInstance; } - private: - float mGameFPS; - int mFPS; - int mFPSCounter; - bool mFramedrop; - bool mDrawFPS; - static SpeedController* mMainInstance; - int mOldTicks; - - // internal data - unsigned int mBeginSecond; - int mCounter; -}; - - diff --git a/src/main.cpp b/src/main.cpp index 512825e8..4fa6f248 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,11 +52,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "TextManager.h" #include "UserConfig.h" #include "IMGUI.h" -#include "SpeedController.h" #include "Blood.h" #include "FileSystem.h" #include "state/State.h" #include "BlobbyApp.h" +#include "RateController.h" #if defined(WIN32) #ifndef GAMEDATADIR @@ -222,63 +222,32 @@ int main(int argc, char* argv[]) UserConfig gameConfig; gameConfig.loadFile("config.xml"); - SpeedController scontroller(gameConfig.getFloat("gamefps")); - SpeedController::setMainInstance(&scontroller); - scontroller.setDrawFPS(gameConfig.getBool("showfps")); + RateController controller; int running = 1; DEBUG_STATUS("starting mainloop"); BlobbyApp app( std::unique_ptr(new MainMenuState()), gameConfig ); + controller.start(144); while (running) { - app.getInputManager().updateInput(); - running = app.getInputManager().running(); - - app.getIMGUI().begin(); - app.step(); - //draw FPS: - static int lastfps = 0; - static int lastlag = -1; - if (scontroller.getDrawFPS()) - { - // We need to ensure that the title bar is only set - // when the framerate changed, because setting the - // title can be quite resource intensive on some - // windows manager, like for example metacity. - // we only update lag information if lag changed at least by - // 5 ms, for the same reason. - int newfps = scontroller.getFPS(); - if (newfps != lastfps || std::abs(CURRENT_NETWORK_LAG - lastlag) > 4) - { - std::stringstream tmp; - tmp << AppTitle << " FPS: " << newfps; - if( CURRENT_NETWORK_LAG != -1) - tmp << " LAG: " << CURRENT_NETWORK_LAG; - app.getRenderManager().setTitle(tmp.str()); - lastlag = CURRENT_NETWORK_LAG; - } - lastfps = newfps; - } - // Dirty workarround for hiding fps in title - if (!scontroller.getDrawFPS() && (lastfps != -1)) - { - std::stringstream tmp; - tmp << AppTitle; - app.getRenderManager().setTitle(tmp.str()); + running = app.step(); - lastfps = -1; - } - - if (!scontroller.doFramedrop()) + controller.handle_next_frame(); + // TODO make sure we do not drop too many consecutive frames + if(!controller.wants_next_frame()) { - app.getIMGUI().end(app.getRenderManager()); - app.getRenderManager().getBlood().step(app.getRenderManager()); + app.getIMGUI().end( app.getRenderManager()); + app.getRenderManager().getBlood().step( app.getRenderManager()); app.getRenderManager().refresh(); + } else { + std::cout << "FRAME DROP\n"; + } + while(!controller.wants_next_frame()) { + std::this_thread::yield(); } - scontroller.update(); } } catch (std::exception& e) diff --git a/src/runtest.cpp b/src/runtest.cpp index 3f735bd9..556593ca 100644 --- a/src/runtest.cpp +++ b/src/runtest.cpp @@ -223,10 +223,7 @@ int main(int argc, char* argv[]) } ++step; - app.getInputManager().updateInput(); - running = app.getInputManager().running(); - app.getIMGUI().begin(); - app.step(); + running = app.step(); auto* rmanager = &app.getRenderManager(); //RenderManager may change if (!scontroller.doFramedrop()) diff --git a/src/server/NetworkGame.cpp b/src/server/NetworkGame.cpp index 3a2d48ee..6477950f 100644 --- a/src/server/NetworkGame.cpp +++ b/src/server/NetworkGame.cpp @@ -51,7 +51,8 @@ NetworkGame::NetworkGame(RakServer& server, NetworkPlayer& leftPlayer, std::string rules, int scoreToWin, float speed) : mServer(server), mMatch(new DuelMatch(false, rules, scoreToWin)), - mSpeedController(speed), + mGameFps(speed), + mRateController(), mLeftInput (new InputSource()), mRightInput(new InputSource()), mLeftLastTime(-1), @@ -79,7 +80,7 @@ NetworkGame::NetworkGame(RakServer& server, NetworkPlayer& leftPlayer, mRecorder->setPlayerNames(leftPlayer.getName(), rightPlayer.getName()); mRecorder->setPlayerColors(leftPlayer.getColor(), rightPlayer.getColor()); - mRecorder->setGameSpeed(mSpeedController.getGameSpeed()); + mRecorder->setGameSpeed(mGameFps); mRecorder->setGameRules(rules); // read rulesfile into a string @@ -108,7 +109,6 @@ NetworkGame::NetworkGame(RakServer& server, NetworkPlayer& leftPlayer, processPackets(); step(); SWLS_GameSteps++; - mSpeedController.update(); } } ); } @@ -297,7 +297,7 @@ void NetworkGame::processPacket( const packet_ptr& packet ) // writing data into leftStream RakNet::BitStream leftStream; leftStream.Write((unsigned char)ID_GAME_READY); - leftStream.Write((int)mSpeedController.getGameSpeed()); + leftStream.Write((int)mGameFps); strncpy(name, mMatch->getPlayer(RIGHT_PLAYER).getName().c_str(), sizeof(name)); leftStream.Write(name, sizeof(name)); leftStream.Write(mMatch->getPlayer(RIGHT_PLAYER).getStaticColor().toInt()); @@ -305,7 +305,7 @@ void NetworkGame::processPacket( const packet_ptr& packet ) // writing data into rightStream RakNet::BitStream rightStream; rightStream.Write((unsigned char)ID_GAME_READY); - rightStream.Write((int)mSpeedController.getGameSpeed()); + rightStream.Write((int)mGameFps); strncpy(name, mMatch->getPlayer(LEFT_PLAYER).getName().c_str(), sizeof(name)); rightStream.Write(name, sizeof(name)); rightStream.Write(mMatch->getPlayer(LEFT_PLAYER).getStaticColor().toInt()); @@ -338,31 +338,32 @@ void NetworkGame::step() // don't record the pauses if(!mMatch->isPaused()) { - mRecorder->record(mMatch->getState()); - - mMatch->step(); - - broadcastGameEvents(); - - PlayerSide winning = mMatch->winningPlayer(); - if (winning != NO_PLAYER) + while(mRateController.handle_next_frame()) { - // if someone has won, the game is paused - mMatch->pause(); - mRecorder->record(mMatch->getState()); - mRecorder->finalize( mMatch->getScore(LEFT_PLAYER), mMatch->getScore(RIGHT_PLAYER) ); + mRecorder->record( mMatch->getState()); + mMatch->step(); + PlayerSide winning = mMatch->winningPlayer(); + if (winning != NO_PLAYER) + { + // if someone has won, the game is paused + mMatch->pause(); + mRecorder->record(mMatch->getState()); + mRecorder->finalize( mMatch->getScore(LEFT_PLAYER), mMatch->getScore(RIGHT_PLAYER) ); - RakNet::BitStream stream; - stream.Write((unsigned char)ID_WIN_NOTIFICATION); - stream.Write(winning); + RakNet::BitStream stream; + stream.Write((unsigned char)ID_WIN_NOTIFICATION); + stream.Write(winning); - RakNet::BitStream switchStream; - switchStream.Write((unsigned char)ID_WIN_NOTIFICATION); - switchStream.Write(winning == LEFT_PLAYER ? RIGHT_PLAYER : LEFT_PLAYER); + RakNet::BitStream switchStream; + switchStream.Write((unsigned char)ID_WIN_NOTIFICATION); + switchStream.Write(winning == LEFT_PLAYER ? RIGHT_PLAYER : LEFT_PLAYER); - broadcastBitstream(stream, switchStream); + broadcastBitstream(stream, switchStream); + break; + } } + broadcastGameEvents(); broadcastPhysicState(mMatch->getState()); } } @@ -416,7 +417,7 @@ void NetworkGame::broadcastGameEvents() const { RakNet::BitStream stream; - auto events = mMatch->getEvents(); + auto events = mMatch->fetchEvents(); // send the events if( events.empty() ) return; diff --git a/src/server/NetworkGame.h b/src/server/NetworkGame.h index 478f895c..abeeef03 100644 --- a/src/server/NetworkGame.h +++ b/src/server/NetworkGame.h @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "Global.h" #include "raknet/NetworkTypes.h" #include "raknet/BitStream.h" -#include "SpeedController.h" +#include "RateController.h" #include "DuelMatch.h" #include "BlobbyDebug.h" @@ -92,7 +92,8 @@ class NetworkGame : public ObjectCounter std::mutex mPacketQueueMutex; const std::unique_ptr mMatch; - SpeedController mSpeedController; + int mGameFps; + RateController mRateController; std::shared_ptr mLeftInput; std::shared_ptr mRightInput; unsigned mLeftLastTime; diff --git a/src/server/servermain.cpp b/src/server/servermain.cpp index b74dc510..9b3d2d8a 100644 --- a/src/server/servermain.cpp +++ b/src/server/servermain.cpp @@ -36,7 +36,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include "DedicatedServer.h" -#include "SpeedController.h" #include "FileSystem.h" #include "UserConfig.h" #include "Global.h" @@ -200,8 +199,6 @@ int main(int argc, char** argv) // ------------------------------ void main_loop( DedicatedServer& server) { - SpeedController scontroller( UPDATE_FREQUENCY ); - while ( g_run_server ) { // ------------------------------------------------------------------------------- @@ -222,7 +219,7 @@ void main_loop( DedicatedServer& server) server.processPackets(); server.updateGames(); - scontroller.update(); + std::this_thread::yield(); } } diff --git a/src/state/GameState.cpp b/src/state/GameState.cpp index 14e3ed05..ec45c71a 100644 --- a/src/state/GameState.cpp +++ b/src/state/GameState.cpp @@ -62,7 +62,7 @@ void GameState::presentGame() rmanager.setBlobColor(RIGHT_PLAYER, mMatch->getPlayer(RIGHT_PLAYER).getStaticColor()); } - auto events = mMatch->getEvents( ); + auto events = mMatch->fetchEvents( ); for(const auto& e : events ) { if( e.event == MatchEvent::BALL_HIT_BLOB ) diff --git a/src/state/LocalGameState.cpp b/src/state/LocalGameState.cpp index d5ff17c8..385a836d 100644 --- a/src/state/LocalGameState.cpp +++ b/src/state/LocalGameState.cpp @@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "IMGUI.h" #include "replays/ReplayRecorder.h" #include "SoundManager.h" -#include "SpeedController.h" #include "IUserConfigReader.h" #include "LocalInputSource.h" @@ -78,9 +77,6 @@ void LocalGameState::init() // create default replay name setDefaultReplayName(leftPlayer.getName(), rightPlayer.getName()); - // set speed - SpeedController::getMainInstance()->setGameSpeed( (float)config->getInteger("gamefps") ); - playSound(SoundManager::WHISTLE, ROUND_START_SOUND_VOLUME); mMatch.reset(new DuelMatch( false, config->getString("rules"))); @@ -91,6 +87,9 @@ void LocalGameState::init() mRecorder->setPlayerColors( leftPlayer.getStaticColor(), rightPlayer.getStaticColor() ); mRecorder->setGameSpeed((float)config->getInteger("gamefps")); mRecorder->setGameRules( config->getString("rules") ); + + // set speed + mRateController.start(config->getInteger("gamefps")); } @@ -155,14 +154,17 @@ void LocalGameState::step_impl() } else { - mRecorder->record(mMatch->getState()); - mMatch->step(); - - if (mMatch->winningPlayer() != NO_PLAYER) + while(mRateController.handle_next_frame()) { - mWinner = true; - mRecorder->record(mMatch->getState()); - mRecorder->finalize( mMatch->getScore(LEFT_PLAYER), mMatch->getScore(RIGHT_PLAYER) ); + mRecorder->record( mMatch->getState()); + mMatch->step(); + if (mMatch->winningPlayer() != NO_PLAYER) + { + mWinner = true; + mRecorder->record(mMatch->getState()); + mRecorder->finalize( mMatch->getScore(LEFT_PLAYER), mMatch->getScore(RIGHT_PLAYER) ); + break; + } } presentGame(); diff --git a/src/state/LocalGameState.h b/src/state/LocalGameState.h index 818ab3d3..dfa5a3fe 100644 --- a/src/state/LocalGameState.h +++ b/src/state/LocalGameState.h @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #pragma once #include "GameState.h" +#include "RateController.h" class ReplayRecorder; class InputSource; @@ -46,5 +47,6 @@ class LocalGameState : public GameState bool mWinner; std::unique_ptr mRecorder; + RateController mRateController; }; diff --git a/src/state/NetworkSearchState.cpp b/src/state/NetworkSearchState.cpp index ae9205dc..ccbdc39f 100644 --- a/src/state/NetworkSearchState.cpp +++ b/src/state/NetworkSearchState.cpp @@ -46,7 +46,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "FileWrite.h" #include "FileRead.h" #include "UserConfig.h" -#include "SpeedController.h" #include "server/DedicatedServer.h" @@ -360,8 +359,8 @@ void NetworkSearchState::step_impl() std::vector rule_vec{config.getString("rules")}; - DedicatedServer server(info, rule_vec, std::vector{ SpeedController::getMainInstance()->getGameSpeed() }, 4, true); - SpeedController scontroller( 10 ); + DedicatedServer server(info, rule_vec, std::vector{ 75 }, 4, true); + //SpeedController scontroller( 10 ); gKillHostThread = false; while(!gKillHostThread) { @@ -370,7 +369,8 @@ void NetworkSearchState::step_impl() server.processPackets(); server.updateGames(); - scontroller.update(); + std::this_thread::yield(); + //scontroller.update(); } }; diff --git a/src/state/NetworkState.cpp b/src/state/NetworkState.cpp index 527e4ff2..bc8caadd 100644 --- a/src/state/NetworkState.cpp +++ b/src/state/NetworkState.cpp @@ -41,7 +41,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "GenericIO.h" #include "FileRead.h" #include "FileWrite.h" -#include "SpeedController.h" #include "LobbyStates.h" // global variable to save the lag @@ -213,7 +212,7 @@ void NetworkGameState::step_impl() // read gamespeed int speed; stream.Read(speed); - SpeedController::getMainInstance()->setGameSpeed(speed); + mRateController.start(speed); // read playername stream.Read(charName, sizeof(charName)); @@ -476,10 +475,14 @@ void NetworkGameState::step_impl() switchState(new MainMenuState); } break; + break; } case PLAYING: { - mMatch->step(); + while(mRateController.handle_next_frame()) + { + mMatch->step(); + } mLocalInput->updateInput(); PlayerInputAbs input = mLocalInput->getRealInput(); diff --git a/src/state/NetworkState.h b/src/state/NetworkState.h index a69b222a..d8c327ae 100644 --- a/src/state/NetworkState.h +++ b/src/state/NetworkState.h @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "GameState.h" #include "NetworkMessage.h" #include "PlayerIdentity.h" +#include "RateController.h" #include #include @@ -87,4 +88,6 @@ class NetworkGameState : public GameState // somewhat ugly: we need to keep the rules checksum until we actually initialize the state int mRulesChecksum; + + RateController mRateController; }; diff --git a/src/state/OptionsState.cpp b/src/state/OptionsState.cpp index 400e6910..1483ffe8 100644 --- a/src/state/OptionsState.cpp +++ b/src/state/OptionsState.cpp @@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "State.h" #include "RenderManager.h" #include "InputManager.h" -#include "SpeedController.h" #include "SoundManager.h" #include "BlobbyApp.h" #include "Blood.h" @@ -919,7 +918,6 @@ void MiscOptionsState::save() mOptionConfig.setString("rules", mRules[mRule] + ".lua"); mOptionConfig.saveFile("config.xml"); - SpeedController::getMainInstance()->setDrawFPS(mOptionConfig.getBool("showfps")); getApp().getRenderManager().getBlood().enable(mOptionConfig.getBool("blood")); getApp().getSoundManager().setVolume(mOptionConfig.getFloat("global_volume")); getApp().getSoundManager().setMute(mOptionConfig.getBool("mute")); @@ -968,7 +966,6 @@ void MiscOptionsState::step_impl() if (imgui.doButton(GEN_ID, Vector2(484.0, 120.0), TextManager::OP_FPS)) { mShowFPS = !mShowFPS; - SpeedController::getMainInstance()->setDrawFPS(mShowFPS); } if (mShowFPS) { diff --git a/src/state/ReplaySelectionState.cpp b/src/state/ReplaySelectionState.cpp index 825ab543..f12c5649 100644 --- a/src/state/ReplaySelectionState.cpp +++ b/src/state/ReplaySelectionState.cpp @@ -29,7 +29,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "ReplayState.h" #include "IMGUI.h" #include "TextManager.h" -#include "SpeedController.h" #include "FileSystem.h" #include "replays/IReplayLoader.h" @@ -49,8 +48,6 @@ void ReplaySelectionState::init() if (mReplayFiles.empty()) mSelectedReplay = -1; std::sort(mReplayFiles.rbegin(), mReplayFiles.rend()); - - SpeedController::getMainInstance()->setGameSpeed(75); } void ReplaySelectionState::step_impl() diff --git a/src/state/ReplayState.cpp b/src/state/ReplayState.cpp index 33a3db8b..18068c89 100644 --- a/src/state/ReplayState.cpp +++ b/src/state/ReplayState.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "DuelMatch.h" #include "SoundManager.h" #include "TextManager.h" -#include "SpeedController.h" #include "IUserConfigReader.h" #include "ReplaySelectionState.h" #include "InputManager.h" @@ -72,10 +71,6 @@ void ReplayState::loadReplay(const std::string& file) mMatch->getPlayer(LEFT_PLAYER).setStaticColor(mReplayPlayer->getBlobColor(LEFT_PLAYER)); mMatch->getPlayer(RIGHT_PLAYER).setStaticColor(mReplayPlayer->getBlobColor(RIGHT_PLAYER)); - SpeedController::getMainInstance()->setGameSpeed( - (float)IUserConfigReader::createUserConfigReader("config.xml")->getInteger("gamefps") - ); - //} /* catch (VersionMismatchException& e) @@ -212,12 +207,6 @@ void ReplayState::step_impl() // we just have to jump to the beginning playSound(SoundManager::WHISTLE, ROUND_START_SOUND_VOLUME); - // do we really need this? - // maybe, users want to replay the game on the current speed - SpeedController::getMainInstance()->setGameSpeed( - (float)IUserConfigReader::createUserConfigReader("config.xml")->getInteger("gamefps") - ); - mPaused = false; mPositionJump = 0; } diff --git a/src/state/State.cpp b/src/state/State.cpp index 46b6667a..654040b6 100644 --- a/src/state/State.cpp +++ b/src/state/State.cpp @@ -36,7 +36,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "SoundManager.h" #include "IMGUI.h" #include "TextManager.h" -#include "SpeedController.h" #include "InputManager.h" #include "IScriptableComponent.h" @@ -88,8 +87,6 @@ InputManager& State::getInputMgr() const { MainMenuState::MainMenuState() { - // set main menu fps - SpeedController::getMainInstance()->setGameSpeed(75); } MainMenuState::~MainMenuState() = default;