/*
	Asteroids
    Copyright (C) 2006  Darragh Coy.

    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 3 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, see <http://www.gnu.org/licenses/>.
*/

/*##############################################################################

Module name: Timer.cpp
Purpose:     Stores and maintains timing information for the game. This module
             is vital to maintain framerate independant movement, regardless of
             how fast or slow the game is running. Because of the need for precision
             when timing, high precision data types are used when storing and manipulating
             the time- such as 64-bit ints and 80-bit IEEE floats.

##############################################################################*/

#include "Timer.h"

/*******************************************************************************
Constants
*******************************************************************************/

// Number of frames over which the current frame time is averaged

static const unsigned FRAME_TIME_UPDATE_FRAMES = 8;

/*******************************************************************************
Variables
*******************************************************************************/

float       frameTimeSeconds;       // Current frame time in seconds. Averaged every so often over a number of frames
unsigned    frameTimesCounted;      // Number of frames added to accumalated frame times
unsigned    frameTimeClocksAccum;   // Accumlated clock times for a number of frames
unsigned    lastTimeStamp;          // Time stamp for the last frame

/*******************************************************************************

Name:       Timer_Init
Purpose:    Initialises the timer.
Parameters: None
Returns:    None

*******************************************************************************/

void Timer_Init()
{
     // Reset all variables:

     frameTimeSeconds       = 0;
     frameTimesCounted      = 0;
     frameTimeClocksAccum   = 0;
     lastTimeStamp          = clock();
}

/*******************************************************************************

Name:       Timer_Update
Purpose:    Updates the timer and calculates how long the last frame took in
            seconds. We can use this to adjust movement based on how fast or not
            the game is running.
Parameters: None
Returns:    None

*******************************************************************************/

void Timer_Update ( void )
{
     // Get the current time stamp:

     unsigned currentTimeStamp = clock();

     // Calculate how many tics have passed since the last call to update

     unsigned ticsElapsed = currentTimeStamp - lastTimeStamp;

     // Add this to the accumalated frame times and increment number of frame times accumalated

     frameTimeClocksAccum += ticsElapsed; frameTimesCounted++;

     // Save the current time stamp as the last time stamp

     lastTimeStamp = currentTimeStamp;

     // See if it is time to update the frame time:

     if ( frameTimesCounted >= FRAME_TIME_UPDATE_FRAMES )
     {
         // Update the frame time:

         frameTimeSeconds = float(frameTimeClocksAccum) / ( 1000.0f * float(FRAME_TIME_UPDATE_FRAMES) );

         // Reset accumalated time variables

         frameTimeClocksAccum   = 0;
         frameTimesCounted      = 0;
     }
}

/*******************************************************************************

Name:       Timer_FrameTime()
Purpose:    Returns the number of seconds the last frame took. Inlined for speed
Parameters: None
Returns:    None

*******************************************************************************/

float Timer_FrameTime(){ return frameTimeSeconds; }

/*******************************************************************************

Name:       Timer_Unpause()
Purpose:    Discounts any time passed since the last call to Update()
Parameters: None
Returns:    None

*******************************************************************************/

void Timer_Unpause()
{
     // Reset accumalated time variables

     frameTimeClocksAccum   = 0;
     frameTimesCounted      = 0;

     // Set the current time stamp:

     lastTimeStamp = clock();
}
