SpriteKit SKAction easing - ios

Well the title gives the question away, how can I apply easing to the SKAction node actions in SpriteKit?
I found that this works:
SKAction *moveAction = [SKAction moveByX:moveX y:moveY duration:0.5];
moveAction.timingMode = SKActionTimingEaseInEaseOut;
[node runAction:moveAction];
However there are only a few easing types available there, namely Linear, EaseIn, EaseOut, EaseInOut.
And those easing values are fixed and cannot be altered. I am looking for something like EleasticInOut. With preferably a bit more control. How can I create that?

I've been using the SKEase framework:
https://github.com/buddingmonkey/SpriteKit-Easing
It's as simple to use as the standard SpriteKit Actions and adds all the usual more complex eases, cubic, bounce, elastic, back etc.
SpriteKitUtils also adds more complex easing types and some handy SpriteKit utilities: https://github.com/raywenderlich/SKTUtils
The other option is to roll your own using the custom action method, and pass it a block of code with your custom easing/animation function:
-(SKAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(SKNode *node, CGFloat elapsedTime))block

Apple introduced spring animations in UIKit a couple years ago, by letting you set a spring damping and initial velocity when performing a UIView animation. Unfortunately they didn't implement that in SpriteKit, so I made my own library that does just that.
It's a set of extensions on SKAction that replicate most factory methods, adding the damping and velocity parameters.
The code is on GitHub, feel free to use it: https://github.com/ataugeron/SpriteKit-Spring

Here is fresh, as spring water, answer goes. In iOS 8 timingFunction was introduced. It allows you to create custom timing curves.
The return SKActionTimingFunction value of the timing function
determines the actual time used to perform the animation.
This way, you can implement your own easing function. Although it has certain limitations: output values must be between 0.0 and 1.0. So for more realistic elastic bouncing I would recommend use SpriteKit-Spring

Related

swift animate spritekit with damping effect

