C++ - using glfwGetTime() for a fixed time step - c++

After doing some research and debugging in my C++ project with glfwGetTime(), I'm having trouble making a game loop for my project. As far as time goes I really only worked with nanoseconds in Java and on the GLFW website it states that the function returns the time in seconds. How would I make a fixed time step loop with glfwGetTime()?
What I have now -
while(!glfwWindowShouldClose(window))
{
double now = glfwGetTime();
double delta = now - lastTime;
lastTime = now;
accumulator += delta;
while(accumulator >= OPTIMAL_TIME) // OPTIMAL_TIME = 1 / 60
{
//tick
accumulator -= OPTIMAL_TIME;
}
}

All you need is this code for limiting updates, but keeping the rendering at highest possible frames. The code is based on this tutorial which explains it very well. All I did was to implement the same principle with GLFW and C++.
static double limitFPS = 1.0 / 60.0;
double lastTime = glfwGetTime(), timer = lastTime;
double deltaTime = 0, nowTime = 0;
int frames = 0 , updates = 0;
// - While window is alive
while (!window.closed()) {
// - Measure time
nowTime = glfwGetTime();
deltaTime += (nowTime - lastTime) / limitFPS;
lastTime = nowTime;
// - Only update at 60 frames / s
while (deltaTime >= 1.0){
update(); // - Update function
updates++;
deltaTime--;
}
// - Render at maximum possible frames
render(); // - Render function
frames++;
// - Reset after one second
if (glfwGetTime() - timer > 1.0) {
timer ++;
std::cout << "FPS: " << frames << " Updates:" << updates << std::endl;
updates = 0, frames = 0;
}
}
You should have a function update() for updating game logic and a render() for rendering. Hope this helps.

Related

float outputs differently in different consoles

I am running the same OpenGL executable in CLion and cmd, but they show different outputs. CLion shows the right number, cmd shows inf and sometimes the number. cout does the same.
(I've mitigated all ogl calls from the code since they're unnecessary)
The code to that is:
int i = 0;
auto lastTime = std::chrono::high_resolution_clock::now();
while ... {
auto currentTime = std::chrono::high_resolution_clock::now();
if (i % 10000 == 0) {
auto deltaTime = std::chrono::duration_cast<std::chrono::duration<float>>(currentTime - lastTime).count();
printf("FPS: %10.0f\n", 1.0f / deltaTime);
}
i++;
lastTime = currentTime;
}
CLion left, cmd right
As Peter pointed out, the problem is that some iterations take less time than the resolution of the clock being used and that time in turn depends on the environment where the program is executed.
A solution to such problems could be to measure the time for X iterations (10000 in the following example) and then calculate the average time:
int i = 0;
auto lastTime = std::chrono::high_resolution_clock::now();
while ... {
if (++i == 10000) {
auto currentTime = std::chrono::high_resolution_clock::now();
auto deltaTime = std::chrono::duration_cast<std::chrono::duration<float>>(currentTime - lastTime).count();
deltaTime /= 10000.0f; //average time for 1 iteration
printf("FPS: %10.0f\n", 1.0f / deltaTime);
lastTime = currentTime;
i = 0; //reset counter to prevent overflow in long runs
}
}

Real-time based increment / decrement in C++ console

