// Copyright 1994 Brad Pitzel
//
// Feel free to use/distribute/modify as long as credit/copyrights for myself 
// are included.

// This is a class to simply the job of maintaining a fixed 
// frames-per-second animation rate in the program.
// Search for "Timer::" in sasteroids.c to see how its used.

#ifndef __Timer__
#define __Timer__

#include <sys/time.h>
#include <unistd.h>


// used to get fixed animation rates on different
// speed computers
class Timer {
    public:
    
    	// set frame rate to 'f' frames per second
    	static void setFrameRate( int f );
	static int  FrameRate() { return VframeRate; }
	    	
    	// call once before entering animation loops
    	static void init();
    
    	// pause required amount of time to get proper frame rate
    	// returns the amount of time passed since last sync() or
    	// init() call in usec.
    	static long sync();

    private:
    	static timeval	VlastClk, VnewClk;
	static long	VfTime, Vlast;

    	static int VframeRate;
    };


// set frame rate to 'f' frames per second
inline void Timer::setFrameRate( int f ) 
	{ 
	VframeRate = f;
	VfTime = 1000000/f; 
	}
    	
// call once before entering animation loops
inline void Timer::init() 
	{ 
	gettimeofday(&VlastClk,NULL); 
	gettimeofday(&VnewClk,NULL); 
	Vlast = VlastClk.tv_usec;
	}
    
// pause required amount of time to get proper frame rate
inline long Timer::sync()
    	{
    	long delta(0),wait(0);
    	
    	gettimeofday(&VnewClk, NULL);	// get current time

	// figure out how long to wait. Min is 0 usec, max is ftime.
    	wait  = ((VfTime - VnewClk.tv_usec + Vlast) >? 0) <? VfTime;
    	usleep( wait );
    	
    	// This should approx. be the current time, but if usleep took
    	// alot longer than it should have, the next 'wait' value will
    	// be shorter. This will SOMEWHAT even out the peformance under
    	// varying CPU loads.  Needs improvement tho (need real-time linux :-)
    	Vlast = VnewClk.tv_usec + wait;
	
	// calc the time between sleeps (not including sleeping time)
	// This give you the time between calls to sync(), therefore the
	// time to create one frame of animation.
   	delta = VnewClk.tv_usec - VlastClk.tv_usec;
	gettimeofday(&VlastClk, NULL);
	
	return delta;
	}

#endif
