🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Under-drive & Over-drive

posted in A Keyboard and the Truth for project 96 Mill
Published February 09, 2015
Advertisement
Under-drive & Over-drive

This is a situation that comes up a lot in game development; It recently reared its head again when adding a 'ghost writer' text effect to our NPC dialogue system.

I thought I would take a moment to talk about the crux of the issue so that some folks might understand it better.


The Problem

When developing a 'ghost writer' text feature, I found myself first doing a word for word string build up.

An update event would happen, and I would simply move my nextWordIndex forward by one.

To throttle this I had a countdownTimer, which, when a new word was shown, I added an amount to; and would decay this timer in the update method.

So to recap, new word shown, timer set, timer elapses, show next word.


My co-developer Brian, saw this effect and felt it was too choppy; instead he wanted it to spit out single characters, instead of discrete words.

I made some quick modifications to test this, and found that adjusting my CPS (characters per second) did nothing up to a point.

Since I have seen this effect before, I quickly realized what was wrong.


Discrete Incrementing

Because in my update method, I would check for timer expiration, and perform the wordIncrement (now character increment) this meant, I could NEVER achieve faster word incrementing than One Character per Frame.

At a 1:1 ratio this is considered 'Drive' the input shaft (the game loop) is turning the output shaft (the cps incrementor) at 100%.

When I was doing words per second I was working at a comfortable Under-Drive, or, a ratio less than 1:1; such that multiple discrete frames would have to pass before the next word was shown.

[sub]I often relate programming to real-world mechanics, in this case, some may see that a game-loop, to me feels a lot like a drivetrain of some machine.[/sub]


Simply increasing my CPS in an effort to speed up the incrementor saturated into 1CPS.


The Solution

The root of the problem here, is that I am relying on a timer expiration and a single fixed increment of an index.

This conditional discrete operation means that it is fixed to a maximum of the frame rate.

Thankfully the solution is very simple

First, it probably makes sense to generalize how we are displaying the ghost-written string; to instead of string-building, using a sub-string instead:

Imagine text.subString(0,Math.floor(ll)); where 0 is the starting index, and ll is lineLength; the number of characters to display (with a max of text.length, of course).

[sub]Note the Math.floor(), ll is a floating point variable (this is essential) but we can only display integer length strings, so a truncation is needed.[/sub]

With this, we can remove our countdownTimer machinery, and instead, simply 'drive' ll:

ll += frameTimeSeconds * CPS;

We can see above that we push ll forward using our measured frame time, and a constant 'Characters Per Second' the throttle by which you wish to print characters.

a typical under-drive scenario might be when we are achieving a frame time of 0.016 or 60FPS; meaning each frame is executing at 1/60th of a second.

If we imagine a CPS of 1 (one character printed per second) we see that we will push ll forward only 0.016 'characters' per frame: this is under-drive because the game loop is 'rotating' multiple 'revolutions' to only a single 'revolution' (character increment).


In an over-drive scenario; let us imagine we are operating with a low frame rate '0.033' (30FPS); and a higher CPS of 40 (40 characters printed per second).

[sub]1.32 = 0.033 * 40[/sub]

We can see here we are now pushing ll one whole character and about 1/3 of a character per frame, this means we are operating at a ratio over 1:1, or 'Over-drive'.

The important effect here is that we are preserving non-integral time accumulation, instead of just clamping/saturating it away, as over-drive increases, we could/would begin to see multiple discrete characters being printed per-frame, in order to 'keep up'.
4 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement