How would you wait a frame in c++.
I don't want the program to sleep or anything.
It would go soemthing like
Do this in this frame (1)
Continue with rest of program
Do this in the next frame (2)
where action 1 happens only in the first frame and action 2 happens only in the next frame. It would continue like this. 1, 2, 1 again, 2
I have the time between frames, I use c++ and i'm using Visual Studio 2008 to compile.
Edit:
I'm using Opengl my OS is Windows 7.
Frame - http://en.wikipedia.org/wiki/Frame_rate
like each image of the scene printed to the screen over a given time period
I'm making some assumptions here.
Suppose you have a model for which you wish to show the state. You might wish to maximise the CPU time spent evolving the model rather than rendering.
So you fix the target frame rate, at e.g. 25 fps.
Again, assume you have optimised rendering so that it can be done in much less than 0.04 seconds.
So you might want something like (pseudo-code):
Time lastRendertime = now();
while(forever)
{
Time current = now();
if ((current - lastRenderTime > 0.04))
{
renderEverything();
lastRenderTime = current;
}
else
{
evolveModelABit();
}
}
Of course, you probably have an input handler to break the loop. Note that this approach assumes that you do not want the model evolution affected by elapsed real time. If you do, and may games do, then pass in the current time to the evolveModelABit();.
For time functions on Windows, you can use:
LARGE_INTEGER frequency; // ticks per second
LARGE_INTEGER t1; // ticks
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&t1);
Note that this approach is suitable for a scientific type simulation. The model evolution will not depend on the frame rate, rendering etc, and gives the same result very time.
For a game, typically there is a push for maximising the fps. This means that the main loop is of the form:
Time lastRendertime = now();
while(forever)
{
Time current = now();
evolveModelABit(current, lastRenderTime);
renderEverything();
lastRenderTime = current;
}
If V-Sync is enabled, SwapBuffers will block the current thread until the next frame has been shown. So if you create a worker thread, and release a lock, or resume its execution right before the call of SwapBuffers your programm recieves the CPU time it would otherwise yield to the rest of the system during the wait-for-swap block. If the worker thread is manipulating GPU resources, it is a good idea using high resolution/performance counters to determine how much time is left until the swap, minus some margin and use this timing in the worker thread, so that the worker thread puts itself to sleep at about the time the swap happens, so that the GPU will not have to context switch between worker and renderer thread.
Related
I'm trying to create a game using C++ and I want to create limit for fps but I always get more or less fps than I want. When I look at games that have fps limit it's always precise framerate. Tried using Sleep() std::this_thread::sleep_for(sleep_until). For example Sleep(0.01-deltaTime) to get 100 fps but ended up with +-90fps.
How do these games handle fps so precisely when any sleeping isn't precise?
I know I can use infinite loop that just checks if time passed but it's using full power of CPU but I want to decrease CPU usage by this limit without VSync.
Yes, sleep is usually inaccurate. That is why you sleep for less than the actual time it takes to finish the frame. For example, if you need 5 more milliseconds to finish the frame, then sleep for 4 milliseconds. After the sleep, simply do a spin-lock for the rest of the frame. Something like
float TimeRemaining = NextFrameTime - GetCurrentTime();
Sleep(ConvertToMilliseconds(TimeRemaining) - 1);
while (GetCurrentTime() < NextFrameTime) {};
Edit: as stated in another answer, timeBeginPeriod() should be called to increase the accuracy of Sleep(). Also, from what I've read, Windows will automatically call timeEndPeriod() when your process exits if you don't before then.
You could record the time point when you start, add a fixed duration to it and sleep until the calculated time point occurs at the end (or beginning) of every loop. Example:
#include <chrono>
#include <iostream>
#include <ratio>
#include <thread>
template<std::intmax_t FPS>
class frame_rater {
public:
frame_rater() : // initialize the object keeping the pace
time_between_frames{1}, // std::ratio<1, FPS> seconds
tp{std::chrono::steady_clock::now()}
{}
void sleep() {
// add to time point
tp += time_between_frames;
// and sleep until that time point
std::this_thread::sleep_until(tp);
}
private:
// a duration with a length of 1/FPS seconds
std::chrono::duration<double, std::ratio<1, FPS>> time_between_frames;
// the time point we'll add to in every loop
std::chrono::time_point<std::chrono::steady_clock, decltype(time_between_frames)> tp;
};
// this should print ~10 times per second pretty accurately
int main() {
frame_rater<10> fr; // 10 FPS
while(true) {
std::cout << "Hello world\n";
fr.sleep(); // let it sleep any time remaining
}
}
The accepted answer sounds really bad. It would not be accurate and it would burn the CPU!
Thread.Sleep is not accurate because you have to tell it to be accurate (by default is about 15ms accurate - means that if you tell it to sleep 1ms it could sleep 15ms).
You can do this with Win32 API call to timeBeginPeriod & timeEndPeriod functions.
Check MSDN for more details -> https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
(I would comment on the accepted answer but still not having 50 reputation)
Be very careful when implementing any wait that is based on scheduler sleep.
Most OS schedulers have higher latency turn-around for a wait with no well-defined interval or signal to bring the thread back into the ready-to-run state.
Sleeping isn't inaccurate per-se, you're just approaching the problem all wrong. If you have access to something like DXGI's Waitable Swapchain, you synchronize to the DWM's present queue and get really reliable low-latency timing.
You don't need to busy-wait to get accurate timing, a waitable timer will give you a sync object to reschedule your thread.
Whatever you do, do not use the currently accepted answer in production code. There's an edge case here you WANT TO AVOID, where Sleep (0) does not yield CPU time to higher priority threads. I've seen so many game devs try Sleep (0) and it's going to cause you major problems.
Use a timer.
Some OS's can provide special functions. For example, for Windows you can use SetTimer and handle its WM_TIMER messages.
Then calculate the frequency of the timer. 100 fps means that the timer must fire an event each 0.01 seconds.
At the event handler for this timer-event you can do your rendering.
In case the rendering is slower than the desired frequency then use a syncro flag OpenGL sync and discard the timer-event if the previous rendering is not complete.
You may set a const fps variable to your desired frame rate, then you can update your game if the elapsed time from last update is equal or more than 1 / desired_fps.
This will probably work.
Example:
const /*or constexpr*/ int fps{60};
// then at update loop.
while(running)
{
// update the game timer.
timer->update();
// check for any events.
if(timer->ElapsedTime() >= 1 / fps)
{
// do your updates and THEN renderer.
}
}
I'm making a game in openGL and I want to spawn 2 enemies per second on the screen. The problem is, I'm calling the spawn function inside idle:
idle
{
// ...
world.spawnEnemy();
}
And then, in the spawnEnemy function:
void World::spawnEnemy()
{
Enemy newEnemy, newEnemy2;
float start;
start = glutGet(GLUT_ELAPSED_TIME);
// 1/2 a second passes
while ( (glutGet(GLUT_ELAPSED_TIME) - start) <= 500 )
{
;
}
// create enemy
newEnemy();
pushToEnemyList(newEnemy);
// another 1/2 second passes
while ( (glutGet(GLUT_ELAPSED_TIME) - start) <= 1000 )
{
;
}
// create enemy
newEnemy2();
pushToEnemyList(newEnemy2);
}
And this is not working, of course. Probably because idle is called everytime and I'm calling a function inside idle that waits for a certain amount of time to pass and then everything starts going wrong. The solution is to do the spawning in the idle function (without calling any function, doing all the logic inside idle), but I don't like this idea. I need to do more things in a certain number of time, for example, my enemies have guns and they will have to shoot n times every second. And if I do all of these directly inside of idle it will become a mess. So, basically, how do I make this work:
idle
{
// ...
world.spawnEnemy();
world.enemyShoot();
// another functionalities that depend on time
}
instead of this:
idle
{
// ...
// logic of spawnEnemy directly here in the idle function
// logic of enemyShoot directly here in the idle function
// logic of another functionalities that depend on time directly here in the idle function
}
There is quite a few ways to do this here the most common:
Measure elapsed time
Simply remember time of last spawn t0 and on each (idle) iteration get current time t. If t0+T<=t then spawn new enemy ans set t0=t. The T is the period of spawning in the same units as the measured time. In your case 500ms.
As mentioned OnIdle Event will take 100% of one CPU core for itself. To remedy this use Sleep(x); where x<<T that will ease up on the CPU load (even Sleep(1); will be a big difference).
To measure time use any OS routine you got available (with high enough accuracy) I am using PerformanceCounter on Windows but there are other alternatives like RDTSC etc ...
Timers
Modern messaging based OS provides timer function which will fire your event periodically (usually with ~1ms accuracy). Just study your API to implement it. Then you just spawn your enemy inside timer event without any other logic or timing code ...
In case you do not have any timers you can fake this by creating thread with code like this inside:
for (;!spawn_exit;)
{
if (spawn_enabled) spawn();
Sleep(T);
}
where volatile bool spawn_enabled=true,spawn_exit=false; are used to control the spawning and stop the thread (before App shutdown) But in this case be careful with multi threaded access in the spawn() function ...
I am looking at trying to pause something in C++. Specifically a bullet you shoot in a space invaders game. Each time you press the UP key it fires a shot, I have been trying to find a way to pause it for a number of seconds before being able to fire again.
I've tried Sleep(); but it freezes the entire game rather than pauses the ability to press UP again.
Firing code
if (CInput::getInstance()->getIfKeyDownEvent(DIK_UP))
{
g_pGame->AddSprite(new CMissile(m_fX, m_fY+0.5*m_fH, 0.09, 0.9, 2));
}
Try taking the current time and then adding your delay to it. Store that in your shooting object. The next time through your program loop, if the current time is less than the time stored in the object, ignore the UP arrow.
Here are two simple ways to manage this.
When you fire a bullet, take the current system time and add the delay you want to it. If the player attempts to fire again while the current time is less than the variable you set, nothing happens.
Or, when you fire a bullet, set a timer variable to the delay you want. Each update, subtract delta time from the timer. When the timer is <=0, the user can fire.
Typically when you want to deal with real time seconds, you need something called delta time. Due to the inconsistency with frame rates, you need a way to measure real time. Typically you do this by counting the amount of time elapsed between frames. Here's an example of this implementation:
Source
int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);
int oldTimeSinceStart = 0;
while( ... ) // main game loop
{
int timeSinceStart = glutGet(GLUT_ELAPSED_TIME);
int deltaTime = timeSinceStart - oldTimeSinceStart;
oldTimeSinceStart = timeSinceStart;
secondsSinceLastShot += deltaTime;
if (secondsSinceLastShot > shotTimer)
{
canShoot = true;
secondsSinceLastShot = 0;
}
if ( // press space or something )
{
canShoot = false;
// shoot
}
}
Note that this uses GLUT's implementation of a timer, but you need to implement that yourself (probably using clock()).
I've tried Sleep(); but it freezes the entire game rather than pauses the ability to press UP again.
Sleeping will freeze the thread, which is not what you want to do. However, sleep() is typically used in an implementation that contains delta time, usually sleep()ing for the amount of time elapsed between frames. For an example, see Lazy Foo's SDL tutorials
Ignore the fact that I linked to both OpenGL and SDL links, the principle is the same no matter the graphics library used.
I have done a memory tiles program but i want it to be timed, i.e, the user shoud be able to play the game only for 2 mins. what do i do?
Also in linux sleep() does not work, what should we use for a delay??
I presume the game has a "main loop" somewhere.
At the beginning of the main loop (before the actual loop), take the current time, call this start_time. Then in each iteration of the loop, take the current time again, call this now. The elapsed time is elapsed_time = now - start_time;. Assuming time is in seconds, then if (elapsed_time >= 120) { ... end game ... } would do the trick.
So I made a game loop that uses SDL_Delay function to cap the frames per second, it look like this:
//While the user hasn't qui
while( stateID != STATE_EXIT )
{
//Start the frame timer
fps.start();
//Do state event handling
currentState->handle_events();
//Do state logic
currentState->logic();
//Change state if needed
change_state();
//Do state rendering
currentState->render();
//Update the screen
if( SDL_Flip( screen ) == -1 )
{
return 1;
}
//Cap the frame rate
if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
}
So when I run my games on 60 frames per second (which is the "eye cap" I assume) I can still see laggy type of motion, meaning i see the frames appearing independently causing unsmooth motion.
This is because apparently SDL_Delay function is not too accurate, causing +,- 15 milliseconds or something difference between frames greater than whatever I want it to be.
(all these are just my assumptions)
so I am just searching fo a good and accurate timer that will help me with this problem.
any suggestions?
I think there is a similar question in How to make thread sleep less than a millisecond on Windows
But as a game programmer myself, I don't rely on sleep functions to manage frame-rate (the parameter they take is just a minimum). I just draw stuff on screen as fast as I can. I have a bunch of function calls in my game loop, and then I keep track of how often I'm calling them. For instance, I check input quite often (1000x/second) to make the game more responsive, but I don't check the network inbox more than 100x/second.
For example:
#define NW_CHECK_INTERVAL 10
#define INPUT_CHECK_INTERVAL 1
uint32_t last_nw_check = 0, last_input_check = 0;
while (game_running) {
uint32_t now = SDL_GetTicks();
if (now - last_nw_check > NW_CHECK_INTERVAL) {
check_network();
last_nw_check = now;
}
if (now - last_input_check > INPUT_CHECK_INTERVAL) {
check_input();
last_input_check = now;
}
check_video();
// and so on...
}
Use the QueryPerformanceCounter / Frequency for that.
LARGE_INTEGER start, end, tps; //tps = ticks per second
QueryPerformanceFrequency( &tps );
QueryPerformanceCounter( &start );
QueryPerformanceCounter( &end );
int usPassed = (end.QuadPart - start.QuadPart) * 1000000 / tps.QuadPart;
Here's a small wait function I had created for timing midi sequences using QueryPerformanceCounter:
void wait(int waitTime) {
LARGE_INTEGER time1, time2, freq;
if(waitTime == 0)
return;
QueryPerformanceCounter(&time1);
QueryPerformanceFrequency(&freq);
do {
QueryPerformanceCounter(&time2);
} while((time2.QuadPart - time1.QuadPart) * 1000000ll / freq.QuadPart < waitTime);
}
To convert ticks to microseconds, calculate the difference in ticks, multiply by 1,000,000 (microseconds/second) and divide by the frequency of ticks per second.
Note that some things may throw this off, for instance the precision of the high-resolution counter is not likely to be down to a single microsecond. For example, if you want to wait 10 microseconds and the precision/frequency is one tick every 6 microseconds, your 10 microsecond wait will actually be no less than 12 microseconds. Again, this frequency is system dependent and will vary from system to system.
Also, Windows is not a real-time operating system. A process may be preempted at any time and it is up to Windows to decide when the process is rescheduled. The application may be preempted in the middle of this function and not restarted again until long after the expected wait time has elapsed. There really isn't much you can do about it but you'll probably never notice it if it happens.
60 fame per second is just the frequency of power in US (50 in Europe, Africa and Asia are somehow mixed) and is the frequency of video refreshing for hardware comfortable reasons (It can be an integer multiple on more sophisticated monitors). It was a mandatory constrains for CRT dispaly, and it is still a comfortable reference for LCD (that's how frequently the frame buffer is uploaded to the display)
The eye-cap is no more than 20-25 fps - not to be confused with retina persistency, that's about one-half - and that's why TV interlace two squares upon every refresh.
independently on the timing accuracy, whatever hardware device cannot be updated during its buffer-scan (otherwise the image changes while it is shown, resulting in half-drawn broken frames), hence, if you go faster than one half of the device refresh you are queued behind it and forced to wait for it.
60 fps in a game loop serves only to help CPU manufacturers to sell new faster CPUs. Slow down under 25 and everything will look more fluid.
SDL_Delay:
This function waits a specified number of milliseconds before returning. It waits at least the specified time, but possible longer due to OS scheduling. The delay granularity is at least 10 ms. Some platforms have shorter clock ticks but this is the most common.
The actual delays observed with this function depend on OS settings. I'd suggest to look into the
Mutimedia Timer API, particulary into the timeBeginPeriod function, to adapt the interrupt frequency to your requirements.
Obtaining and Setting Timer Resolution shows an example how to change the interrupt period to about 1ms. This way you don't have the 15ms hickup anymore. BTW: Eye-catch period is about 40ms.
Obtaining fixed period timing can also be addressed by Waitable Timer Objects. But the use of mutimedia timers is mandatory to obtain decent resolution, no matter what.
Using other tools to improve the timing capabilities is discussed here.