Is there a way to increment / decrement value of a varaible in correspondence to the real-time in a simple C++ console application without using third-party libraries.
For, e.g. in Unity3D game engine, there is something called Time.DeltaTime which gives the time it took to complete last frame. Now, I understand there are no draw update functions or frames in a console app, however what I'm trying to do is able to increment / decrement value of a variable such that, it changes with respect to the time something like,
variable = 0
variable = variable + Time.DeltaTime
so that the variable value increment each second. Is something like this possible in C++ 11 ? so, say if speed is 5 then after 5 seconds the variable has a value 5.
Bascially, I am creating a simple particle system where I want the particles to die after their MAX_AGE is reached. I am not sure how to implement that in a simple C++ console app.
For simple timing you can use std::chrono::system_clock. The tbb::tick_count is a better delta timer, but you said no third party libraries.
As you already know, delta time is the final time, minus the original time.
dt= t-t0
This delta time, though, is simply the amount of time that passes while the velocity is changing.
The derivative of a function represents an infinitesimal change in the function with respect to one of its variables. The derivative of a function with respect to the variable is defined as
f(x + h) - f(x)
f'(x) = lim -----------------
h->0 h
First you get a time, i.e NewTime = timeGetTime().
Then you subtract the old time from a new time you just got. call it delta time , dt.
OldTime = NewTime;
dt = (float) (NewTime - OldTime)/1000;
Now you sum dt into totaltime.
TotalTime += dt
So that when TotalTime reaches 5, you end the life of the particles.
if(TotalTime >= 5.0f){
//particles to die after their MAX_AGE is reached
TotalTime=0;
}
...
More interesting reading:
http://gafferongames.com/game-physics/
http://gafferongames.com/game-physics/integration-basics/
...
example code for Windows:
#include<time.h>
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
#pragma comment(lib,"winmm.lib")
void gotoxy(int x, int y);
void StepSimulation(float dt);
int main(){
int NewTime = 0;
int OldTime = 0;
int StartTime = 0;
int TimeToLive = 5000; //// TimeToLive 5 seconds
float dt = 0;
float TotalTime = 0;
int FrameCounter = 0;
int RENDER_FRAME_COUNT = 60;
// reset TimeToLive
StartTime = timeGetTime();
while(true){
NewTime = timeGetTime();
dt = (float) (NewTime - OldTime)/1000; //delta time
OldTime = NewTime;
// print to screen TimeToLive
gotoxy(1,1);
printf("NewTime - StartTime = %d ", NewTime - StartTime );
if ( (NewTime - StartTime ) >= TimeToLive){
// reset TimeToLive
StartTime = timeGetTime();
}
// The rest of the timestep and 60fps lock
if (dt > (0.016f)) dt = (0.016f); //delta time
if (dt < 0.001f) dt = 0.001f;
TotalTime += dt;
if(TotalTime >= 5.0f){
TotalTime=0;
StepSimulation(dt);
}
if(FrameCounter >= RENDER_FRAME_COUNT){
// draw stuff
//Render();
gotoxy(1,3);
printf("OldTime = %d \n",OldTime);
printf("NewTime = %d \n",NewTime);
printf("dt = %f \n",dt);
printf("TotalTime = %f \n",TotalTime);
printf("FrameCounter = %d fps\n",FrameCounter);
printf(" \n");
FrameCounter = 0;
}
else{
gotoxy(22,7);
printf("%d ",FrameCounter);
FrameCounter++;
}
}
return 0;
}
void gotoxy(int x, int y){
COORD coord;
coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
return;
}
void StepSimulation(float dt){
// calculate stuff
//vVelocity += Ae * dt;
}

Updating time and position using GetTickCount() in C++

Problem: I am attempting to update time using getTickCount without avail.
Situation: I currently obtain the timedifference using getTickCount and pass it into world update method parameters. However within the update method where I update the position, a large value is passed in (even though I have divided by 1000) and so the position adds an odd 4000 to the position vector.
Code below:
Simulation.CPP:
int Simulation::simControlLogic(HWND hWnd, keyEvent event)
{
/* TO DO: add relevant code */
if (event != QUIT)
{
previousTime = 0;
frameStartTime = GetTickCount();
if (previousTime == 0)
previousTime = frameStartTime;
timeDifference = (frameStartTime - previousTime) / 1000.0f; // this generates the difference between the last and current time
world.update(event, &graphics, timeDifference); // update parameters of virtual world
gameLoopDelay(frameStartTime);
simDisplayFrame(hWnd); // display frame
previousTime = frameStartTime; //the current time is set to the previous time for the next loop step
}
return 1;
}
looking into the world Update method:
int WorldData::update(keyEvent kEvent, GraphicsM * pGraphicsModule, float timeStep)
{
//updates the particle
for (int i = 0; i < 3; i++)
{
particles[i].Update(kEvent, pGraphicsModule, timeStep);
}
return 1;
}
looking into particles Update method:
void ParticleModel::Update(keyEvent kEvent, GraphicsM * pGraphicsModule, float timeStep)
{
move(timeStep);
}
looking into move method:
void ParticleModel::move(float timeStep)
{
velocity.y = 0.5F;
velocity.x = 0.5F;
acceleration.x = 0.0F;
acceleration.y = 0.0F;
pos.x += velocity.x * timeStep; //here is the problem. I get a large value e.g 79637.1788 causing pos.x to be ridiculously large
pos.y += velocity.y * timeStep; //here is the problem. I get a large value e.g 79637.1788 causing pos.y to be ridiculously large
}
After moving previousTime to the simulator constructor initializing it to 0, it worked. Thanks for replies

Limiting Update Rate in C++. Why does this code update once a second not 60 times a second?

