1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Better implementation of the framerate manager, FPS timer added, minor improvements

This commit is contained in:
beegee1 2011-04-05 17:38:24 +00:00
parent 0aad12ae67
commit 157002fe68
10 changed files with 145 additions and 158 deletions

View File

@ -183,6 +183,14 @@ void CCursorHandler::shiftPos( int &x, int &y )
}
}
void CCursorHandler::centerCursor()
{
SDL_Surface *cursor = this->cursors[mode]->ourImages[number].bitmap;
this->xpos = (screen->w / 2.) - (cursor->w / 2.);
this->ypos = (screen->h / 2.) - (cursor->h / 2.);
SDL_WarpMouse(this->xpos, this->ypos);
}
CCursorHandler::~CCursorHandler()
{
if(help)

View File

@ -35,8 +35,9 @@ public:
void shiftPos( int &x, int &y );
void draw2();
void hide(){Show=0;};
void show(){Show=1;};
void hide() { Show=0; };
void show() { Show=1; };
void centerCursor();
~CCursorHandler();
};

View File

@ -266,7 +266,7 @@ int main(int argc, char** argv)
playIntro();
SDL_FillRect(screen,NULL,0);
SDL_Flip(screen);
CSDL_Ext::update(screen);
loading.join();
tlog0<<"Initialization of VCMI (together): "<<total.getDif()<<std::endl;

View File

@ -105,8 +105,6 @@ CPlayerInterface::CPlayerInterface(int Player)
makingTurn = false;
showingDialog = new CondSh<bool>(false);
sysOpts = GDefaultOptions;
//initializing framerate keeper
//framerate keeper initialized
cingconsole = new CInGameConsole;
terminate_cond.set(false);
firstCall = 1; //if loading will be overwritten in serialize
@ -283,7 +281,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
initMovement(details, ho, hp);
//first initializing done
SDL_framerateDelay(GH.mainFPSmng); // after first move
GH.mainFPSmng->framerateDelay(); // after first move
//main moving
for(int i=1; i<32; i+=2*sysOpts.heroMoveSpeed)
@ -292,7 +290,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
adventureInt->updateScreen = true;
adventureInt->show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(GH.mainFPSmng); //for animation purposes
GH.mainFPSmng->framerateDelay(); //for animation purposes
} //for(int i=1; i<32; i+=4)
//main moving done
@ -1330,18 +1328,11 @@ void CPlayerInterface::update()
if(adventureInt && !adventureInt->selection && GH.topInt() == adventureInt)
return;
GH.updateTime();
GH.handleEvents();
if(adventureInt && !adventureInt->isActive() && adventureInt->scrollingDir) //player forces map scrolling though interface is disabled
GH.totalRedraw();
else
GH.simpleRedraw();
CCS->curh->draw1();
CSDL_Ext::update(screen);
CCS->curh->draw2();
pim->unlock();
}

View File

@ -351,12 +351,7 @@ void CGPreGame::update()
if(SEL)
SEL->update();
CCS->curh->draw1();
SDL_Flip(screen);
CCS->curh->draw2();
GH.topInt()->show(screen);
GH.updateTime();
GH.handleEvents();
}
CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMultiMode MultiPlayer /*= CMenuScreen::SINGLE_PLAYER*/, const std::map<ui32, std::string> *Names /*= NULL*/)

View File

