6

I have the following custom SKAction working but as an EaseIn instead EaseOut. I want it to EaseOut! I have failed miserably to correct it using various easing equations found around the web.

    let duration = 2.0
    let initialX = cameraNode.position.x
    let customEaseOut = SKAction.customActionWithDuration(duration, actionBlock: {node, elapsedTime in

        let t = Double(elapsedTime)/duration
        let b = Double(initialX)
        let c = Double(targetPoint.x)
        let p = t*t*t*t*t

        let l = b*(1-p) + c*p

        node.position.x = CGFloat(l)
    })

    cameraNode.runAction(customEaseOut)

Any help would be much appreciate.

Thanks

shahidaltaf
  • 585
  • 1
  • 5
  • 17

2 Answers2

12

You don't need to calculate it.

SKAction just have a property called timingMode:

// fall is an SKAction
fall.timingMode = .easeInEaseOut

You can choose from:

  • linear (default)
  • easeIn
  • easeOut
  • easeInEaseOut

Check details from API docs and also here.

If you need to change the Apple presets you can use: timingFunction

fall.timingFunction = { time -> Float in
    return time
}

To build a custom function according to the source:

/**
 A custom timing function for SKActions. Input time will be linear 0.0-1.0
 over the duration of the action. Return values must be 0.0-1.0 and increasing
 and the function must return 1.0 when the input time reaches 1.0.
 */
public typealias SKActionTimingFunction = (Float) -> Float

So with these informations you can write:

func CubicEaseOut(_ t:Float)->Float
{
   let f:Float = (t - 1);
   return f * f * f + 1;
}
fall.timingFunction = CubicEaseOut
Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
  • In some ways you're right. But it looks like the OP is after a much stronger curve than the presets from Apple. – Confused Oct 16 '16 at 14:08
  • 1
    Hi Confused, thank you for you comment. So, why don't try to use it : timingFunction?(https://developer.apple.com/reference/spritekit/skactiontimingfunction?) an example: http://stackoverflow.com/a/28521379/1894067 – Alessandro Ornano Oct 16 '16 at 14:55
  • because I'm not the OP ;). More seriously, I'm busily adopting some of these, for what I'm doing: https://github.com/craiggrummitt/SpriteKitEasingSwift and coming to terms with the "powers" of SKActions. I don't fully understand their range of customisation options yet. I tend to think much more in terms of physics and keyframes. Never really liked Actions and their way of thinking. but starting to come around on their usefulness, a little. – Confused Oct 16 '16 at 15:00
  • I can see one reason to not use the timingFunction: it's (seemingly) changing the relative time of events through the range of a duration rather than the position during time steps. For most visual thinkers, this playing with time stretching is harder to conceive of and incorporate into a mental model than position curves changing over equal time steps. The graphs in Epsilon's answer come naturally to this kind of thinking. I think. – Confused Oct 16 '16 at 15:06
  • But I can sort of see that playing with time could get the same results. Just harder to visualise which changes what, when and how. And why. – Confused Oct 16 '16 at 15:07
  • Sorry for the spamminess, but the more I think about the SKActionTimingFunction, the more I see it might be quite powerful. And elegant. The maths of using it are a little beyond me. I need something visual to draw out the desired curves. – Confused Oct 16 '16 at 15:09
  • 1
    You're welcome, I've added also some examples to my answer. You can easily build these function with few lines, only changing time, your project in link follow the same rules, good luck man : https://github.com/craiggrummitt/SpriteKitEasingSwift/blob/master/Pod/Classes/easing.swift – Alessandro Ornano Oct 16 '16 at 15:21
  • Argh, that additional code is awesome. I was just getting some stuff together to ask you about how to do this. Here's a site to see how the curves make motion very different: http://cubic-bezier.com/#0,1,0,1 – Confused Oct 16 '16 at 15:26
  • This stops working at four (f * f * f * f + 1).. it's still not quite as tight as I'd like. Is there a way to get a tighter/stronger curve? – Confused Oct 16 '16 at 21:47
  • How do I apply this to something like the width of a line of an SKShapeNode? – Confused Oct 27 '16 at 13:57
  • And in this line `func CubicEaseOut(_ t:Float)->Float` what is t, and what are its possible range of values and their impact? – Confused Oct 27 '16 at 14:00
  • A timingMode define the behaviour of a SKAction. You speak about an object (SKShapeNode ) and ask to have the same behaviour about a line. If I' ve understand this is not possible. – Alessandro Ornano Oct 27 '16 at 14:01
  • In this answer, it seems possible to use "blocks" or "closures" or whatever they are called to make changes to SKShapeNode properties, but I don't understand how to put it all together with custom actions. http://stackoverflow.com/questions/40072071/resize-sprite-without-shrinking-contents/40073252#40073252 – Confused Oct 27 '16 at 14:03
  • And this comes close, it provides a float that changes over time, but I can't see how to use it: http://stackoverflow.com/questions/40284692/skease-action-how-to-use-float-changing-action-setter-block – Confused Oct 27 '16 at 14:04
  • Oh yes, but there is always an action involved , in this case is "resize", and they don't speak about spriteNode but shapeNode. Basically, timingMode define the action behavior during time, then if you want to build a shape or resize a sprite you could do it but timingMode change only the SKAction, it's not applicable directly to an object. – Alessandro Ornano Oct 27 '16 at 14:21
  • DOH! How do I use the CGFloat animation that comes from the SKEase facilities in the question here, in a way it impacts a property of an SKShapeNode? http://stackoverflow.com/questions/40284692/skease-action-how-to-use-float-changing-action-setter-block – Confused Oct 27 '16 at 14:29
  • If you want to "give a timingMode animation" to a SKShapeNode construction, you could start from the shape foundation: point and line. For example if I want to build a rectangle I can draw lines to construct sides inside a block defined by a customAction, After, I can change timingMode about this SKAction. You should this because to the init methods about SKSpriteNode or SKShapeNode you haven't timingMode definition to control the build animation. – Alessandro Ornano Oct 27 '16 at 14:36
  • Not to the construction, I want to provide a very strong easing curve to the animation of changes to the lineWidth of a ShapeNode – Confused Oct 27 '16 at 14:43
  • If you have a SKAction that define this change , yes you can do it. – Alessandro Ornano Oct 27 '16 at 14:51
  • If a method dont exist, you should re-create it starting from dots or use methods that give you the final result :-) – Alessandro Ornano Oct 27 '16 at 15:02
2

We can modify the following code to allow the custom action to ease-out instead of ease-in

let t = Double(elapsedTime)/duration
...
let p = t*t*t*t*t

To get a better understanding of p, it is helpful to plot it as a function of t

enter image description here

Clearly, the function eases in over time. Changing the definition of t to

let t = 1 - Double(elapsedTime)/duration

and plotting p gives

enter image description here

The action now eases out, but it starts at 1 and ends at 0. To resolve this, change the definition of p to

let p = 1-t*t*t*t*t

enter image description here

Epsilon
  • 1,016
  • 1
  • 6
  • 15