恒定游戏速度的独立在OpenGL变量FPS与葡萄糖转运? [英] Constant game speed independent of variable FPS in OpenGL with GLUT?

查看:242
本文介绍了恒定游戏速度的独立在OpenGL变量FPS与葡萄糖转运?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在读公园威特斯详细的文章,但我有一些问题实施最后一个与GLUT,这是推荐的。

I've been reading Koen Witters detailed article about different game loop solutions but I'm having some problems implementing the last one with GLUT, which is the recommended one.

阅读几篇文章,教程和其他人如何实现恒定的游戏速度code后,我认为我目前已经实现了(我会后下面的code)是什么公园威特斯所谓的游戏速度依赖于变量FPS 的,第二个是关于他的文章。

After reading a couple of articles, tutorials and code from other people on how to achieve a constant game speed, I think that what I currently have implemented (I'll post the code below) is what Koen Witters called Game Speed dependent on Variable FPS, the second on his article.

第一,通过我的搜索体验,有一对夫妇的人大概有知识,以帮助这个,但不知道是我要去尝试,并解释(随时纠正我)有什么转运蛋白的相关职能为我这个OpenGL的工具包的问题。如果你知道GLUT是什么,以及如何发挥它跳过这一节。

First, through my searching experience, there's a couple of people that probably have the knowledge to help out on this but don't know what GLUT is and I'm going to try and explain (feel free to correct me) the relevant functions for my problem of this OpenGL toolkit. Skip this section if you know what GLUT is and how to play with it.

GLUT工具包:


  • GLUT是一个OpenGL工具包和OpenGL中常见的任务有所帮助。

  • glutDisplayFunc(renderScene)需要一个指针 renderScene()函数回调,这将是负责呈现的一切。在 renderScene()功能将仅回调注册后调用一次。

  • glutTimerFunc(TIMER_MILLISECONDS,processAnimationTimer,0)花费的毫秒数 processAnimationTimer()。最后一个参数就是要传递给回调的定时器的值。在 processAnimationTimer()将不会被调用每个 TIMER_MILLISECONDS ,但只有一次。

  • glutPostRedisplay()函数请求GLUT渲染新帧,所以我们需要每次我们在场景改变的东西时调用它。

  • glutIdleFunc(renderScene)可用于注册一个回调 renderScene()(这并没有使 glutDisplayFunc()无关),但应避免使用此功能,因为没有被接收到的事件当空闲回调连续调用,增加了CPU的负载。

  • glutGet(GLUT_ELAPSED_TIME)函数返回的毫秒数,因为 glutInit 被称为(或第一次调用 glutGet(GLUT_ELAPSED_TIME))。这是我们与GLUT计时器。我知道有高分辨率定时器更好的替代品,但让我们保持这一个现在。

  • GLUT is an OpenGL toolkit and helps with common tasks in OpenGL.
  • The glutDisplayFunc(renderScene) takes a pointer to a renderScene() function callback, which will be responsible for rendering everything. The renderScene() function will only be called once after the callback registration.
  • The glutTimerFunc(TIMER_MILLISECONDS, processAnimationTimer, 0) takes the number of milliseconds to pass before calling the callback processAnimationTimer(). The last argument is just a value to pass to the timer callback. The processAnimationTimer() will not be called each TIMER_MILLISECONDS but just once.
  • The glutPostRedisplay() function requests GLUT to render a new frame so we need call this every time we change something in the scene.
  • The glutIdleFunc(renderScene) could be used to register a callback to renderScene() (this does not make glutDisplayFunc() irrelevant) but this function should be avoided because the idle callback is continuously called when events are not being received, increasing the CPU load.
  • The glutGet(GLUT_ELAPSED_TIME) function returns the number of milliseconds since glutInit was called (or first call to glutGet(GLUT_ELAPSED_TIME)). That's the timer we have with GLUT. I know there are better alternatives for high resolution timers, but let's keep with this one for now.

我觉得这是在转运蛋白是如何呈现的帧使人们不知道它也间距在这个问题上,试图帮助他们是否下跌喜欢它足够的信息。

I think this is enough information on how GLUT renders frames so people that didn't know about it could also pitch in this question to try and help if they fell like it.

实施现状:

现在,我不知道我正确实施由公园提出的第二种方案,的游戏速度依赖于变量FPS 的。有关code表示是这样的:

Now, I'm not sure I have correctly implemented the second solution proposed by Koen, Game Speed dependent on Variable FPS. The relevant code for that goes like this:

#define TICKS_PER_SECOND 30
#define MOVEMENT_SPEED 2.0f

const int TIMER_MILLISECONDS = 1000 / TICKS_PER_SECOND;

int previousTime;
int currentTime;
int elapsedTime;

void renderScene(void) {
    (...)

    // Setup the camera position and looking point
    SceneCamera.LookAt();

    // Do all drawing below...

    (...)
}

void processAnimationTimer(int value) {
    // setups the timer to be called again
    glutTimerFunc(TIMER_MILLISECONDS, processAnimationTimer, 0);

    // Get the time when the previous frame was rendered
    previousTime = currentTime;

    // Get the current time (in milliseconds) and calculate the elapsed time
    currentTime = glutGet(GLUT_ELAPSED_TIME);
    elapsedTime = currentTime - previousTime;

    /* Multiply the camera direction vector by constant speed then by the
       elapsed time (in seconds) and then move the camera */
    SceneCamera.Move(cameraDirection * MOVEMENT_SPEED * (elapsedTime / 1000.0f));

    // Requests to render a new frame (this will call my renderScene() once)
    glutPostRedisplay();
}

void main(int argc, char **argv) {
    glutInit(&argc, argv);

    (...)

    glutDisplayFunc(renderScene);

    (...)

    // Setup the timer to be called one first time
    glutTimerFunc(TIMER_MILLISECONDS, processAnimationTimer, 0);
    // Read the current time since glutInit was called
    currentTime = glutGet(GLUT_ELAPSED_TIME);

    glutMainLoop();
}

这实现不跌的权利。它工作在这个意义上,可以帮助游戏速度是恒定的依赖于FPS。这样从A点移动到B点需要同时无论高/低帧率。不过,我相信我限制了游戏的帧率这种方法。 [修改到时调用回调函数每一帧只会被渲染,这意味着帧率将大致围绕 TICKS_PER_SECOND 帧每秒。这感觉不对,你不应该限制你的强大的硬件,这是错误的。这是我的理解虽然,我还需要计算 elapsedTime 。只是因为我告诉GLUT调用定时器的回调每个 TIMER_MILLISECONDS ,这并不意味着它会一直这样做的时候。]

This implementation doesn't fell right. It works in the sense that helps the game speed to be constant dependent on the FPS. So that moving from point A to point B takes the same time no matter the high/low framerate. However, I believe I'm limiting the game framerate with this approach. [ Each frame will only be rendered when the time callback is called, that means the framerate will be roughly around TICKS_PER_SECOND frames per second. This doesn't feel right, you shouldn't limit your powerful hardware, it's wrong. It's my understanding though, that I still need to calculate the elapsedTime. Just because I'm telling GLUT to call the timer callback every TIMER_MILLISECONDS, it doesn't mean it will always do that on time.]

我不知道我怎么能解决这个问题,并要完全诚实的,我不知道什么是GLUT游戏循环,你知道,而(game_is_running)循环在公园的文章。 [修改这是我的理解是GLUT是的事件驱动的那场比赛循环开始的时候我叫 glutMainLoop() (它从不返回),是吗?]

I'm not sure how can I fix this and to be completely honest, I have no idea what is the game loop in GLUT, you know, the while( game_is_running ) loop in Koen's article. [ It's my understanding that GLUT is event-driven and that game loop starts when I call glutMainLoop() (which never returns), yes?]

我以为我可以注册空闲回调glutIdleFunc()和使用,作为替代的glutTimerFunc() ,仅呈现在必要时(而不是所有的时间像往常一样),但是当我测试一个空的回调(如无效gameLoop(){} ),它基本上是做什么都没有,只有一个黑色的屏幕,CPU飙升至25%,并在那里停留,直到我杀的游戏,它回到正常。因此,我不认为这是走的一条路。

I thought I could register an idle callback with glutIdleFunc() and use that as replacement of glutTimerFunc(), only rendering when necessary (instead of all the time as usual) but when I tested this with an empty callback (like void gameLoop() {}) and it was basically doing nothing, only a black screen, the CPU spiked to 25% and remained there until I killed the game and it went back to normal. So I don't think that's the path to follow.

使用 glutTimerFunc()绝对不是执行基于所有的运动/动画一个好办法,因为我限制我的游戏,以一个恒定的FPS,不冷静。或者,也许我用错了,我的实现是不正确的?

Using glutTimerFunc() is definitely not a good approach to perform all movements/animations based on that, as I'm limiting my game to a constant FPS, not cool. Or maybe I'm using it wrong and my implementation is not right?

究竟如何,我可以有一个恒定的游戏速度可变FPS?更确切地说,我该如何正确地贯彻公园的的恒定的游戏速度与最大FPS 的溶液(第四个关于他的文章)与GLUT?也许这是根本不可能用GLUT?如果不是,有什么是我的选择吗? 什么是这个问题,GLUT?最好的办法(恒定游戏速度)

How exactly can I have a constant game speed with variable FPS? More exactly, how do I correctly implement Koen's Constant Game Speed with Maximum FPS solution (the fourth one on his article) with GLUT? Maybe this is not possible at all with GLUT? If not, what are my alternatives? What is the best approach to this problem (constant game speed) with GLUT?

另一种方法:

我一直在尝试和这里就是我能现在来实现。相反,在计算定时功能经过的时间(这限制了我的游戏的帧率)的我做,现在在 renderScene()。每当改变到现场发生的我称之为 glutPostRedisplay()(即:移动摄像机,有些对象动画等),这将使调用 renderScene()。我可以使用运行时间在这个功能将我的相机实例。

I've been experimenting and here's what I was able to achieve now. Instead of calculating the elapsed time on a timed function (which limits my game's framerate) I'm now doing it in renderScene(). Whenever changes to the scene happen I call glutPostRedisplay() (ie: camera moving, some object animation, etc...) which will make a call to renderScene(). I can use the elapsed time in this function to move my camera for instance.

我的code现在已经变成这样:

My code has now turned into this:

int previousTime;
int currentTime;
int elapsedTime;

void renderScene(void) {
    (...)

    // Setup the camera position and looking point
    SceneCamera.LookAt();

    // Do all drawing below...

    (...)
}

void renderScene(void) {
    (...)

    // Get the time when the previous frame was rendered
    previousTime = currentTime;

    // Get the current time (in milliseconds) and calculate the elapsed time
    currentTime = glutGet(GLUT_ELAPSED_TIME);
    elapsedTime = currentTime - previousTime;

    /* Multiply the camera direction vector by constant speed then by the
       elapsed time (in seconds) and then move the camera */
    SceneCamera.Move(cameraDirection * MOVEMENT_SPEED * (elapsedTime / 1000.0f));

    // Setup the camera position and looking point
    SceneCamera.LookAt();

    // All drawing code goes inside this function
    drawCompleteScene();

    glutSwapBuffers();

    /* Redraw the frame ONLY if the user is moving the camera
       (similar code will be needed to redraw the frame for other events) */
    if(!IsTupleEmpty(cameraDirection)) {
        glutPostRedisplay();
    }
}

void main(int argc, char **argv) {
    glutInit(&argc, argv);

    (...)

    glutDisplayFunc(renderScene);

    (...)

    currentTime = glutGet(GLUT_ELAPSED_TIME);

    glutMainLoop();
}

结论,它的工作,或者看起来是这样。如果我不移动相机,CPU使用率很低,没有什么是被渲染(用于测试目的我只有4000.0f延长一格,而zFar设置为1000.0f)。当我开始移动相机的场景开始重绘本身。如果我继续pressing的移动键,CPU使用率会增加;这是正常的行为。它滴回来时,我停止移动。

Conclusion, it's working, or so it seems. If I don't move the camera, the CPU usage is low, nothing is being rendered (for testing purposes I only have a grid extending for 4000.0f, while zFar is set to 1000.0f). When I start moving the camera the scene starts redrawing itself. If I keep pressing the move keys, the CPU usage will increase; this is normal behavior. It drops back when I stop moving.

除非我失去了一些东西,这似乎是现在的好方法。我没有找到上iDevGames这个有趣的文章实施这一项目可能是受该条所述的问题。上什么是你的想法?

Unless I'm missing something, it seems like a good approach for now. I did find this interesting article on iDevGames and this implementation is probably affected by the problem described on that article. What's your thoughts on that?

请注意,我只是在做这个为了好玩,我没有创造一些游戏至少分发或类似的东西,而不是在不久的将来的意图。如果我这样做,我可能会用除了GLUT别的东西去了。但自从我使用GLUT,和其他比iDevGames描述的问题,你认为这个最新执行足以GLUT?唯一真正的问题,我现在能想到的是,我需要不断的打电话 glutPostRedisplay()每一个场景改变的东西,一直在打它,直到有没有什么新的时间重绘。加入到code,共创美好事业有一点复杂,我想。

Please note that I'm just doing this for fun, I have no intentions of creating some game to distribute or something like that, not in the near future at least. If I did, I would probably go with something else besides GLUT. But since I'm using GLUT, and other than the problem described on iDevGames, do you think this latest implementation is sufficient for GLUT? The only real issue I can think of right now is that I'll need to keep calling glutPostRedisplay() every time the scene changes something and keep calling it until there's nothing new to redraw. A little complexity added to the code for a better cause, I think.

你怎么想的?

推荐答案

供过于求的设计的的游戏循环。当你调用glutMainLoop(),它执行了循环,除了()退出信号没有终止条件。你可以实现你的程序有点像你现在这样做,但你需要一些小的改动。首先,如果你想知道的FPS是什么,你应该把那个跟踪到renderScene()函数,而不是在你的更新功能。当然,你的更新功能被称为以最快的速度由定时器规定而你对待elapsedTime作为帧之间的时间的措施。一般情况下,因为你打电话glutPostRedisplay是缓慢而过剩不会尝试更新屏幕,如果它并不需要(有没有需要重新绘制,如果现场没有改变),这将是真实的。但是,也有其他的倍renderScene将被调用。例如,如果拖动整个窗口的东西。如果你这样做,你会看到一个更高的FPS(如果你正确地渲染功能跟踪FPS)。

glut is designed to be the game loop. When you call glutMainLoop(), it executes a 'for loop' with no termination condition except the exit() signal. You can implement your program kind of like you're doing now, but you need some minor changes. First, if you want to know what the FPS is, you should put that tracking into the renderScene() function, not in your update function. Naturally, your update function is being called as fast as specified by the timer and you're treating elapsedTime as a measure of time between frames. In general, that will be true because you're calling glutPostRedisplay rather slowly and glut won't try to update the screen if it doesn't need to (there's no need to redraw if the scene hasn't changed). However, there are other times that renderScene will be called. For example, if you drag something across the window. If you did that, you'd see a higher FPS (if you were properly tracking the FPS in the render function).

这篇关于恒定游戏速度的独立在OpenGL变量FPS与葡萄糖转运?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