9

我正在写一个老式的 ASCII DOS 提示游戏。老实说,我正在尝试模仿 ZZT 来了解更多关于这个品牌的游戏设计(即使它已经过时了)

我做得很好,我的全屏文本模式可以工作,我可以毫无问题地创造世界和四处走动,但我找不到合适的渲染时间方法。

我知道我的渲染和预渲染代码很快,因为如果我不从 time.h 添加任何 delay()s 或 (clock()-renderBegin)/CLK_TCK 检查,渲染速度非常快。

我不想使用 delay() 因为它是我的知识平台特定的,最重要的是,它延迟时我无法运行任何代码(如用户输入和处理)。所以我决定做这样的事情:

do {
    if(kbhit()) {
        input = getch();
        processInput(input);
    }

    if(clock()/CLOCKS_PER_SEC-renderTimer/CLOCKS_PER_SEC > RenderInterval) {
        renderTimer = clock();
        render();
        ballLogic();
    }
}while(input != 'p');

在“理论上”应该可以正常工作。问题是,当我运行这段代码(将 RenderInterval 设置为 0.0333 或 30fps)时,我没有得到接近 30fps 的任何地方,我得到的最大值更像是 18。

我想也许我会尝试将 RenderInterval 设置为 0.0 以查看性能是否提高了......它没有。我(RenderInterval 为 0.0)达到最高 ~18-20fps。

我虽然可能因为我不断调用所有这些时钟()和“除以”方法,我正在减慢 CPU 速度,但当我从 if 语句的括号中取出渲染和 ballLogic 调用并将 RenderInterval 设置为0.0 我再次获得了超快的渲染速度。

这对我来说没有任何意义,因为如果我离开 if check in,它不应该运行得一样慢吗?我的意思是它仍然需要做所有的计算

顺便说一句,我正在使用 Borland 的 Turbo C++ V1.01 进行编译

4

5 回答 5

2

最好的游戏体验通常是通过与显示器的垂直回扫同步来实现的。除了提供时间,这也将使游戏在屏幕上运行更流畅,至少如果你有一个 CRT 显示器连接到计算机。

在 80x25 文本模式下,垂直回扫(在 VGA 上)发生 70 次/秒。我不记得 EGA/CGA 上的频率是否相同,但我很确定 Hercules 和 MDA 上的频率是 50 Hz。通过测量例如 20 帧的持续时间,您应该对正在处理的频率有一个足够好的估计。

让主循环类似于:

  while (playing) {
     do whatever needs to be done for this particular frame
     VSync();
  }

  ...  /* snip */

  /* Wait for vertical retrace */
  void VSync() {
    while((inp(0x3DA) & 0x08));
    while(!(inp(0x3DA) & 0x08));
  }
于 2010-09-05T11:26:00.833 回答
1
clock()-renderTimer > RenderInterval * CLOCKS_PER_SEC

如果您预先计算RenderInterval * CLOCKS_PER_SEC零件,计算速度会更快,甚至可能更快。

于 2010-07-22T13:13:34.810 回答
1

我弄清楚为什么它没有立即渲染,我创建的计时器很好,问题是实际的clock_t 只精确到.054547XXX 左右,所以我只能以18fps 渲染。我解决这个问题的方法是使用更准确的时钟......这是另一回事

于 2010-07-24T11:30:03.080 回答
0

正如您在最近的问题中所发现的那样,您受到 CLOCKS_PER_SEC 的限制,它只有大约 18 个。每个离散的时钟值都会得到一帧,这就是为什么您被限制为 18fps 的原因。

您可以使用屏幕垂直消隐间隔进行计时,这对于游戏来说是传统的,因为它避免了“撕裂”(一半屏幕显示一帧,另一半显示另一帧)

于 2010-07-23T15:43:39.070 回答
0

怎么样:你从 x (=clock()) y (=renderTimer) 中减去。x 和 y 都除以 CLOCKS_PER_SEC:

clock()/CLOCKS_PER_SEC-renderTimer/CLOCKS_PER_SEC > RenderInterval

写这样不是更有效率吗:

( clock() - renderTimer ) > RenderInterval

我看到的第一个除法问题是你不会从中得到一个实数,因为它发生在两个长整数之间。secons 的问题是,将 RenderInterval * CLOCKS_PER_SEC 相乘更有效,这样就可以摆脱它,简化操作。

添加括号使其更易读。也许通过简化这个公式,你会更容易出错。

于 2010-07-22T13:14:26.323 回答