如何为游戏循环制作计时器?

发布于 2024-10-26 17:37:28 字数 56 浏览 1 评论 0原文

我想计算 fps 计数,并将其限制设置为 60,但是我一直在通过谷歌查看一些代码,但我完全不明白。

I want to time fps count, and set it's limit to 60 and however i've been looking throught some code via google, I completly don't get it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

海的爱人是光 2024-11-02 17:37:28

增量时间是最终时间减去原始时间。

dt= t-t0

不过,这个增量时间只是速度变化时所经过的时间量。

函数的导数代表无穷小的变化
在函数中相对于其变量之一。
函数相对于变量的导数定义为

                f(x + h) - f(x)
f'(x) = lim    -----------------
        h->0           h

http://mathworld.wolfram.com/Derivative。 html

#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;
  float dt = 0;
  float TotalTime = 0;
  int FrameCounter = 0;
  int RENDER_FRAME_COUNT = 60;

  while(true){

        NewTime = timeGetTime();    
        dt = (float) (NewTime - OldTime)/1000; //delta time
        OldTime = NewTime;

        if (dt > (0.016f)) dt = (0.016f);  //delta time
        if (dt < 0.001f) dt = 0.001f;

        TotalTime += dt;

        if(TotalTime > 1.1f){ 
            TotalTime=0;
            StepSimulation(dt);
            }

        if(FrameCounter >= RENDER_FRAME_COUNT){           
            // draw stuff
            //Render(); 

            gotoxy(1,2);
            printf(" \n");
            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;

}

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

http://mathworld.wolfram.com/Derivative.html

#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;
  float dt = 0;
  float TotalTime = 0;
  int FrameCounter = 0;
  int RENDER_FRAME_COUNT = 60;

  while(true){

        NewTime = timeGetTime();    
        dt = (float) (NewTime - OldTime)/1000; //delta time
        OldTime = NewTime;

        if (dt > (0.016f)) dt = (0.016f);  //delta time
        if (dt < 0.001f) dt = 0.001f;

        TotalTime += dt;

        if(TotalTime > 1.1f){ 
            TotalTime=0;
            StepSimulation(dt);
            }

        if(FrameCounter >= RENDER_FRAME_COUNT){           
            // draw stuff
            //Render(); 

            gotoxy(1,2);
            printf(" \n");
            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;

}
帅气尐潴 2024-11-02 17:37:28

如果您想要 60 FPS,您需要计算出每一帧的时间。在本例中为 16.67 毫秒。因此您需要一个每 16.67 毫秒完成一次的循环。

通常它会这样(简单地说):获取输入,执行物理操作,渲染,暂停直到 16.67 毫秒过去。

它通常是通过在循环顶部保存时间,然后在最后计算差值并在这段时间内休眠或循环不执行任何操作来完成的。

本文介绍了几种不同的游戏循环方式,包括您想要的方式,尽管我' d 使用本文中更高级的替代方案之一。

If you want 60 FPS, you need to figure out how much time you have on each frame. In this case, 16.67 milliseconds. So you want a loop that completes every 16.67 milliseconds.

Usually it goes (simply put): Get input, do physics stuff, render, pause until 16.67ms has passed.

Its usually done by saving the time at the top of the loop and then calculating the difference at the end and sleeping or looping doing nothing for that duration.

This article describes a few different ways of doing game loops, including the one you want, although I'd use one of the more advanced alternatives in this article.

走野 2024-11-02 17:37:28

您不应该尝试限制 fps。这样做的唯一原因是如果您不使用增量时间并且您希望每个帧具有相同的长度。即使是最简单的游戏也不能保证这一点。

但是,您可以将增量时间分割成固定大小,然后保留其余部分。

这是我最近写的一些代码。它没有经过彻底的测试。

void GameLoop::Run()
{
    m_Timer.Reset();

    while(!m_Finished())
    {
        Time delta = m_Timer.GetDelta();
        Time frameTime(0);
        unsigned int loopCount = 0;

        while (delta > m_TickTime && loopCount < m_MaxLoops)
        {
            m_SingTick();
            delta -= m_TickTime;
            frameTime += m_TickTime;
            ++loopCount;
        }
        m_Independent(frameTime);

        // add an exception flag later.
        // This is if the game hangs
        if(loopCount >= m_MaxLoops)
        {
            delta %= m_TickTime;
        }

        m_Render(delta);
        m_Timer.Unused(delta);
    }
}

成员对象是 Boost 槽,因此不同的代码可以使用不同的计时方法进行注册。独立插槽用于诸如键映射或更改音乐之类的事情,这些事情不需要那么精确。 SingTick 对于物理很有用,如果您知道每个刻度都是相同的,但又不想穿墙的话,那就更容易了。渲染采用增量,以便动画运行流畅,但必须记住在下一个 SingTick 上考虑它。

希望有帮助。

You shouldn't try to limit the fps. The only reason to do so is if you are not using delta time and you expect each frame to be the same length. Even the simplest game cannot guarantee that.

You can however take your delta time and slice it into fixed sizes and then hold onto the remainder.

Here's some code I wrote recently. It's not thoroughly tested.

void GameLoop::Run()
{
    m_Timer.Reset();

    while(!m_Finished())
    {
        Time delta = m_Timer.GetDelta();
        Time frameTime(0);
        unsigned int loopCount = 0;

        while (delta > m_TickTime && loopCount < m_MaxLoops)
        {
            m_SingTick();
            delta -= m_TickTime;
            frameTime += m_TickTime;
            ++loopCount;
        }
        m_Independent(frameTime);

        // add an exception flag later.
        // This is if the game hangs
        if(loopCount >= m_MaxLoops)
        {
            delta %= m_TickTime;
        }

        m_Render(delta);
        m_Timer.Unused(delta);
    }
}

The member objects are Boost slots so different code can register with different timing methods. The Independent slot is for things like key mapping or changing music Things that don't need to be so precise. SingTick is good for physics where it is easier if you know every tick will be the same but you don't want to run through a wall. Render takes the delta so animations run smooth, but must remember to account for it on the next SingTick.

Hope that helps.

记忆之渊 2024-11-02 17:37:28

有很多充分的理由说明为什么您不应该以这种方式限制帧速率。一个原因是 stijn 指出的,并不是每个显示器都能以 60fps 的速度运行,另一个原因是计时器的分辨率不够,还有一个原因是即使有足够的分辨率,两个独立的计时器(显示器刷新和你的)运行在由于随机的不准确性,并行总是会与时间不同步(它们必须!),最重要的原因是它根本没有必要。

请注意,Windows 下的默认计时器分辨率是 15 毫秒,您可以获得的最佳分辨率(通过使用 timeBeginPeriod)是 1 毫秒。因此,您(最多)可以等待 16 毫秒或 17 毫秒。 60fps 的一帧是 16.6666ms 你怎么等 16.6666ms?

如果您想将游戏速度限制为显示器的刷新率,请启用垂直同步。这将准确地完成您想要的操作,并且不会出现同步问题。垂直同步也有其特殊性(例如当一帧需要 16.67 毫秒时您会得到有趣的惊喜),但它是迄今为止最好的可用解决方案。

如果您想要这样做的原因是为了让模拟适合渲染循环,这个 是您必读的内容。

There are many good reasons why you should not limit your frame rate in such a way. One reason being as stijn pointed out, not every monitor may run at exactly 60fps, another reason being that the resolution of timers is not sufficient, yet another reason being that even given sufficient resolutions, two separate timers (monitor refresh and yours) running in parallel will always get out of sync with time (they must!) due to random inaccuracies, and the most important reason being that it is not necessary at all.

Note that the default timer resolution under Windows is 15ms, and the best possible resolution you can get (by using timeBeginPeriod) is 1ms. Thus, you can (at best) wait 16ms or 17ms. One frame at 60fps is 16.6666ms How do you wait 16.6666ms?

If you want to limit your game's speed to the monitor's refresh rate, enable vertical sync. This will do what you want, precisely, and without sync issues. Vertical sync does have its pecularities too (such as the funny surprise you get when a frame takes 16.67ms), but it is by far the best available solution.

If the reason why you wanted to do this was to fit your simulation into the render loop, this is a must read for you.

网白 2024-11-02 17:37:28

检查一下这个:

//Creating Digital Watch in C++
#include<iostream>
#include<Windows.h>
using namespace std;

struct time{

int hr,min,sec;
};
int main()
{
time a;
a.hr = 0;
a.min = 0;
a.sec = 0;

for(int i = 0; i<24; i++)
{
    if(a.hr == 23)
    {
        a.hr = 0;
    }

    for(int j = 0; j<60; j++)
    {
        if(a.min == 59)
        {
            a.min = 0;
        }

        for(int k = 0; k<60; k++)
        {
            if(a.sec == 59)
            {
                a.sec = 0;
            }

            cout<<a.hr<<" : "<<a.min<<" : "<<a.sec<<endl;
            a.sec++;
            Sleep(1000);
            system("Cls");
        }
    a.min++;

}

    a.hr++;
}

}

check this one out:

//Creating Digital Watch in C++
#include<iostream>
#include<Windows.h>
using namespace std;

struct time{

int hr,min,sec;
};
int main()
{
time a;
a.hr = 0;
a.min = 0;
a.sec = 0;

for(int i = 0; i<24; i++)
{
    if(a.hr == 23)
    {
        a.hr = 0;
    }

    for(int j = 0; j<60; j++)
    {
        if(a.min == 59)
        {
            a.min = 0;
        }

        for(int k = 0; k<60; k++)
        {
            if(a.sec == 59)
            {
                a.sec = 0;
            }

            cout<<a.hr<<" : "<<a.min<<" : "<<a.sec<<endl;
            a.sec++;
            Sleep(1000);
            system("Cls");
        }
    a.min++;

}

    a.hr++;
}

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文