0
\$\begingroup\$

Please bear with me as I've been spending some time lately trying to get a better grasp of some game dev fundamentals. My specific issue is a direct result of trying to apply what I've read about here: When should I use a fixed or variable time step?

I understand that a common option is to write your game framerate-dependent and be done with it. However, once you mix in SKAction's or physics bodies, this seems like a good way for things to get out of sync. For example, one scenario I can think of is something like an endless runner where the earth is moving beneath you at a steady rate (.position.x -= someDistance) mixed with other objects whose positions are updated with a [SKAction moveTo: duration:], or physics bodies whose positions are updated by applying a force/impulse.

So it makes sense to me that the solution to this problem is to decouple game world updates from frame redraws. This means not using [SKScene update:] for world updates and instead coming up with your own game loop.

So I guess my question is twofold. Am I on the right track or am I off-base with any of my assumptions? Does Sprite Kit have a game loop set up outside of [SKScene update:] that is redraw independent, and whose resolution I can specify, that I can leverage? NSTimer has turned out to be way too inaccurate in my tests. Specifically a practical example would be great.

\$\endgroup\$
  • \$\begingroup\$ Are you taking into account the ellapsed game time in your calculations of velocity? \$\endgroup\$ – Shroeder Oct 28 '14 at 14:18
  • \$\begingroup\$ Based on my understanding, what I believe I should implement is option 3 in this answer: gamedev.stackexchange.com/a/1619/54348 Option 1 is not an option because of what I describe above and that is that SKAction's and physics bodies are updated independently of framerate (as well they should). So I'm trying to better understand where and how to implement such a solution as that option in iOS. Or more specifically, how I would set up such an update loop outside of [SKScene update:] or am I even grasping the concept correctly? \$\endgroup\$ – Manny Oct 28 '14 at 15:27
0
\$\begingroup\$

I spend a bit more time on this and I do think I was making a few wrong assumptions. First of all, I think one big mistake was in thinking that I should avoid [SKScene update:] for framerate-independence. But since iOS devices are vsync'ed, and the update method is coupled to screen redraws, I can reliably expect that that method will fire every 1/60th of a second (60fps) at best, and when performance degrades, it'll step down in discrete increments. That is: 30fps (60/2), then 20fps (60/3), then 15fps (60/4), etc. This is because if load is too much that an updated frame 1/60th of a second later is not ready - whatever was drawn last is repeated - the next opportunity to draw an update only comes 1/60th of a second after that and so on.

So what this tells me is that I should always be able to figure out the number of frames I need to catch up to. My understanding now is that this is what an accumulator does. Anyhow, here's the code more or less:

var lastTime: CFTimeInterval = 0.0
override func update(currentTime: CFTimeInterval) {

    if (lastTime == 0.0) { lastTime = currentTime }

    var accumulatedFrames = round((currentTime - lastTime) * 60.0) // assume updates at 60hz and catch up if we drop below that

    lastTime = currentTime // for the next update

    // update the world as many times needed to "catch up"
    while (accumulatedFrames > 0) {
        updateMyWorld()
        accumulatedFrames--
    }
}

It appears to be working well but I would love if someone could confirm my approach.

\$\endgroup\$

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.