smooth operator: programming the little things that games can't do without
DESCRIPTION
Looking at the big picture, video games appear to be a kind of immensely intricate machinery. However, when up close, they are clearly made of many small and simple things that only create a smooth experience when working in harmony. A gameplay programmer must exhibit tremendous attention to detail that never becomes a game's killer feature, but is still necessary to make the game - whether indie or AAA - believable and enjoyable. In this talk I will discuss the need for smooth colour blends and organic movement, and the elementary techniques and their mathematics that get the job done, such as interpolation and noise. All of this from a gameplay programmer's point of view, as a series of case studies from our upcoming FPS game: The Adventurer.TRANSCRIPT
Smooth OperatorProgramming the little things that games can't do without
WGK 2012 · August 31, 2012
Leszek [email protected]
www.thefarm51.com
Hello, target audience!
www.thefarm51.com
● Beginner programmers● You can learn some cool stuff (hopefully)
● Beginner gameplay programmers● Intermediate programmers
● Maybe you'll learn a thing or two● Seasoned gameplay programmers
● You'll be bored to death :(
Far from done
www.thefarm51.com
WORK INWORK INPROGRESSPROGRESS
All game footage in these slides is work in progress and is not representative of final quality of the game.
Why so smooth?
www.thefarm51.com
● Rough and sharp things are, well, rough and sharp● We all like pleasant stuff● Jerky movement and rough transitions create
an impression of being unfinished, unprofessional, lacking polish
● Few processes in nature happen instantly● Kinematics: movement derives from velocity,
velocity derives from acceleration● Physical and chemical reactions all take time
www.thefarm51.com
Organic motionVideo source: http://youtu.be/geg3ck3OT5Y
www.thefarm51.com
Organic motionImage source: http://commons.wikimedia.org/wiki/File:1-D_kinematics.svg
Visual feedback of game logic
www.thefarm51.com
● Gameplay logic is usually driven by a set of variables
● These variables are also used for visual feedback, either directly or indirectly (visual variables are derived from them in some way)● Discrete variables – potentially rough
transitions, often need smoothing out for appearance
● Continuous ones – usually less problematic
Visual feedback of game logic
www.thefarm51.com
● Discrete transitions can be smoothed out for visuals by interpolation● It's not nearly as bad in reality as you may think
after taking a class in numerical methods!
Lerp
www.thefarm51.com
● Mother of all interpolations! Used since antiquity
● Alpha term aka time● y = α · y0 + (1 – α) · y1● α [0; 1]∈
Why alpha is cool
www.thefarm51.com
● It's simply percentage! (normalization FTW)● It's absurdly easy to convert lerps into
higher-order exponential interpolation! y = xz
Why alpha is cool
www.thefarm51.com
● It's elementary to reverse its direction! αi = (1 – α0)
z
● It's trivial to make it time-dependent! α(t) = α(t - 1) + Δt · v
Moar interpolation!
www.thefarm51.com
● Lerp can also be applied to vectors, Euler angles etc. (component-wise, using the same alpha term)
● Quaternions can be slerped● Polynomial interpolation, eg. cubic
(results in a C1 function), exponential, sine interpolation
● Ease-in, ease-out, ease-in-ease-out● Decelerating interpolation:
f(t) = f(t – 1) + α · [t – f(t – 1)]
What's that noise?
www.thefarm51.com
● Entropy is a major natural force● In opposition to order and regularity● Humankind strives for the latter
● Need to simulate entropy for believable natural and organic features
● Lots of academic research on noise● Random number generators● Noise pattern algorithms
What's that noise?
www.thefarm51.com
● Noises can be combined for procedural textures
● No memory/bandwidth limits● No mapping problem● Limitless possibilities of effects
www.thefarm51.com
Case 1: Generic character animation
Case 1: Generic character animation
www.thefarm51.com
● Skeletal animation data consists of key frames
● Need to interpolate (aka “inbetween”, or “tween”) between key frames for continuous motion independent of simulation speed
● But this is handled by animation playback code● Non-blended animation transitions look
bad● I mean, really, REALLY bad!● The effect is known as “popping”
www.thefarm51.com
PoppingVideo clip: 01-popping.m4v
Popping
www.thefarm51.com
Solution:● Interpolate the skeleton poses
resulting from the contributing animations
● Lerp bone translations● Slerp bone quaternions
www.thefarm51.com
Animation blendingVideo clip: 02-blending.m4v
Animation blending
www.thefarm51.com
Yeah, I know – nothing fancy, every game has it...
www.thefarm51.com
Case 2: Camera target following
Case 2: Camera target following
www.thefarm51.com
Challenges:● Camera can translate and rotate● Target can move as well!
● Fortunately, we can ignore target rotation● Target translation changes angle delta to
target!
Moving target problem
www.thefarm51.com
angledelta
viewer
target angle delta
viewer
target
t = t0 t = t1
www.thefarm51.com
Iteration 1: LerpVideo clip: 03-lerp.m4v
Iteration 1: Lerp
www.thefarm51.com
● That's awful!● Direct result of lerping – no easing, motion feels
absolutely inorganic● Therefore we need an interpolation with ease
www.thefarm51.com
Iteration 2: Decelerating interpolationVideo clip: 04-decel.m4v
Iteration 2: Decelerating interp.
www.thefarm51.com
● Okay, so that actually looks fine!... sometimes● But only as long as the initial angle delta is
not extreme...● This is ease-out only● We need to ease-in, too!
Iterations 3..n
www.thefarm51.com
Fast-forward through some trial, lots of error and a bit of despair...
Iteration n + 1
www.thefarm51.com
How about this:● At start, compute initial angle delta
Δ0 = Θc(0) - Θt(0)● Store the current angle delta to target Δ(t)● Compensate for target translation by adding
the delta of deltas to camera rotation (we need to go deeper!)
Θc(t) = Θc(t – 1) + Δ(t) – Δ(t – 1)● Interpolate over Δ0 with a simple ease-in-
ease-out
www.thefarm51.com
Iteration n + 1Video clip: 05-compensation.m4v
Iteration n + 1
www.thefarm51.com
● Phew! That'll do.● The delta of deltas compensates almost
perfectly for target movement● Only the most extreme of cases may still
cause problems (very fast-moving target, very short distance to target)
● Ease-in-ease-out makes for a nice, smooth feeling
www.thefarm51.com
Case 3: Flashlight
Case 3: Flashlight
www.thefarm51.com
Challenges:● Spotlight must be aligned correctly with the
1st person mesh● But 1st person mesh is drawn in a different FOV!
● Spotlight must change size and colour according to the flashlight state
● Normal light – static shape, dynamic colour● Focused light – dynamic shape and colour● Dead battery – static shape, dynamic colour,
blinking
Light alignment vs FOV
www.thefarm51.com
Light alignment vs FOV
www.thefarm51.com
Light alignment vs FOV
www.thefarm51.com
Light alignment vs FOV
www.thefarm51.com
Light alignment vs FOV
www.thefarm51.com
Light alignment vs FOV
www.thefarm51.com
Off to an easy start● Light is obviously rendered at global
FOV● Configurable offset from camera● Dynamic light influence switched off
for 1st person meshes to avoid artifacts
www.thefarm51.com
Oops! Gimbal lock!Video clip: 06-gimbal.m4v
Oops! Gimbal lock!
www.thefarm51.com
● Quick fix: use quaternions instead for composing the rotations together
QuatToRotator( QuatProduct( QuatInvert( QuatFromRotator(Rotation)), QuatFromRotator(SocketRotation) ))
From logic to visuals
www.thefarm51.com
● Logic control variables● Current item state (discrete)● Remaining battery power (continuous)
● Light cone size (continuous)● Derived from state transition and, if focused, from
battery power● Light brightness and colour (continuous)
● Derived from state transition and battery power● Light blink state (when the battery is dying)
Light cone size
www.thefarm51.com
● Recap: drive light volume mesh scale and spotlight cone angle by state and battery power
● For state, let's try a helper variable and a lerp (0: unfocused, 1: focused)
if (IsFlashLightBeamActive()) FocusAlpha = FMin(1.f, FocusAlpha + DeltaTime * FocusSpeed);else FocusAlpha = FMax(0.f, FocusAlpha - DeltaTime * FocusSpeed);
Bonus!
www.thefarm51.com
● FocusAlpha may be easily applied to drive visuals by beam focus, such as FOV
FREE!!!FREE!!!
Light cone size
www.thefarm51.com
● Recap: drive light volume mesh scale and spotlight cone angle by state and battery power
● Final light cone scale:ConeScale = Lerp(1.f, ((1.f – PowerBlinkThreshold) * Power ** 2.f + PowerBlinkThreshold) * FocusSizeMultiplier, FocusAlpha);
www.thefarm51.com
Light cone sizeVideo clip: 07-size.m4v
Light brightness & colour
www.thefarm51.com
● Recap: drive spotlight brightness by state and battery power, and colour by battery power only
● Brightness is a piece of cake:NewBrightness = Lerp( UnfocusedBrightness, FocusedBrightness, FocusAlpha * Power);
Light brightness & colour
www.thefarm51.com
● Recap: drive spotlight brightness by state and battery power, and colour by battery power only
● Colour is just as easy:NewColor = LerpColor( LowBatteryLightColour, FullBatteryLightColour, Power);
www.thefarm51.com
Light brightness & colourVideo clip: 08-colour.m4v
Light blinking
www.thefarm51.com
● A little noise will come in handy:if (bDeadBattery) bBlinking = Power < 0.925 && Rand(100) < 8;else if (Power <= PowerBlinkThreshold) bBlinking = Power <= 0.f || FRand() < (1.f - Power / PowerBlinkThreshold);
www.thefarm51.com
Light blinkingVideo clip: 09-blinking.m4v
www.thefarm51.com
Flashlight in actionVideo clip: 10-flashlight.m4v
General tips
www.thefarm51.com
● Fractions are your best friends!● Alpha term is usually just a floating point
division away● Bias and scaling is easy
● Easing is cheap● Use whenever motion or transition feels robotic
● Ordinary rand() is often noisy enough● Plenty of other noise functions available if not
www.thefarm51.com
Questions?
Thank you!
Like us on Facebook!http://www.facebook.com/farm51http://www.facebook.com/ProjectAdventurer
www.thefarm51.com