I've been searching on the internet for several days, I didn't find what I'm looking for.
I'm working on an iOS game and I would like to move some sprites using usingSpringWithDamping (to have some rubber effect when moving my sprites).
I have found many solutions for UIViews but nothing for SKSpriteNode.
I would like to move a SKSpriteNode from position 1 to position 2 with a Damping effect.
Can you please give me some ideas?
Thanks.
C.C.
The Sprite Kit Utils from Ray Wenderlich (https://github.com/raywenderlich/SKTUtils) could be what you are looking for. Specifically, using SKTEffects and SKTTimingFunctions will allow you to add easing to your SKActions.
For example SKTTimingFunctionElasticEaseIn, SKTTimingFunctionElasticEaseOut, and SKTTimingFunctionElasticEaseInOut have the rubber effect you are looking for, but you may need to tweak them to your needs. Ray's utils also have other easing functions available; there is a good reference on different easing functions at: http://easings.net
Hope this helps!
UIView animations have support for spring animations, but these are not available in SpriteKit.
There is a third-party library on GitHub which extends SKAction with spring animations: https://github.com/ataugeron/SpriteKit-Spring

Smooth sprite movement in SpriteKit

Hi I'm making a game in Swift with Sprite Kit and I'm wondering if there is a way to have a sprite have smooth movement. Currently I'm using the moveTo method in SKAction and the sprite gets to the target location in a set period of time - meaning that if the location is farther away, the sprite will get there faster. I'm wondering if there is a solid way of getting the sprite to accelerate to a maximum set speed and then slow down when getting to the location. All help is appreciated.
Use the Pythagorean theorem to get the correct duration based on distance in order to get desired speed. See here: https://stackoverflow.com/a/19126642/431271
as far as slowing at the end goes, you can do some quick built in easing methods like this:
var moveAction = SKAction.moveByX(moveX, y:moveY, duration:0.5);
moveAction.timingMode = SKActionTiming.EaseInEaseOut
node.runAction(moveAction)
And if you want other easing methods use libraries such as the one referenced here

How can I slow down a SKSpriteNode that is running SKAction followPath for a slow motion effect using Sprite Kit?

I basically want the action to be running and then in the middle of the action create a slow motion effect and then later bring it out of slow motion. Does anyone have any good feedback of how this might be done? I've thought about creating the action manually and using an update method, but I feel like that might be overkill. I was hoping for a simpler solution.
The other thought I have is to stop the action and then start it again at a slower duration, but I don't think it will stay on the same path and it will probably look weird.
This is the code I'm using to create the action.
CGMutablePathRef cgpath = CGPathCreateMutable();
CGPathMoveToPoint(cgpath,NULL, mysprite.position.x, mysprite.position.y);
CGPathAddCurveToPoint(cgpath, NULL, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y);
[mysprite runAction:[SKAction sequence:#[[SKAction followPath:cgpath asOffset:NO orientToPath:YES duration:3]]]];
CGPathRelease(cgpath);
Each node has a speed property:
A speed modifier applied to all actions executed by a node and its
descendants.
Discussion
The default value is 1.0, which means that all actions run
at their normal speed. If you set a different speed, time appears to
run faster or slower for all actions executed on the node and its
descendants. For example, if you set a speed value of 2.0, actions run
twice as fast.
You could set this to a value smaller than 1 to make the action run slower. You can even animate the speed to gradually slow down:
[mySprite runAction:[SKAction speedTo:0.5 duration:1.0]];

How to apply different easing effects to sprite action?

I use a lot of CCEase* functionalities in Cocos2D described here. iOS 7 Sprite Kit also have SKActionTimingMode. However only simple modes. How can I get CCEaseElasticIn or CCEaseBounceIn like effects using Sprite Kit?
Sprite Kit left easing (or tweening) intentionally limited with the expectation that the developer would take control of the specifics of the motion of the sprites. Basically, what you need to do is make a custom action and apply an easing curve to the parameter before changing the property (rotation, position, scale, etc) of the sprite. Here's an example.
CGFloat initialScale = mySprite.xScale;
SKAction *scaleAction = [SKAction customActionWithDuration:duration actionBlock:^(SKNode *node, CGFloat elapsedTime) {
CGFloat t = elapsedTime/duration;
CGFloat p = t*t;
CGFloat s = initialScale*(1-p) + scale * p;
[node setScale:s];
}];
[mySprite runAction:scaleAction];
The part of this that determines the easing is p = t*t. So, p is a function of t such that :
when t is 0, p is 0
when t is 1, p is 1
That means that you will start at the beginning and end at the end but the shape of the curve in between will determine how you get there. Easing functions can be simple, like the one shown here, which is basically an ease-in, or quite complex such as elastic or bounce. To generate your own, try this : http://www.timotheegroleau.com/Flash/experiments/easing_function_generator.htm
Or take a more detailed look at Robert Penner's equations: http://www.robertpenner.com/easing/
For arbitrary easing, Kardasis' answer says it all.
If you're looking for an easy way to add a bouncing effect to your animations, that is consistent with the way things are done in UIKit, I have something for you.
Apple introduced spring animations in UIKit a couple years ago, by letting you set a spring damping and initial velocity when performing a UIView animation. Unfortunately they didn't implement that in SpriteKit, so I made my own library that does just that.
It's a set of extensions on SKAction that replicate most factory methods, adding the damping and velocity parameters.
The code is on GitHub, feel free to use it: https://github.com/ataugeron/SpriteKit-Spring

Animate by changing CGPoint

In my iOS app, I do a ton of trigonometric calculations based on a given point (specified by CGPoint) and then create some transformation matrices based on those calculations to finally be used in an OpenGL drawing (via GLKit). I'd like to create an animation by changing that fundamental CGPoint over time, but I'm not sure what approach I should use for the animation.
What I'm really looking for is an API that allows me to specify a function to be called on each iteration, much like NSTimer does, but it'd be really cool if I could take advantage ease in/out, etc. The only piece of data that needs to be modified each iteration is my main CGPoint, and the rest of the rendering can be determined from that.
Approaches I've considered, but abandoned:
Core Animation: I'm using OpenGL to draw, so Core Animation doesn't seem to help.
NSTimer: This doesn't give me the flexibility of bezier curves and seems very manual.
Heartbeat based on a given framerate: I only need to re-render when the point changes, and most of the time it is stationary. Doesn't feel like a heartbeat is the right approach.
Does something exist like what I'm describing? Do I have to write it myself? Or am I just misunderstanding the tools provided for me which suggests I should take another look at how I'm drawing my graphics?
I agree with the other poster. Assuming you can use iOS 5, you should use GLKView and GLKViewController. That's set up to call you once per screen refresh (using a CADisplayLink internally .) If you don't want to be iOS 5 only, you can set up a CADisplayLink yourself.
Core Animation isn't useful for OpenGL rendering. However, you can use the design of Core Animation to drive your design. Core Animation (like the rest of Cocoa) is build on top of OpenGL, so you can do everything CA does yourself. It just takes work. (sometimes a LOT of work.)
Core Animation use a motion-based, not a frame based, animation model. Each time it renders the scene, it decides how much motion should be applied based on the elapsed time since the beginning of the animation. If it gets behind in rendering frames, the next frame moves further, so the motion over time is consistent.
As far as ease in/ease out timing, you can do that yourself too. You'd need to read up on animation timing. It uses a non-linear mapping of input time to output time, using bezier curves to change the shape of the curve at the beginning and the end.
You can use GLKView and GLKViewController for your rendering and change the point in the update: method of GLKViewController.

Resources