Results 1 to 2 of 2

Thread: Rendering at a constant rate

  1. #1

    Rendering at a constant rate

    I've got struck badly by nostalgia, so I've whipped out go32v2 version of fpc and decided to make actual DOS game. Rendering, etc. I can manage, but I want to know how can I do cpu-independent timing so game will render at a constant rate no matter of the cpu used.

  2. #2
    You will need to have some time-measuring function. If you were using e.g. SDL, you could use the libraries built-in function, but on DOS I guess you'd have to rely on FPC's built-in functions from the SysUtils unit:
    Code:
    TimeStampToMSecs(DateTimeToTimeStamp(Now()))
    Using that, you get a timestamp with x1000 scaling (so if you want seconds, you div 1000). Now what you need to do in the game loop is basically:
    1. Record the timestamp before first entering the loop.
    2. While TimeDifference := GetTimestamp() - OldStamp is less than your game cycle length, call some kind of Delay() function so you don't hog the CPU.
    3. Calculate the number of game cycles you need to process - so basically difference_in_timestamps div CYCLE_LENGTH.
    4. Call the CalculateGameStep() function as many times as needed.
    5. Advance the OldStamp variable by cyclesProcessed * CYCLE_LENGTH.
    6. Render the frame
    7. Loop back to step 2

    Regarding step 5 - Yes, you should add cyclesProcessed * CYCLE_LENGTH to OldStamp. You don't want to set this via OldStamp += TimeDifference, because if you have a 16ms cycle (60FPS) and TimeDifference is 20ms, then the next cycle should be processed 12ms from now, not 16. This way your game should always run the same. If your CPU is faster than needed, you will wait on step 2 until enough time has passed that you actually need to calculate the game cycle. If you get a hiccup, the game will detect that it needs to process several cycles, do that, and only then render a frame.

    Of couse, you can just go with a variable timestep (so instead of a fixed CYCLE_LENGTH, you just use TimeDifference, but this way your calculations will go off if you experience a slowdown - e.g. you might not detect a collision, because the TimeDifference will be so big that doing something like Bullet.X += Bullet.Xvelocity * TimeDifference / TICKS_PER_SECOND will cause the bullet to teleport across half the map.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •