2
\$\begingroup\$

I think this is a very basic game programming question, but I am bad with math and new to programming & game programming so I'm looking for some advice. I'm making a 2D sprite game for iOS. Every frame in my game loop I check to see if player moves past a boundary in the game; if so, I scroll the camera's view:

    if playerPosition.x > rightBound {
        let amt = playerPosition.x - rightBound
        camera.position = CGPoint(x: camera.position.x + (amt * 0.1), y: camera.position.y)
    }

This works OK; the camera scrolls slowly when the player exceeds the boundary by a small amount and scrolls more quickly when they exceed the boundary by a larger amount. So the scrolling speed scales up linearly. However, I would like the scrolling speed to scale up faster, perhaps in at a more "exponential" rate. (Enter my terrible understanding of math...)

I don't know the best way to express this mathematically. I know that exponential growth is an actual thing in math, but I actually had to look it up on Wikipedia. And I don't know the best way to implement that in game programming.

To clarify with a simple hypothetical, say that the boundary x position is at 0. When the player moves past it in the first frame his position is 1, so the difference between the two positions is 1. Then next frame his position is 2 so the difference increases to 2, and so on. So the difference between the positions grows like 1, 2, 3, 4, 5, 6, etc. However, I want to calculate the difference between these positions so that my result grows more like 1, 2.1, 3.3, 4.5, 6.1, 7.8, etc.

This graph suggests that I might want to use cubic growth or exponential growth:

enter image description here

But I'm not sure how to express such a formula programmatically. Perhaps more importantly, I don't know if that is the best way to approach this sort of calculation from a game programming perspective. This calculation will run four times every frame, and performance is a concern so I'm trying to find an efficient solution rather than some crufty version I arrive at by myself.

Can anyone provide some advice? I'm working in Swift but I think this is a language-agnostic problem. If you express the answer in another language I can probably figure out how to implement that in Swift.

UPDATE:

Thanks to tom10, I ended up going with this formula for exponentially increasing my camera scrolling speed based on how far the player has passed beyond a boundary:

if playerPosition.x > rightBound {
    let dx = playerPosition.x - rightBound
    let baseAmt = dx * 0.033
    let amt = baseAmt + pow(2, baseAmt * 0.25)
    camera.position = CGPoint(x: camera.position.x + amt, y: camera.position.y)
}

0.033 and 0.25 are "magic numbers" that work well for my game; I arrived at them by trial & error.

\$\endgroup\$
3
\$\begingroup\$

To put these into a formula, it seems that you want something that varies with the distance from the boundary, so first calculate that parameter (I'll call it dx below), and then put that into whatever formula you want.

Note that some terms will preserve the sign of the distance and some won't (exp(x) and x*x won't but x*x*x will) so excursions to the left vs right of the boundary need to be thought through differently in two cases.

if playerPosition.x > rightBound {
    let dx = playerPosition.x - rightBound
    let amt = 0.1*dx*dx*dx  // or pow(dx, 3), or exp(abs(x))
    camera.position = CGPoint(x: camera.position.x + amt, y: camera.position.y)
}

I'd skip the exponential if I were you. For example, exp(0) = 1, which can be dealt with, but it's a hassle, and for small dx it won't make much difference anyway.

If you want to fine tune things, I think you'd be better off using something like a*dx + b*dx*dx*dx, where you tune the parameters a and b to your liking. Here the linear term will be most relevant at small dx and the cubic for larger dx.

\$\endgroup\$
  • \$\begingroup\$ Thanks, I will play around with the numbers using those formulas and see which works best. Wish I had your brain for math :) \$\endgroup\$ – peacetype Apr 3 '18 at 22:07
  • \$\begingroup\$ In case it helps anyone, I updated my answer with an implementation of this solution. \$\endgroup\$ – peacetype Apr 4 '18 at 6:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.