C++ ASCII DOS游戏-呈现方法

C++ ASCII DOS游戏-呈现方法,c++,ascii,render,dos,turbo-c++,C++,Ascii,Render,Dos,Turbo C++,我在写一个老式的ASCII DOS提示游戏。老实说,我正试图模仿ZZT来更多地了解这个品牌的游戏设计(即使它是过时的) 我做得很好,让我的全屏文本模式工作,我可以创造世界和移动没有问题,但我找不到一个像样的时间方法为我的渲染 我知道我的渲染和预渲染代码很快,因为如果我不从time.h添加任何delay()s或(clock()-renderBegin)/CLK_TCK检查,渲染速度会非常快 我不想使用delay(),因为它是特定于我的知识平台的,而且我不能在延迟时运行任何代码(如用户输入和处理)。

我在写一个老式的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

我想可能是因为我一直在调用所有这些clock()和“除以那个”方法,我让CPU慢了一些可怕的事情,但是当我把render和ballLogic调用从if语句的括号中拿出来,并将RenderInterval设置为0.0时,我得到的渲染速度再次非常快

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

我正在用Borland的Turbo C++ V1.01

编译
clock()-renderTimer > RenderInterval * CLOCKS_PER_SEC

如果预先计算
RenderInterval*CLOCKS\u PER__second
部分,计算速度可能会更快。

这是怎么回事:从x(=clock())y(=renderTimer)中减去。x和y都被时钟每秒除以:

clock()/CLOCKS_PER_SEC-renderTimer/CLOCKS_PER_SEC > RenderInterval
写下这样的话不是更有效吗

( clock() - renderTimer ) > RenderInterval
我看到除法的第一个问题是,你不能从中得到一个实数,因为它发生在两个长整数之间。secons的问题是,将RenderInterval*CLOCKS_乘以每秒更有效,这样就可以消除它,简化操作


添加括号使其更清晰。也许通过简化这个公式,你会更容易发现问题所在。

正如你在最近的问题中所发现的,你受到每秒时钟的限制,只有大约18秒。时钟的离散值为一帧,这就是为什么限制为18fps


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

我知道为什么它不能立即渲染,我创建的计时器很好。问题是实际时钟仅精确到.054547XXX左右,因此我只能以18fps的速度渲染。我解决这个问题的方法是使用更精确的时钟。。。这完全是另一回事

最好的游戏体验通常是通过与显示器的垂直回程同步来实现的。除了提供计时功能外,这还将使游戏在屏幕上运行更加流畅,至少在您将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));
  }

谢谢你的回复,我看到了优化。尽管如此,这个问题仍然存在。尽管编译器对循环进行了各种优化,但它可以创建特性(特别是当它们包含分支时)——试着在这两种情况下查看生成的代码。事实上,处理器也做了一些类似的工作(查找分支预测)。我检查了预处理器,但找不到启用了哪些优化。我尝试了这些公式优化,但仍然得到相同的结果。如果强制RenderInterval=1会怎么样?你和我都是,caf。(
#throwstar seek
)@Parad0x13:如果您不介意离开DOS,我编写了一个库来在SDL支持的任何平台上模拟这种图形样式:如果您存储来自“clock()”的结果并分配存储的值,您将保存对它的调用(最快的代码是您不调用的代码),它将更加准确(否则,您将失去第一次调用'clock()',完成所有数学运算和处理分支之间的时间)。这种精度损失将使游戏运行速度比您希望的慢,即使您不再最大限度地使用cpu。(编辑:哈哈,刚刚看到了这张表上的日期,哦)