Как сделать таймер для игрового цикла? - PullRequest
2 голосов
/ 26 марта 2011

Я хочу рассчитать количество кадров в секунду и установить для него ограничение 60, и, хотя я искал какой-то код через Google, я его полностью не понимаю.

Ответы [ 5 ]

3 голосов
/ 24 ноября 2012

дельта-время является последним временем, минус исходное время.

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;

}
3 голосов
/ 26 марта 2011

Если вы хотите 60 кадров в секунду, вам нужно выяснить, сколько времени у вас есть на каждый кадр. В этом случае 16,67 миллисекунды. Итак, вы хотите цикл, который завершается каждые 16,67 миллисекунды.

Обычно это происходит (проще говоря): получить ввод, выполнить физику, отрендерить, сделать паузу, пока не пройдет 16,67 мс.

Обычно это делается путем сохранения времени в верхней части цикла, а затем вычисления разницы в конце и ожидания или зацикливания, ничего не делая в течение этой продолжительности.

Эта статья описывает несколько различных способов создания игровых циклов, включая тот, который вам нужен, хотя я бы использовал одну из более продвинутых альтернатив в этой статье.

2 голосов
/ 26 марта 2011

Вы не должны пытаться ограничить количество кадров в секунду. Единственная причина сделать это, если вы не используете дельта-время, и вы ожидаете, что каждый кадр будет одинаковой длины. Даже самая простая игра не может этого гарантировать.

Однако вы можете взять свое дельта-время и нарезать его на фиксированные размеры, а затем удержать остаток.

Вот код, который я недавно написал. Это не полностью проверено.

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.

Надеюсь, это поможет.

1 голос
/ 26 марта 2011

Есть много веских причин, почему вы не должны ограничивать частоту кадров таким образом.Как указала Стийн, одна причина заключается в том, что не каждый монитор может работать с частотой 60 кадров в секунду, другая причина в том, что разрешение таймеров недостаточно, и еще одна причина в том, что даже при достаточном разрешении работают два отдельных таймера (обновление монитора и ваш).параллель всегда будет не синхронизирована со временем (они должны!) из-за случайных неточностей, и наиболее важной причиной является то, что это вообще не нужно.

Обратите внимание, что разрешение таймера по умолчанию в Windows составляет 15 мс,и наилучшее возможное разрешение, которое вы можете получить (используя timeBeginPeriod), составляет 1 мс.Таким образом, вы можете (в лучшем случае) ждать 16 мс или 17 мс.Один кадр со скоростью 60 кадров в секунду равен 16,6666 мс. Как вы ждете 16,6666 мс?

Если вы хотите ограничить скорость вашей игры частотой обновления монитора, включите вертикальную синхронизацию.Это будет делать то, что вы хотите, точно и без проблем с синхронизацией.Вертикальная синхронизация тоже имеет свои особенности (например, забавный сюрприз, который вы получаете, когда кадр занимает 16,67 мс), но это, безусловно, лучшее из доступных решений.

Если причиной, по которой вы хотели это сделать, былопоместите вашу симуляцию в цикл рендеринга, это обязательно для вас.

0 голосов
/ 11 декабря 2013

проверить это:

//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++;
}

}
...