mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Better implementation of the framerate manager, FPS timer added, minor improvements
This commit is contained in:
		| @@ -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) | ||||
|   | ||||
| @@ -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(); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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*/) | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
							
								
								
									
										12
									
								
								global.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								global.h
									
									
									
									
									
								
							| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user