1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

Framerate manager is now in a separate file and private member of GH

This commit is contained in:
Ivan Savenko
2023-05-13 00:15:48 +03:00
parent 0a874cd89e
commit 03df274450
18 changed files with 156 additions and 111 deletions

View File

@@ -16,6 +16,7 @@
#include "mainmenu/CMainMenu.h" #include "mainmenu/CMainMenu.h"
#include "mainmenu/CPrologEpilogVideo.h" #include "mainmenu/CPrologEpilogVideo.h"
#include "gui/CursorHandler.h" #include "gui/CursorHandler.h"
#include "gui/FramerateManager.h"
#include "CPlayerInterface.h" #include "CPlayerInterface.h"
#include "CVideoHandler.h" #include "CVideoHandler.h"
#include "CMusicHandler.h" #include "CMusicHandler.h"
@@ -599,8 +600,7 @@ static void mainLoop()
fsChanged([](const JsonNode &newState){ CGuiHandler::pushUserEvent(EUserEvent::FULLSCREEN_TOGGLED); }); fsChanged([](const JsonNode &newState){ CGuiHandler::pushUserEvent(EUserEvent::FULLSCREEN_TOGGLED); });
inGuiThread.reset(new bool(true)); inGuiThread.reset(new bool(true));
assert(GH.mainFPSmng); GH.framerateManager().init(settings["video"]["targetfps"].Integer());
GH.mainFPSmng->init(settings["video"]["targetfps"].Integer());
while(1) //main SDL events loop while(1) //main SDL events loop
{ {

View File

@@ -31,6 +31,7 @@ set(client_SRCS
gui/CIntObject.cpp gui/CIntObject.cpp
gui/CursorHandler.cpp gui/CursorHandler.cpp
gui/InterfaceObjectConfigurable.cpp gui/InterfaceObjectConfigurable.cpp
gui/FramerateManager.cpp
gui/NotificationHandler.cpp gui/NotificationHandler.cpp
gui/ShortcutHandler.cpp gui/ShortcutHandler.cpp
@@ -162,6 +163,7 @@ set(client_HEADERS
gui/CIntObject.h gui/CIntObject.h
gui/CursorHandler.h gui/CursorHandler.h
gui/InterfaceObjectConfigurable.h gui/InterfaceObjectConfigurable.h
gui/FramerateManager.h
gui/MouseButton.h gui/MouseButton.h
gui/NotificationHandler.h gui/NotificationHandler.h
gui/Shortcut.h gui/Shortcut.h

View File

@@ -370,7 +370,7 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
auto packet_duration = frame->duration; auto packet_duration = frame->duration;
#endif #endif
double frameEndTime = (frame->pts + packet_duration) * av_q2d(format->streams[stream]->time_base); double frameEndTime = (frame->pts + packet_duration) * av_q2d(format->streams[stream]->time_base);
frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.0; frameTime += GH.getFrameDeltaMilliseconds() / 1000.0;
if (frameTime >= frameEndTime ) if (frameTime >= frameEndTime )
{ {
@@ -450,6 +450,7 @@ bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
pos.x = x; pos.x = x;
pos.y = y; pos.y = y;
frameTime = 0.0;
while(nextFrame()) while(nextFrame())
{ {
@@ -461,10 +462,15 @@ bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
SDL_RenderCopy(mainRenderer, texture, nullptr, &rect); SDL_RenderCopy(mainRenderer, texture, nullptr, &rect);
SDL_RenderPresent(mainRenderer); SDL_RenderPresent(mainRenderer);
// Wait 3 frames #if (LIBAVUTIL_VERSION_MAJOR < 58)
GH.mainFPSmng->framerateDelay(); auto packet_duration = frame->pkt_duration;
GH.mainFPSmng->framerateDelay(); #else
GH.mainFPSmng->framerateDelay(); auto packet_duration = frame->duration;
#endif
double frameDurationSec = packet_duration * av_q2d(format->streams[stream]->time_base);
uint32_t timeToSleepMillisec = 1000 * (frameDurationSec);
boost::this_thread::sleep(boost::posix_time::millisec(timeToSleepMillisec));
} }
return true; return true;

View File

@@ -59,7 +59,7 @@ AdventureMapInterface::AdventureMapInterface():
shortcuts->setState(EAdventureState::MAKING_TURN); shortcuts->setState(EAdventureState::MAKING_TURN);
widget->getMapView()->onViewMapActivated(); widget->getMapView()->onViewMapActivated();
addUsedEvents(KEYBOARD); addUsedEvents(KEYBOARD | TIME);
} }
void AdventureMapInterface::onMapViewMoved(const Rect & visibleArea, int mapLevel) void AdventureMapInterface::onMapViewMoved(const Rect & visibleArea, int mapLevel)
@@ -139,18 +139,20 @@ void AdventureMapInterface::showAll(SDL_Surface * to)
void AdventureMapInterface::show(SDL_Surface * to) void AdventureMapInterface::show(SDL_Surface * to)
{ {
handleMapScrollingUpdate();
CIntObject::show(to); CIntObject::show(to);
LOCPLINT->cingconsole->show(to); LOCPLINT->cingconsole->show(to);
} }
void AdventureMapInterface::handleMapScrollingUpdate() void AdventureMapInterface::tick(uint32_t msPassed)
{
handleMapScrollingUpdate(msPassed);
}
void AdventureMapInterface::handleMapScrollingUpdate(uint32_t timePassed)
{ {
/// Width of window border, in pixels, that triggers map scrolling /// Width of window border, in pixels, that triggers map scrolling
static constexpr uint32_t borderScrollWidth = 15; static constexpr uint32_t borderScrollWidth = 15;
uint32_t timePassed = GH.mainFPSmng->getElapsedMilliseconds();
uint32_t scrollSpeedPixels = settings["adventure"]["scrollSpeedPixels"].Float(); uint32_t scrollSpeedPixels = settings["adventure"]["scrollSpeedPixels"].Float();
uint32_t scrollDistance = scrollSpeedPixels * timePassed / 1000; uint32_t scrollDistance = scrollSpeedPixels * timePassed / 1000;

View File

@@ -75,7 +75,7 @@ private:
const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const; const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const;
/// check and if necessary reacts on scrolling by moving cursor to screen edge /// check and if necessary reacts on scrolling by moving cursor to screen edge
void handleMapScrollingUpdate(); void handleMapScrollingUpdate(uint32_t msPassed);
void showMoveDetailsInStatusbar(const CGHeroInstance & hero, const CGPathNode & pathNode); void showMoveDetailsInStatusbar(const CGHeroInstance & hero, const CGPathNode & pathNode);
@@ -93,6 +93,7 @@ protected:
void activate() override; void activate() override;
void deactivate() override; void deactivate() override;
void tick(uint32_t msPassed) override;
void show(SDL_Surface * to) override; void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override; void showAll(SDL_Surface * to) override;

View File

@@ -381,7 +381,7 @@ bool MovementAnimation::init()
void MovementAnimation::nextFrame() void MovementAnimation::nextFrame()
{ {
progress += float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000 * progressPerSecond; progress += float(GH.getFrameDeltaMilliseconds()) / 1000 * progressPerSecond;
//moving instructions //moving instructions
myAnim->pos.x = static_cast<Sint16>(begX + distanceX * progress ); myAnim->pos.x = static_cast<Sint16>(begX + distanceX * progress );
@@ -579,7 +579,7 @@ bool ColorTransformAnimation::init()
void ColorTransformAnimation::nextFrame() void ColorTransformAnimation::nextFrame()
{ {
float elapsed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; float elapsed = GH.getFrameDeltaMilliseconds() / 1000.f;
float fullTime = AnimationControls::getFadeInDuration(); float fullTime = AnimationControls::getFadeInDuration();
float delta = elapsed / fullTime; float delta = elapsed / fullTime;
totalProgress += delta; totalProgress += delta;
@@ -1029,7 +1029,7 @@ void EffectAnimation::playEffect()
{ {
if(elem.effectID == ID) if(elem.effectID == ID)
{ {
elem.currentFrame += AnimationControls::getSpellEffectSpeed() * GH.mainFPSmng->getElapsedMilliseconds() / 1000; elem.currentFrame += AnimationControls::getSpellEffectSpeed() * GH.getFrameDeltaMilliseconds() / 1000;
if(elem.currentFrame >= elem.animation->size()) if(elem.currentFrame >= elem.animation->size())
{ {

View File

@@ -220,7 +220,7 @@ void BattleHero::render(Canvas & canvas)
canvas.draw(flagFrame, flagPosition); canvas.draw(flagFrame, flagPosition);
canvas.draw(heroFrame, heroPosition); canvas.draw(heroFrame, heroPosition);
float timePassed = float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000.f; float timePassed = float(GH.getFrameDeltaMilliseconds()) / 1000.f;
flagCurrentFrame += currentSpeed * timePassed; flagCurrentFrame += currentSpeed * timePassed;
currentFrame += currentSpeed * timePassed; currentFrame += currentSpeed * timePassed;

View File

@@ -161,7 +161,7 @@ void BattleObstacleController::collectRenderableObjects(BattleRenderer & rendere
void BattleObstacleController::update() void BattleObstacleController::update()
{ {
timePassed += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; timePassed += GH.getFrameDeltaMilliseconds() / 1000.f;
} }
std::shared_ptr<IImage> BattleObstacleController::getObstacleImage(const CObstacleInstance & oi) std::shared_ptr<IImage> BattleObstacleController::getObstacleImage(const CObstacleInstance & oi)

View File

@@ -59,14 +59,14 @@ void ProjectileMissile::show(Canvas & canvas)
canvas.draw(image, pos); canvas.draw(image, pos);
} }
float timePassed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; float timePassed = GH.getFrameDeltaMilliseconds() / 1000.f;
progress += timePassed * speed; progress += timePassed * speed;
} }
void ProjectileAnimatedMissile::show(Canvas & canvas) void ProjectileAnimatedMissile::show(Canvas & canvas)
{ {
ProjectileMissile::show(canvas); ProjectileMissile::show(canvas);
frameProgress += AnimationControls::getSpellEffectSpeed() * GH.mainFPSmng->getElapsedMilliseconds() / 1000; frameProgress += AnimationControls::getSpellEffectSpeed() * GH.getFrameDeltaMilliseconds() / 1000;
size_t animationSize = animation->size(reverse ? 1 : 0); size_t animationSize = animation->size(reverse ? 1 : 0);
while (frameProgress > animationSize) while (frameProgress > animationSize)
frameProgress -= animationSize; frameProgress -= animationSize;
@@ -76,7 +76,7 @@ void ProjectileAnimatedMissile::show(Canvas & canvas)
void ProjectileCatapult::show(Canvas & canvas) void ProjectileCatapult::show(Canvas & canvas)
{ {
frameProgress += AnimationControls::getSpellEffectSpeed() * GH.mainFPSmng->getElapsedMilliseconds() / 1000; frameProgress += AnimationControls::getSpellEffectSpeed() * GH.getFrameDeltaMilliseconds() / 1000;
int frameCounter = std::floor(frameProgress); int frameCounter = std::floor(frameProgress);
int frameIndex = (frameCounter + 1) % animation->size(0); int frameIndex = (frameCounter + 1) % animation->size(0);
@@ -91,7 +91,7 @@ void ProjectileCatapult::show(Canvas & canvas)
canvas.draw(image, pos); canvas.draw(image, pos);
} }
float timePassed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; float timePassed = GH.getFrameDeltaMilliseconds() / 1000.f;
progress += timePassed * speed; progress += timePassed * speed;
} }
@@ -136,7 +136,7 @@ void ProjectileRay::show(Canvas & canvas)
} }
} }
float timePassed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; float timePassed = GH.getFrameDeltaMilliseconds() / 1000.f;
progress += timePassed * speed; progress += timePassed * speed;
} }

View File

@@ -335,7 +335,7 @@ void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
} }
stackAnimation[stack->unitId()]->nextFrame(canvas, fullFilter, facingRight(stack)); // do actual blit stackAnimation[stack->unitId()]->nextFrame(canvas, fullFilter, facingRight(stack)); // do actual blit
stackAnimation[stack->unitId()]->incrementFrame(float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000); stackAnimation[stack->unitId()]->incrementFrame(float(GH.getFrameDeltaMilliseconds()) / 1000);
} }
void BattleStacksController::update() void BattleStacksController::update()

View File

@@ -14,6 +14,7 @@
#include "CIntObject.h" #include "CIntObject.h"
#include "CursorHandler.h" #include "CursorHandler.h"
#include "ShortcutHandler.h" #include "ShortcutHandler.h"
#include "FramerateManager.h"
#include "../CGameInfo.h" #include "../CGameInfo.h"
#include "../render/Colors.h" #include "../render/Colors.h"
@@ -100,7 +101,7 @@ void CGuiHandler::init()
{ {
screenHandlerInstance = std::make_unique<ScreenHandler>(); screenHandlerInstance = std::make_unique<ScreenHandler>();
shortcutsHandlerInstance = std::make_unique<ShortcutHandler>(); shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
mainFPSmng = new CFramerateManager(settings["video"]["targetfps"].Integer()); framerateManagerInstance = std::make_unique<FramerateManager>(settings["video"]["targetfps"].Integer());
isPointerRelativeMode = settings["general"]["userRelativePointer"].Bool(); isPointerRelativeMode = settings["general"]["userRelativePointer"].Bool();
pointerSpeedMultiplier = settings["general"]["relativePointerSpeedMultiplier"].Float(); pointerSpeedMultiplier = settings["general"]["relativePointerSpeedMultiplier"].Float();
@@ -193,7 +194,7 @@ void CGuiHandler::totalRedraw()
void CGuiHandler::updateTime() void CGuiHandler::updateTime()
{ {
int ms = mainFPSmng->getElapsedMilliseconds(); int ms = framerateManagerInstance->getElapsedMilliseconds();
std::list<CIntObject*> hlp = timeinterested; std::list<CIntObject*> hlp = timeinterested;
for (auto & elem : hlp) for (auto & elem : hlp)
{ {
@@ -692,10 +693,9 @@ void CGuiHandler::renderFrame()
disposed.clear(); disposed.clear();
} }
mainFPSmng->framerateDelay(); // holds a constant FPS framerateManagerInstance->framerateDelay(); // holds a constant FPS
} }
CGuiHandler::CGuiHandler() CGuiHandler::CGuiHandler()
: lastClick(-500, -500) : lastClick(-500, -500)
, lastClickTime(0) , lastClickTime(0)
@@ -705,7 +705,6 @@ CGuiHandler::CGuiHandler()
, mouseButtonsMask(0) , mouseButtonsMask(0)
, continueEventHandling(true) , continueEventHandling(true)
, curInt(nullptr) , curInt(nullptr)
, mainFPSmng(nullptr)
, statusbar(nullptr) , statusbar(nullptr)
{ {
terminate_cond = new CondSh<bool>(false); terminate_cond = new CondSh<bool>(false);
@@ -713,7 +712,6 @@ CGuiHandler::CGuiHandler()
CGuiHandler::~CGuiHandler() CGuiHandler::~CGuiHandler()
{ {
delete mainFPSmng;
delete terminate_cond; delete terminate_cond;
} }
@@ -722,6 +720,11 @@ ShortcutHandler & CGuiHandler::shortcutsHandler()
return *shortcutsHandlerInstance; return *shortcutsHandlerInstance;
} }
FramerateManager & CGuiHandler::framerateManager()
{
return *framerateManagerInstance;
}
void CGuiHandler::moveCursorToPosition(const Point & position) void CGuiHandler::moveCursorToPosition(const Point & position)
{ {
SDL_WarpMouseInWindow(mainWindow, position.x, position.y); SDL_WarpMouseInWindow(mainWindow, position.x, position.y);
@@ -756,6 +759,11 @@ const Point & CGuiHandler::getCursorPosition() const
return cursorPosition; return cursorPosition;
} }
uint32_t CGuiHandler::getFrameDeltaMilliseconds() const
{
return framerateManagerInstance->getElapsedMilliseconds();
}
Point CGuiHandler::screenDimensions() const Point CGuiHandler::screenDimensions() const
{ {
return Point(screen->w, screen->h); return Point(screen->w, screen->h);
@@ -783,7 +791,7 @@ void CGuiHandler::drawFPSCounter()
static SDL_Rect overlay = { 0, 0, 64, 32}; static SDL_Rect overlay = { 0, 0, 64, 32};
uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10); uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10);
SDL_FillRect(screen, &overlay, black); SDL_FillRect(screen, &overlay, black);
std::string fps = std::to_string(mainFPSmng->getFramerate()); std::string fps = std::to_string(framerateManagerInstance->getFramerate());
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10)); graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10));
} }
@@ -823,55 +831,3 @@ void CGuiHandler::onScreenResize()
totalRedraw(); totalRedraw();
} }
CFramerateManager::CFramerateManager(int newRate)
: rate(0)
, rateticks(0)
, fps(0)
, accumulatedFrames(0)
, accumulatedTime(0)
, lastticks(0)
, timeElapsed(0)
{
init(newRate);
}
void CFramerateManager::init(int newRate)
{
rate = newRate;
rateticks = 1000.0 / rate;
this->lastticks = SDL_GetTicks();
}
void CFramerateManager::framerateDelay()
{
ui32 currentTicks = SDL_GetTicks();
timeElapsed = currentTicks - lastticks;
accumulatedFrames++;
// FPS is higher than it should be, then wait some time
if(timeElapsed < rateticks)
{
int timeToSleep = (uint32_t)ceil(this->rateticks) - timeElapsed;
boost::this_thread::sleep(boost::posix_time::milliseconds(timeToSleep));
}
currentTicks = SDL_GetTicks();
// recalculate timeElapsed for external calls via getElapsed()
// limit it to 100 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
timeElapsed = std::min<ui32>(currentTicks - lastticks, 100);
lastticks = SDL_GetTicks();
accumulatedTime += timeElapsed;
if(accumulatedFrames >= 100)
{
//about 2 second should be passed
fps = static_cast<int>(ceil(1000.0 / (accumulatedTime / accumulatedFrames)));
accumulatedTime = 0;
accumulatedFrames = 0;
}
}

