I am using about 20 UIImageViews of small airplane images (50x50 pixels) doing simple animation on the iPhone screen. The animation is done by shifting the UIImageView center property at timer interval.
[NSTimer scheduledTimerWithTimeInterval:0.01
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES]
What is the best practice: create one NSTimer and loop the 20 UIImageViews to set the center property when timer fired? Or should I just create one NSTimer per UIImageView object? Is NSTimer resource expensive?
I don't think it's that resource intensive, but common sense would seem to dictate that using 1 timer is probably better than 20.
Looks like your timer is set to fire 100 times per second, which seems a bit excessive. Do you animate each sprite at every timer firing? Might want to try firing 20-30 times per second instead (or maybe even less).
You might want to look into the built in view animation functions as well. Seems like they would probably work very well for what you are doing.
you could try both and use the built in profiling tools that ship with Xcode to gauge resource usage.
Timers are actually PRETTY EXPENSIVE, energy-wise.
Every nanosecond that the OS (or apps running on it) are not doing something, the CPU is sleeping in one of several low-power state modes. Waking the system from an idle state incurs an energy cost when the CPU and other systems are awakened from their low-power, idle states. If a timer causes the system to wake, it incurs that cost. The more frequently your timer fires, the higher the energy cost. On mobile devices, it can affect materially battery life.
In that sense, it is much more efficient to wake the system once, do all your work, then let it sleep again for as many nanosecs as possible. Going back to your example, if you profile this, it should be more efficient to use 1 timer rather than 20 timers, each firing 100 times / sec.
Later OS versions allow you to specify a tolerance (in %). This allows the system to group timers together and execute them at the same wake event, to save power. It seems what you are doing is not time critical (in a real-time execution kind of sense), so permitting a tolerance (e.g. 10%) should help.
Example: [myTimer setTolerace:0.3];
More about timer tolerance here: https://developer.apple.com/documentation/foundation/nstimer
Instead of attempting to have a Timer synchronized to the screen redraw (i.e. firing 60x a second), a better solution would be to use CADisplayLink, which fires as on screen redraw and is built for this purpose.
let displayLink = CADisplayLink(target: self, selector: #selector(displayLinkFired))
displayLink.add(to: .main, forMode: .default) // attach to the main run loop
#objc func displayLinkFired() {
// update image view's here
}
Related
I have a game where I use a lot of SKActions to deliver the desired game logic.
For example, instead of setting the zRotation of a sprite to a value, I would use runAction(SKAction.rotateTo(/* angle here */, duration: 0.0) instead.
I make calls like this in update, and in touchesMoved. Thus this could mean hundreds of these calls, sometimes nested with groups of other actions.
Am I incurring significant overhead relative to directly setting the zRotation property?
Never use SKActions for real-time motion. Instead you should either set the zRotation directly or set the necessary angular velocity each frame. In your case the update method and touchesMoved method are both bad to use for SKActions because they can run 30-60 times a second.
SKActions do generate significant overhead. Here is a quote from Apple's documentation:
When You Shouldn’t Use Actions
Although actions are efficient, there
is a cost to creating and executing them. If you are making changes to
a node’s properties in every frame of animation and those changes need
to be recomputed in each frame, you are better off making the changes
to the node directly and not using actions to do so. For more
information on where you might do this in your game, see Advanced
Scene Processing.
Source
You can see an example of using real-time motion instead of SKActions in my answer here
You should not call a SKAction in the update method as it is called 60 times a second. Instead, use a event based trigger which in turn calls the SKAction. The touchesMoved is a good example of that. You can also use a completion method block to signal for a new SKAction upon completion of the current action.
SO I have a label labelscore and it increase of 1000 every time there is a collision between two images. I would like to see labelscore increase of 1000 like an animated score, a running score. How can I do this?
You can use an NSTimer to call a routine every 16.7 to 50 milliseconds. In the routine increment some value and update it to the label. Rinse and repeat until this value is equal to the score. This is the basic technique of an animation game loop.
You have the option to use a repeating timer and invalidate it when you're done with it. Or setting single-shot timers within each update routine for the next iteration. You could also use CADisplayLink as an alternative to NSTimer, which may provide smoother animation under some conditions.
Is it possible to play an audio file from the user's ipod library and have a callback occur whenever the player reaches a certain time point ? I need it to be very accurate, so simply using methods like currentPlaybackTime might not be enough because float equality is inaccurate. I could use the A - B < Epsilon float check, but is there a better, more accurate way of achieving this?
If you can target iOS 4.0 or hight, try using AVPlayer. Then you will be able to use
- (id)addBoundaryTimeObserverForTimes:(NSArray *)times queue:(dispatch_queue_t)queue usingBlock:(void (^)(void))block
which takes an array of NSValues for CMTimes and will run the contents of the block each time one of the boundary times is hit. (Beware of some behavior like, if you pause the audio file inside of the block, the callback will fire again when you unpause it).
Since CMTime is not a float, I think this will be more accurate than checking for the currentTime repeatedly.
Hi all can anyone help me out with the solution to this problem...
I have a project where I have NSTimer fire about 20 times a sec and thus using only one image(loaded programatically)produces the same image on the iPhone screen about twenty times in a second and these images fall from the top of the screen to the bottom where they are removed(more or less simulating rain fall or rain droplets).
My problem is that looking at the animation, I noticed that there are very small delays and which looks like a break, pause or small vibrations. Thus the flow isn't smooth.
Can anyone help me with the solution please.
Thanks in advance
You can check the CADisplayLink class.
Just because you ask for a timer in the UI run loop to go off at a certain rate, doesn't mean you will get called at exactly that rate or at evenly spaced intervals. You should check the time and the elapsed time "dt" inside each timer callback, and change your animation position, y + dy * dt, etc., accordingly.
Timer's arn't designed to be used for animation.
The best thing to do, is to have a thread running in an infinite loop, where you check if it's time to animate again, or just always animate (giving you a higher frame rate), but using the time elapsed as a reference for the state you are drawing.
You really shouldn't be using a timer for this. Instead you should be using the built in UIView animation methods:
animateWithDuration:animations:
animateWithDuration:animations:completion:
animateWithDuration:delay:options:animations:completion:
What are the best strategies for syncing music to object movement? The app I envision would have an underlying soundtrack with characters animating in time to the music. What I'm after is a strategy for having the soundtrack periodic send a message to an object, objects, triggering it to commence it's scripted movement.
Thanks,
Doug
FMOD Ex should allow this sort of thing. It's not built-in, but it's relatively cheap.
The point is writing the object movement code so that it can use external clock signal. You can for example write the movement update method so that it takes a time delta:
- (void) updateMovementBy: (double) seconds {…}
In each loop you’ll poll the soundtrack player for current playback time, compute time delta from the last iteration and update the model. But of course a lot depends on what exactly you want to do in response to the music.