SpriteKit's Update Function: time vs. framerat

2019-04-24 13:38发布

问题:

I'm new to programming and Spritekit in general, and am interested in exploring the relationship between milliseconds & framerate, and how the update function is used as an intermediary between both.

Framerate vs. milliseconds

Essentially, the main difference between framerate and time is that time is always consistant, while framerate is not (it could dip due to intensive graphics procedures). However, time is usually checked and set during SKScene's update event (which is called every frame), so I'm trying to figure out how time is correctly calculated, when you don't know how many frames are going to be in a second.

Example

I am currently looking at the update event of a space shooter game, where the update function is responsible for counting time intervals before spawning another alien. You can view the full code here: http://www.globalnerdy.com/2014/08/10/a-simple-shoot-em-up-game-with-sprite-kit-and-swift-part-one-last-things-first-the-complete-project/

// Called exactly once per frame as long as the scene is presented in a view
// and isn't paused
override func update(currentTime: CFTimeInterval) {
    var timeSinceLastUpdate = currentTime - lastUpdateTime
    lastUpdateTime = currentTime
    if timeSinceLastUpdate > 1 {
        timeSinceLastUpdate = 1.0 / 60.0
        lastUpdateTime = currentTime
    }
    updateWithTimeSinceLastUpdate(timeSinceLastUpdate)
}

Problem

I can't seem to figure out why timeSinceLastUpdate is set to 1.0 / 60. I know it has to do with reconciling between framerate and seconds, but can someone explain this to me? Also, why are we allowed to use decimals? I thought time intervals were of type Int.

More importantly, is the purpose of this to keep the gameplay from slowing down during dips in framerate? Thanks for reading!

回答1:

SpriteKit doesn't know how many frames are going to be in a second, but it can tell you how much time has elapsed since it finished drawing the previous frame. If your game code has any time-dependent logic, this is something you'll want to know. For example, you might be doing something like position += velocity * timeSinceLastUpdate to move sprites around because you don't need a full-blown physics engine.

Framerate is frames per second: SpriteKit tries to run your game at 60 frames per 1 second. That means the time between frames is 1 / 60 seconds (about 0.01667 sec, or 16.67 milliseconds). CFTimeInterval is a type alias for Double, so it can have non-integer values (and needs to, since you work with frame times that are fractions of a second).

More importantly, is the purpose of this to keep the gameplay from slowing down during dips in framerate?

You got the part about framerate dips right, but the effect is backward. You actually want to slow your gameplay down if framerate dips significantly.

If move a spaceship that across the screen by with code like position += velocity * timeSinceLastUpdate, what's going to happen if we drop several frames in a row? The value of timeSinceLastUpdate will be very high, so the ship will jump a large distance instead of moving just a bit. This is especially likely to happen if your app gets suspended and comes back to the foreground sometime later.

This code checks to see if it's been more than a second since the last frame, and if so, elects to continue gameplay as if the game had been running at 60 fps - avoiding the jumping spaceship issue.