View File

@@ -23,7 +23,7 @@ union SDL_Event;
struct SDL_MouseMotionEvent; struct SDL_MouseMotionEvent;
class ShortcutHandler; class ShortcutHandler;
class CFramerateManager; class FramerateManager;
class IStatusBar; class IStatusBar;
class CIntObject; class CIntObject;
class IUpdateable; class IUpdateable;
@@ -44,32 +44,11 @@ enum class EUserEvent
FORCE_QUIT, //quit client without question FORCE_QUIT, //quit client without question
}; };
// A fps manager which holds game updates at a constant rate
class CFramerateManager
{
private:
double rateticks;
ui32 lastticks;
ui32 timeElapsed;
int rate;
int fps; // the actual fps value
ui32 accumulatedTime;
ui32 accumulatedFrames;
public:
CFramerateManager(int newRate); // initializes the manager with a given fps rate
void init(int newRate); // needs to be called directly before the main game loop to reset the internal timer
void framerateDelay(); // needs to be called every game update cycle
ui32 getElapsedMilliseconds() const {return this->timeElapsed;}
ui32 getFrameNumber() const { return accumulatedFrames; }
ui32 getFramerate() const { return fps; };
};
// Handles GUI logic and drawing // Handles GUI logic and drawing
class CGuiHandler class CGuiHandler
{ {
public: public:
CFramerateManager * mainFPSmng; //to keep const framerate
std::list<std::shared_ptr<IShowActivatable>> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on) std::list<std::shared_ptr<IShowActivatable>> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
std::shared_ptr<IStatusBar> statusbar; std::shared_ptr<IStatusBar> statusbar;
@@ -97,6 +76,7 @@ private:
CIntObjectList textInterested; CIntObjectList textInterested;
std::unique_ptr<IScreenHandler> screenHandlerInstance; std::unique_ptr<IScreenHandler> screenHandlerInstance;
std::unique_ptr<FramerateManager> framerateManagerInstance;
void handleMouseButtonClick(CIntObjectList & interestedObjs, MouseButton btn, bool isPressed); void handleMouseButtonClick(CIntObjectList & interestedObjs, MouseButton btn, bool isPressed);
void processLists(const ui16 activityFlag, std::function<void (std::list<CIntObject*> *)> cb); void processLists(const ui16 activityFlag, std::function<void (std::list<CIntObject*> *)> cb);
@@ -117,7 +97,9 @@ public:
const Point & getCursorPosition() const; const Point & getCursorPosition() const;
ShortcutHandler & shortcutsHandler(); ShortcutHandler & shortcutsHandler();
FramerateManager & framerateManager();
uint32_t getFrameDeltaMilliseconds() const;
Point screenDimensions() const; Point screenDimensions() const;
/// returns true if at least one mouse button is pressed /// returns true if at least one mouse button is pressed

View File

@@ -250,7 +250,7 @@ void CursorHandler::updateSpellcastCursor()
{ {
static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame
frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; frameTime += GH.getFrameDeltaMilliseconds() / 1000.f;
size_t newFrame = frame; size_t newFrame = frame;
while (frameTime >= frameDisplayDuration) while (frameTime >= frameDisplayDuration)

View File

@@ -0,0 +1,65 @@
/*
* FramerateManager.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "FramerateManager.h"
#include <SDL_timer.h>
FramerateManager::FramerateManager(int newRate)
: rate(0)
, rateticks(0)
, fps(0)
, accumulatedFrames(0)
, accumulatedTime(0)
, lastticks(0)
, timeElapsed(0)
{
init(newRate);
}
void FramerateManager::init(int newRate)
{
rate = newRate;
rateticks = 1000.0 / rate;
this->lastticks = SDL_GetTicks();
}
void FramerateManager::framerateDelay()
{
ui32 currentTicks = SDL_GetTicks();
timeElapsed = currentTicks - lastticks;
accumulatedFrames++;
// FPS is higher than it should be, then wait some time
if(timeElapsed < rateticks)
{
int timeToSleep = (uint32_t)ceil(this->rateticks) - timeElapsed;
boost::this_thread::sleep(boost::posix_time::milliseconds(timeToSleep));
}
currentTicks = SDL_GetTicks();
// recalculate timeElapsed for external calls via getElapsed()
// limit it to 100 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
timeElapsed = std::min<ui32>(currentTicks - lastticks, 100);
lastticks = SDL_GetTicks();
accumulatedTime += timeElapsed;
if(accumulatedFrames >= 100)
{
//about 2 second should be passed
fps = static_cast<int>(ceil(1000.0 / (accumulatedTime / accumulatedFrames)));
accumulatedTime = 0;
accumulatedFrames = 0;
}
}

View File

@@ -0,0 +1,31 @@
/*
* FramerateManager.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
// A fps manager which holds game updates at a constant rate
class FramerateManager
{
private:
double rateticks;
ui32 lastticks;
ui32 timeElapsed;
int rate;
int fps; // the actual fps value
ui32 accumulatedTime;
ui32 accumulatedFrames;
public:
FramerateManager(int newRate); // initializes the manager with a given fps rate
void init(int newRate); // needs to be called directly before the main game loop to reset the internal timer
void framerateDelay(); // needs to be called every game update cycle
ui32 getElapsedMilliseconds() const {return this->timeElapsed;}
ui32 getFrameNumber() const { return accumulatedFrames; }
ui32 getFramerate() const { return fps; };
};

View File

@@ -66,13 +66,13 @@ void BasicMapView::render(Canvas & target, bool fullUpdate)
void BasicMapView::show(SDL_Surface * to) void BasicMapView::show(SDL_Surface * to)
{ {
controller->updateBefore(GH.mainFPSmng->getElapsedMilliseconds()); controller->updateBefore(GH.getFrameDeltaMilliseconds());
Canvas target(to); Canvas target(to);
CSDL_Ext::CClipRectGuard guard(to, pos); CSDL_Ext::CClipRectGuard guard(to, pos);
render(target, false); render(target, false);
controller->updateAfter(GH.mainFPSmng->getElapsedMilliseconds()); controller->updateAfter(GH.getFrameDeltaMilliseconds());
} }
void BasicMapView::showAll(SDL_Surface * to) void BasicMapView::showAll(SDL_Surface * to)

View File

@@ -395,7 +395,7 @@ void CShowableAnim::show(SDL_Surface * to)
if ((flags & PLAY_ONCE) && frame + 1 == last) if ((flags & PLAY_ONCE) && frame + 1 == last)
return; return;
frameTimePassed += GH.mainFPSmng->getElapsedMilliseconds(); frameTimePassed += GH.getFrameDeltaMilliseconds();
if(frameTimePassed >= frameTimeTotal) if(frameTimePassed >= frameTimeTotal)
{ {

View File

@@ -215,7 +215,7 @@ void CBuildingRect::show(SDL_Surface * to)
} }
if(stateTimeCounter < BUILD_ANIMATION_FINISHED_TIMEPOINT) if(stateTimeCounter < BUILD_ANIMATION_FINISHED_TIMEPOINT)
stateTimeCounter += GH.mainFPSmng->getElapsedMilliseconds(); stateTimeCounter += GH.getFrameDeltaMilliseconds();
} }
void CBuildingRect::showAll(SDL_Surface * to) void CBuildingRect::showAll(SDL_Surface * to)