I am making a small game with C++ OpenGL. update() is normally called once every time the program runs through the code. I am trying to limit this to 60 times per second (I want the game to update at the same speed on different speed computers).
The code included below runs a timer and should call update() once the timer is >= than 0.0166666666666667 (60 times per second). However the statement if((seconds - lastTime) >= 0.0166666666666667) seems only to be tripped once per second. Does anyone know why?
Thanks in advance for your help.
//Global Timer variables
double secondsS;
double lastTime;
time_t timer;
struct tm y2k;
double seconds;
void init()
{
glClearColor(0,0,0,0.0); // Sets the clear colour to white.
// glClear(GL_COLOR_BUFFER_BIT) in the display function
//Init viewport
viewportX = 0;
viewportY = 0;
initShips();
//Time
lastTime = 0;
time_t timerS;
struct tm y2k;
y2k.tm_hour = 0; y2k.tm_min = 0; y2k.tm_sec = 0;
y2k.tm_year = 100; y2k.tm_mon = 0; y2k.tm_mday = 1;
time(&timerS); /* get current time; same as: timer = time(NULL) */
secondsS = difftime(timerS,mktime(&y2k));
printf ("%.f seconds since January 1, 2000 in the current timezone \n", secondsS);
loadTextures();
ShowCursor(true);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void timeKeeper()
{
y2k.tm_hour = 0; y2k.tm_min = 0; y2k.tm_sec = 0;
y2k.tm_year = 100; y2k.tm_mon = 0; y2k.tm_mday = 1;
time(&timer); /* get current time; same as: timer = time(NULL) */
seconds = difftime(timer,mktime(&y2k));
seconds -= secondsS;
//Run 60 times a second. This limits updates to a constant standard.
if((seconds - lastTime) >= 0.0166666666666667)
{
lastTime = seconds;
update();
//printf ("%.f seconds since beginning program \n", seconds);
}
}
timeKeeper() is called in int WINAPI WinMain, while the program is !done
EDIT:
Thanks to those who helped, you pointed me on the right track. As mentioned in the answer below <ctime> does not have ms accuracy. I have therefore implemented the following code that has the correct accuracy:
double GetSystemTimeSample()
{
FILETIME ft1, ft2;
// assume little endian and that ULONGLONG has same alignment as FILETIME
ULONGLONG &t1 = *reinterpret_cast<ULONGLONG*>(&ft1),
&t2 = *reinterpret_cast<ULONGLONG*>(&ft2);
GetSystemTimeAsFileTime(&ft1);
do
{
GetSystemTimeAsFileTime(&ft2);
} while (t1 == t2);
return (t2 - t1) / 10000.0;
}//GetSystemTimeSample
void timeKeeper()
{
thisTime += GetSystemTimeSample();
cout << thisTime << endl;
//Run 60 times a second. This limits updates to a constant standard.
if(thisTime >= 16.666666666666699825) //Compare to a value in milliseconds
{
thisTime = seconds;
update();
}
}
http://www.cplusplus.com/reference/ctime/difftime/
Calculates the difference in seconds between beginning and end
So, you get a value in seconds. So, even if your value is double, you will get an integer.
So, you only get a difference between a value and the previous one when that difference is at least of 1 second.

Design fps limiter

I try to cap the animation at 30 fps. So I design the functions below to achieve the goal. Unfortunately, the animation doesn't behave as fast as no condition checking for setFPSLimit() function when I set 60 fps (DirectX caps game application at 60 fps by default). How should I fix it to make it work?
getGameTime() function counts the time like stopwatch in millisecond when game application starts.
//Called every time you need the current game time
float getGameTime()
{
UINT64 ticks;
float time;
// This is the number of clock ticks since start
if( !QueryPerformanceCounter((LARGE_INTEGER *)&ticks) )
ticks = (UINT64)timeGetTime();
// Divide by frequency to get the time in seconds
time = (float)(__int64)ticks/(float)(__int64)ticksPerSecond;
// Subtract the time at game start to get
// the time since the game started
time -= timeAtGameStart;
return time;
}
With fps limit
http://www.youtube.com/watch?v=i3VDOMqI6ic
void update()
{
if ( setFPSLimit(60) )
updateAnimation();
}
With No fps limit http://www.youtube.com/watch?v=Rg_iKk78ews
void update()
{
updateAnimation();
}
bool setFPSLimit(float fpsLimit)
{
// Convert fps to time
static float timeDelay = 1 / fpsLimit;
// Measure time elapsed
static float timeElapsed = 0;
float currentTime = getGameTime();
static float totalTimeDelay = timeDelay + getGameTime();
if( currentTime > totalTimeDelay)
{
totalTimeDelay = timeDelay + getGameTime();
return true;
}
else
return false;
}