3
\$\begingroup\$

I have the following problem:

In a 2D game the screen can scroll in any of the 4 directions. Basically, the center of the screen during scrolling moves from (x1,y1) to (x2, y2) whereby (x1,y1) is the current focus and (x2, y2) is the desired focus. The latter changes frequently depending on what happens in the game.

At the moment, I only scroll if the distance d between (x1,y1) and (x2, y2) is above a certain threshold and also I am scrolling the faster the larger d is.

This already results in a quite smooth movement of the screen but I am still not completely happy with it. I was wondering if there are any standard or best-practice approaches to the problem of smoothing the path of the screen? I can imagine something with b-splines but I have no concrete idea of how to approach this.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

While this question is a little abstract, I can share a few tips/realizations I've had over the years.

First, 'smooth' normally means 'more continuous derivatives.' If you are moving at speed X, you are all good. your position is v*t (continuous), the derivative of that is v (continuous), and all derivatives of that are 0 (continuous). However, if you suddenly stop at time T, your position is v*t -> v*T (continuous), but your speed is X -> 0 (discontinuous at T). So maybe to solve this you 'slow down' when close to T rather than coming to an immediate stop.

Some other side notes - the 'farther away' the motion is from the player, the more tolerant they'll be of these discontinuities. Closest: camera, next: avatar, farther: enemies/ais. A super rough guideline - the camera likes to have inf continuous derivatives, the avatar can survive w/ continuous movement and velocity (but then have instant acceleration, but continuous acceleration is better - that's why analog controller input 'feels' better than digital or keypresses), enemies can be a lot crazier.

Ok, now let's analyze your situation.

pos = if (d > D) pos
      else (pos + f(d));

So, let's analyze where the discontinuities could be.

The first obvious point is d = D, where we switch from moving to not moving. What cases would this be continuous and what cases would this be discontinuous? So on one side pos is constant and the velocity == 0, so on the otherside we need our velocity to approach 0 as d -> D. Ok, what's the simplest function that does that? What about f(d) = 0, hah! Of course this works, but that just means the camera never moves! Ok, next simplest function f(d) = k. Now we get there, but definately have a discontinuity at D == d. Ok, next simplest: f(d) = k * d. That has some nice features that we'll get to in a sec but immediately we notice that k*d is non-zero for any D != 0. But we can fix that by subtracting out a D: f(d) = k * (d - D). Now f(d) = 0 when d == D.

Awesome, now we are continuous across d, what about when d > D? Then we are strictly in the case

x = x + k(D-d)

where x is the camera position. Taking the derivative (using the notation x' := the derivative of x)

x' = k(D-d)

cool, and noting that d is a function of x (the camera position) and P the focus position

x' = k(D - (x - P))

interesting, we have a first order differential equation, which i'll skip the hairy details but that means the solution is in the form

f(x) = A * exp(B(x - C))

which is pretty neat because exp(...) has infinite continuous derivatives - exactly what we are looking for (and probably why you settled on that scheme in the first place!)

So that's pretty awesome! But you can go deeper and deeper. Note that this is the case for the focus position P being constant - what happens when the focus changes/is moving? Is that a function of analog stick position? A binary function of a key being pressed? A cut in a cutscene? And so on. By unrolling the complexity of what's driving your motion and understanding what is actually causing what to happen, you can add and adjust constants and factors and functions, normally in the service of 'smoothness' (but sometimes for other reasons like 'keep the player on screen' or 'avoid ringing' or 'avoid framerate dependance') to achieve enjoyable results.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .