Are there any obvious performance issues of mass-using SKActions? - sprite-kit

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.

Related

What's the difference between these two SpriteKit functions?

I don't know what's the difference between these two functions.
First:
coin.run(SKAction.moveTo(y: -146.115, duration: 0))
Second:
coin.position.y = -146.115
The SKAction will not be processed until the next frame-- directly after update. If you call .run after didEvaluateActions, your position will not be updated, and you may encounter bugs due to that.
The second line of code will take place immediately, regardless of your position in the SK loop.
Example, if you are using physics, and call .run(.move( on something in didBegin(contact, and then are expecting that sprite to have moved already by didEnd(contact), then you will have problems. In that situation, you want to manually adjust .position instead of using an action.
Secondly, the .run command is also less performant, because it requires the initialization of an SKAction object, which is somewhere between 20-30% slower than just adjusting the position manually.
Granted, that amount of difference doesn't add up to much, but in complicated scenes it could be the difference between getting everything done in 16ms (60fps) or not.
Third, as others have mentioned, there is the forDuration parameter, which allows you to animate the movement over a period of time.. say, 2 seconds, or however long you want.
SKAction.moveTo() has a duration parameter, which is there, because it is an animated version of changing a node's position over the specified time interval. On the other hand, changing the position of a node doesn't animate the movement.
In first line you are using your coin class object and accessing function run through it's object.
coin.run(SKAction.moveTo(y: -146.115, duration: 0))
In second line coin class object accessing it's property position.y and assign it float value.
coin.position.y = -146.115
Hope u got it!!!

pyglet: synchronise event with frame drawing

The default method of animation is to have an independent timer set to execute at the same frequency as the frame rate. This is not what I'm looking for because it provides no guarantee the event is actually executed at the right time. The lack of synchronisation with the actual frame drawing leads to occasional animation jitters. The obvious solution is to have a function run once for every frame, but I can't find a way to do that. on_draw() only runs when I press a key on the keyboard. Can I get on_draw() to run once per frame, synchronised with the frame drawing?
The way to do this is to use pyglet.clock.schedule(update), making sure vsync is enabled (which it is by default). This ensures on_draw() is run once per frame. The update function passed to pyglet.clock.schedule() doesn't even need to do anything. It can just be blank. on_draw() is now being executed once per frame draw, so there's no point in having separate functions both of which are being executed once per frame drawing. It would have been a lot nicer if there were just an option somewhere in the Window class saying on_draw() should be drawn once per second, but at least it's working now.
I'm still getting bad tearing, but that's a bug in pyglet on my platform or system. There wasn't supposed to be any tearing.

Positioning particles and life span of particle system in AndEngine GLES2

I am using particle system in my game, in andEngine GLES2, to produce a glittering effect.
I could not find a way to position particles after these are attached to the scene(run time).
Secondly i want to know if there is a way to make a check on the particles movement like listener in animations because I want to stop particles to emit after they expire first time.
Any help in this regard will be much appreciated.
First positioning particle system, There is a method setCenter that you can use in following manner.
particleEmitter.setCenter(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
Also you can see basic andengine example to clear your concept.
Second stop particle system, As per my consideration there is no listener for particle system. So to satisfy you need you have to think differently. You have to use TimerHandler to satisfy your need. When first time onTimer method of TimerHandler gets executed at that time you have to detach particle system or whatever you want to do.
if you want to move particles in different directions then add
new VelocityParticleInitializer<Sprite>(30,-42, -40, 40)
to the partial system.
Example:
systemBallParticleSystem.addParticleInitializer(new VelocityParticleInitializer<Sprite>(30,-42, -40, 40));
Second point
when partical effect started register a delay modifier and detach your system after that time
Example:
registerEntityModifier(new DelayModifier(pDuration, pEntityModifierListener));
in this pEntityModifierListener you can detach your partical system

Box2D sleep time

I was just wondering if there was a way to change the amount of time until the sleep state is activated for a body in box2d (cocos2d).
I currently use the sleep state as a way to end a game so it is preferable if I can speed up the time it takes to achieve the sleep state.
Thanks
A physics engine doesn't put objects to sleep based on time. It only puts bodies to sleep which are at rest (idle). Typically the physics engine defines rules when it's safe to put a body to sleep, normally that's when the body has stopped moving at all, when there are no other moving bodies touching it, and when both conditions are met for a certain period of time.
In Box2D you can't modify this behavior unless you modify the Box2D source code (not recommended). In Chipmunk you can at least set the threshold for how long a body must be idle before it is put to sleep. Changing this value can sometimes lead to the effect that slow moving objects will suddenly fall to sleep.
To implement the behavior you want, you should define your own set of rules. Iterate over all bodies that may be moving slowly at the end of the game. Get the values for angular rotation and velocity, and check if they have fallen below a certain threshold that feels good for your game. Then end the game, or you can also manually put the object to sleep with body->SetAwake(false).

How can I chain animations in iPhone-OS?

I want to do some sophisticated animations. But I only know how to animate a block of changes. Is there a way to chain animations, so that I could for example make changes A -> B -> C -> D -> E -> F (and so on), while the core-animation waits until each animation has finished and then proceeds to the next one?
In particular, I want to do this: I have an UIImageView that shows a cube.
Phase 1) Cube is flat on the floor
Phase 2) Cube rotates slightly to left, while the rotation origin is in bottom left.
Phase 3) Cube rotates slightly to right, while the rotation origin is in the bottom right.
These phases repeat 10 times, and stop at Phase 1). Also, the wiggling becomes lesser with time.
I know how to animate ONE change in a block, but how could I do such a repeating-thing with some sophisticated code in between? It's not the same thing over time. It changes, since the wiggling becomes lesser and lesser until it stops.
Assuming you're using UIView animation...
You can provide an animation 'stopped' method that gets called when an animation is actually finished (check out setAnimationDelegate). So you can have an array of animations queued up and ready to go. Set the delegate then kick off the first animation. When it ends it calls the setAnimationDidStopSelector method (making sure to check the finished flag to make sure it's really done and not just paused). You can also pass along an animation context which could be the index in your queue of animations. It can also be a data structure that contains counters so you can adjust the animation values through each cycle.
So then it's just a matter of waiting for one to be done then kicking off the next one taken off the queue.
The same method applies if you're using other types of animation. You just need to set up your data structures so it knows what to do after each one ends.
You'll need to setup an animation delegate inside of your animation blocks. See setAnimationDelegate in the UIView documentation for all the details.
In essence your delegate can be notified whenever an animation ends. Use the context parameter to determine what step in your animation is currently ending (Phase 1, Phase 2, etc)
This strategy should allow you to chain together as many animation blocks as you want.
I think the answer to your question is that you need to get more specification on what you want to do. You clearly have an idea in mind, but more specification of details will help you answer your own question.