@ -103,6 +103,11 @@ IShowActivable * CGuiHandler::topInt()
}
void CGuiHandler::totalRedraw()
{
this->invalidateTotalRedraw = true;
}
void CGuiHandler::internalTotalRedraw()
{
for(int i=0;i<objsToBlit.size();i++)
objsToBlit[i]->showAll(screen2);
@ -111,6 +116,9 @@ void CGuiHandler::totalRedraw()
if(objsToBlit.size())
objsToBlit.back()->showAll(screen);
this->invalidateTotalRedraw = false;
this->invalidateSimpleRedraw = false;
}
void CGuiHandler::updateTime()
@ -303,11 +311,18 @@ void CGuiHandler::handleMouseMotion(SDL_Event *sEvent)
}
void CGuiHandler::simpleRedraw()
{
this->invalidateSimpleRedraw = true;
}
void CGuiHandler::internalSimpleRedraw()
{
//update only top interface and draw background
if(objsToBlit.size() > 1)
blitAt(screen2,0,0,screen); //blit background
objsToBlit.back()->show(screen); //blit active interface/window
this->invalidateSimpleRedraw = false;
}
void CGuiHandler::handleMoveInterested( const SDL_MouseMotionEvent & motion )
@ -343,14 +358,33 @@ void CGuiHandler::run()
setThreadName(-1, "CGuiHandler::run");
try
{
SDL_initFramerate(mainFPSmng);
CCS->curh->centerCursor();
mainFPSmng->init(); // resets internal clock, needed for FPS manager
while(!terminate)
{
if(curInt)
curInt->update();
curInt->update(); // calls a update and drawing process of the loaded game interface object at the moment
SDL_framerateDelay(mainFPSmng);
//SDL_Delay(20); //give time for other apps
// Handles mouse and key input
GH.updateTime();
GH.handleEvents();
// Redraws the GUI only once during rendering
if (this->invalidateTotalRedraw == true)
internalTotalRedraw();
if (this->invalidateSimpleRedraw == true)
internalSimpleRedraw();
if (SHOW_FPS)
drawFPSCounter();
mainFPSmng->framerateDelay(); // holds a constant FPS
// draw the mouse cursor and update the screen
// todo: bad way of updating the cursor, update screen should be the last statement of the rendering process
CCS->curh->draw1();
CSDL_Ext::update(screen);
CCS->curh->draw2();
}
} HANDLE_EXCEPTION
}
@ -363,8 +397,8 @@ CGuiHandler::CGuiHandler()
terminate = false;
statusbar = NULL;
mainFPSmng = new FPSmanager;
SDL_setFramerate(mainFPSmng, 48);
// Creates the FPS manager and sets the framerate to 48 which is doubled the value of the original Heroes 3 FPS rate
mainFPSmng = new FPSManager(48);
}
CGuiHandler::~CGuiHandler()
@ -377,6 +411,17 @@ void CGuiHandler::breakEventHandling()
current = NULL;
}
void CGuiHandler::drawFPSCounter()
{
const static SDL_Color yellow = {255, 255, 0, 0};
static SDL_Rect overlay = { 0, 0, 64, 32};
Uint32 black = SDL_MapRGB(screen->format, 10, 10, 10);
SDL_FillRect(screen, &overlay, black);
std::string fps = toString(mainFPSmng->fps);
CSDL_Ext::printAt(fps, 10, 10, FONT_BIG, yellow, screen);
}
void CIntObject::activateLClick()
{
GH.lclickable.push_front(this);

View File

@ -511,8 +511,16 @@ public:
/// Handles GUI logic and drawing
class CGuiHandler
{
private:
bool invalidateTotalRedraw;
bool invalidateSimpleRedraw;
void internalTotalRedraw();
void internalSimpleRedraw();
public:
FPSmanager * mainFPSmng; //to keep const framerate
const static bool SHOW_FPS = false; // shows a fps counter when set to true
FPSManager *mainFPSmng; //to keep const framerate
timeHandler th;
std::list<IShowActivable *> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
IStatusBar * statusbar;
@ -539,14 +547,17 @@ public:
CGuiHandler();
~CGuiHandler();
void run();
void totalRedraw(); //forces total redraw (using showAll)
void simpleRedraw(); //update only top interface and draw background from buffer
void run(); // holds the main loop for the whole program after initialization and manages the update/rendering system
void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering
void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering
void popInt(IShowActivable *top); //removes given interface from the top and activates next
void popIntTotally(IShowActivable *top); //deactivates, deletes, removes given interface from the top and activates next
void pushInt(IShowActivable *newInt); //deactivate old top interface, activates this one and pushes to the top
void popInts(int howMany); //pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front
IShowActivable *topInt(); //returns top interface
void updateTime(); //handles timeInterested
void handleEvents(); //takes events from queue and calls interested objects
void handleEvent(SDL_Event *sEvent);
@ -554,6 +565,7 @@ public:
void handleMoveInterested( const SDL_MouseMotionEvent & motion );
void fakeMouseMove();
void breakEventHandling(); //current event won't be propagated anymore
void CGuiHandler::drawFPSCounter(); // draws the FPS to the upper left corner of the screen
ui8 defActionsDef; //default auto actions
ui8 captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
std::list<CIntObject *> createdObj; //stack of objs being created

View File

@ -1,84 +1,41 @@
/*
SDL_framerate: framerate manager
LGPL (c) A. Schiffler
/*
* SDL_framerate.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 "../stdafx.h"
#include "SDL_framerate.h"
#include <SDL.h>
/*
Initialize the framerate manager
*/
void SDL_initFramerate(FPSmanager * manager)
FPSManager::FPSManager(int rate)
{
/*
* Store some sane values
*/
manager->framecount = 0;
manager->rate = FPS_DEFAULT;
manager->rateticks = (1000.0 / (float) FPS_DEFAULT);
manager->lastticks = SDL_GetTicks();
this->rate = rate;
this->rateticks = (1000.0 / (double) rate);
this->fps = 0;
}
/*
Set the framerate in Hz
*/
int SDL_setFramerate(FPSmanager * manager, int rate)
void FPSManager::init()
{
if ((rate >= FPS_LOWER_LIMIT) && (rate <= FPS_UPPER_LIMIT)) {
manager->framecount = 0;
manager->rate = rate;
manager->rateticks = (1000.0 / (float) rate);
return (0);
} else {
return (-1);
}
this->lastticks = SDL_GetTicks();
}
/*
Return the current target framerate in Hz
*/
int SDL_getFramerate(FPSmanager * manager)
void FPSManager::framerateDelay()
{
if (manager == NULL) {
return (-1);
} else {
return (manager->rate);
}
}
/*
Delay execution to maintain a constant framerate. Calculate fps.
*/
void SDL_framerateDelay(FPSmanager * manager)
{
Uint32 current_ticks;
Uint32 target_ticks;
Uint32 the_delay;
/*
* Next frame
*/
manager->framecount++;
/*
* Get/calc ticks
*/
current_ticks = SDL_GetTicks();
target_ticks = manager->lastticks + (Uint32) ((float) manager->framecount * manager->rateticks);
if (current_ticks <= target_ticks) {
the_delay = target_ticks - current_ticks;
SDL_Delay(the_delay);
} else {
manager->framecount = 0;
manager->lastticks = SDL_GetTicks();
}
Uint32 currentTicks = SDL_GetTicks();
double diff = currentTicks - this->lastticks;
if (diff < this->rateticks) // FPS is higher than it should be, then wait some time
{
SDL_Delay(ceil(this->rateticks) - diff);
}
this->fps = ceil(1000. / (SDL_GetTicks() - this->lastticks));
this->lastticks = SDL_GetTicks();
}

View File

@ -1,65 +1,33 @@
/*
SDL_framerate: framerate manager
LGPL (c) A. Schiffler
/*
* timeHandler.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
*
*/
#ifndef _SDL_framerate_h
#define _SDL_framerate_h
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
/// A fps manager which holds game updates at a constant rate
class FPSManager
{
private:
double rateticks;
unsigned int lastticks;
int rate;
public:
int fps; // the actual fps value
FPSManager(int rate); // initializes the manager with a given fps rate
void FPSManager::init(); // 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
};
#endif
/* --- */
#include "SDL.h"
/* --------- Definitions */
/* Some rates in Hz */
#define FPS_UPPER_LIMIT 200
#define FPS_LOWER_LIMIT 1
#define FPS_DEFAULT 30
/* --------- Structure variables */
typedef struct {
Uint32 framecount;
float rateticks;
Uint32 lastticks;
Uint32 rate;
} FPSmanager;
/* --------- Function prototypes */
#ifdef WIN32
#ifdef BUILD_DLL
#define DLLINTERFACE __declspec(dllexport)
#else
#define DLLINTERFACE __declspec(dllimport)
#endif
#else
#define DLLINTERFACE
#endif
/* Functions return 0 or value for sucess and -1 for error */
void SDL_initFramerate(FPSmanager * manager);
int SDL_setFramerate(FPSmanager * manager, int rate);
int SDL_getFramerate(FPSmanager * manager);
void SDL_framerateDelay(FPSmanager * manager);
/* --- */
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#endif /* _SDL_framerate_h */

View File

@ -135,7 +135,6 @@ const int BFIELD_SIZE = BFIELD_WIDTH * BFIELD_HEIGHT;
const int SPELLBOOK_GOLD_COST = 500;
//for battle stacks' positions
struct THex
{
@ -348,6 +347,17 @@ enum EAlignment
{
GOOD, EVIL, NEUTRAL
};
// Converts an int/double or any data type you wish to a string
template<typename T>
std::string toString(const T& value)
{
std::ostringstream oss;
oss << value;
return oss.str();
}
//uncomment to make it work
//#define MARK_BLOCKED_POSITIONS
//#define MARK_VISITABLE_POSITIONS