Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASCII DOS Games - Rendering methods

I'm writing an old school ASCII DOS-Prompt game. Honestly I'm trying to emulate ZZT to learn more about this brand of game design (Even if it is antiquated)

I'm doing well, got my full-screen text mode to work and I can create worlds and move around without problems BUT I cannot find a decent timing method for my renders.

I know my rendering and pre-rendering code is fast because if I don't add any delay()s or (clock()-renderBegin)/CLK_TCK checks from time.h the renders are blazingly fast.

I don't want to use delay() because it is to my knowledge platform specific and on top of that I can't run any code while it delays (Like user input and processing). So I decided to do something like this:

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

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

Which should in "theory" work just fine. The problem is that when I run this code (setting the RenderInterval to 0.0333 or 30fps) I don't get ANYWHERE close to 30fps, I get more like 18 at max.

I thought maybe I'd try setting the RenderInterval to 0.0 to see if the performance kicked up... it did not. I was (with a RenderInterval of 0.0) getting at max ~18-20fps.

I though maybe since I'm continuously calling all these clock() and "divide this by that" methods I was slowing the CPU down something scary, but when I took the render and ballLogic calls out of the if statement's brackets and set RenderInterval to 0.0 I get, again, blazingly fast renders.

This doesn't make sence to me since if I left the if check in, shouldn't it run just as slow? I mean it still has to do all the calculations

BTW I'm compiling with Borland's Turbo C++ V1.01

like image 795
Parad0x13 Avatar asked Jul 22 '10 12:07

Parad0x13


3 Answers

The best gaming experience is usually achieved by synchronizing with the vertical retrace of the monitor. In addition to providing timing, this will also make the game run smoother on the screen, at least if you have a CRT monitor connected to the computer.

In 80x25 text mode, the vertical retrace (on VGA) occurs 70 times/second. I don't remember if the frequency was the same on EGA/CGA, but am pretty sure that it was 50 Hz on Hercules and MDA. By measuring the duration of, say, 20 frames, you should have a sufficiently good estimate of what frequency you are dealing with.

Let the main loop be someting like:

  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));
  }
like image 174
SteinNorheim Avatar answered Nov 02 '22 23:11

SteinNorheim


clock()-renderTimer > RenderInterval * CLOCKS_PER_SEC

would compute a bit faster, possibly even faster if you pre-compute the RenderInterval * CLOCKS_PER_SEC part.

like image 30
Ofir Avatar answered Nov 03 '22 00:11

Ofir


I figured out why it wasn't rendering right away, the timer that I created is fine the problem is that the actual clock_t is only accurate to .054547XXX or so and so I could only render at 18fps. The way I would fix this is by using a more accurate clock... which is a whole other story

like image 1
Parad0x13 Avatar answered Nov 02 '22 22:11

Parad0x13