Value easing class (a.k.a value tween)

I needed the value easing capabilities of intervals without using intervals so I ported this actionscript tutorial to a python class.

import math

class Easing:
    """ A class for easing ratio values in and out.
    Ported from http://www.actionscript.org/resources/articles/138/1/tweening/Page1.html """
   
    @staticmethod
    def Expo(ratio, power):
        if ratio is 0 or ratio is 1:
            return ratio
        if power < 2:
            power = 2
        return math.pow(power, 10 * (ratio-1) )
    @staticmethod
    def Circ(ratio, power):
        ratio = -(math.sqrt(1 - ratio*ratio) - 1 )
        if power > 1:
            return Easing.easeIn(ratio, Tween.Circ, power - 1)
        else:
            return ratio
    @staticmethod
    def Sine(ratio, power):
        ratio = 1 - math.cos(ratio * math.pi/2)
        if power > 1:
            return Easing.easeIn(ratio, Tween.Sine, power - 1)
        else:
            return ratio
    @staticmethod
    def Square(ratio, power):
        return math.pow(ratio, power)
   
    @staticmethod
    def easeIn(ratio, method=math.pow, power=2):
        """
        Eases in a value between 0-1
       
        ratio: a float between 0-1
        method (optional): the method to be used to tween
        """
        if ratio < 0 or ratio > 1:
            raise ValueError, "Invalid ratio: %f. Tweened value should be between 0 and 1" % ratio
        if not callable(method):
            raise ValueError, "Tweening method not callable"
        return method(ratio, power)
    @staticmethod
    def easeOut(ratio, method=math.pow, power=2):
        """ Eases out a value between 0-1 """
        return 1-Easing.easeIn(1-ratio, method, power)
    @staticmethod
    def easeInOut(ratio, method=math.pow, power=2):
        if ratio < 0.5:
            return Easing.easeIn(2*ratio, method, power) / 2
        else:
            return Easing.easeOut(2*(ratio - 0.5), method, power) / 2 + 0.5

To use, just import the Easing class and call as below. This class only tweens values between 0-1, using it otherwise will raise an exception

from EaseUtil import Easing # Replace with however you import this class
Easing.easeOut(0.4)
Easing.easeIn(0.4)
Easing.easeInOut(0.4)
# See http://www.actionscript.org/resources/articles/138/3/tweening/Page3.html
Easing.easeIn(0.4)
Easing.easeIn(0.4, Tween.Sine)
Easing.easeIn(0.4, Tween.Circ)
Easing.easeIn(0.4, Tween.Expo)

oh looks cool. Now that is a good use for intervals.

nice!
i use to program in actionscript in my day to day work
what would i do without tweening classes :slight_smile:
in fact, i think that should be a great thing to include in the panda libs,
a complete tween class with different equations and functions like alphaTo, colorTo, etc…
c

Thanks so much for this code snippet; I’ve been doing a lot of Flash game programming lately and have found Tweens to be incredibly useful for a lot of things. I don’t quite understand how this code of yours works though. Like, how exactly would one use this in their game? When your code runs “Tween.easeIn(0.4)” then what happens?

I’m not sure if the terminology I’m using for the class is correct. This isn’t tweening like how it is used in flash where a tween would automatically move things from one position to another. A use case for this would be in a task that wants to move things. Normally things would move linearly which isn’t very interesting to look at, a value tween allows you to ease it in and out.

from TweenUtil import Tween

import direct.directbase.DirectStart

from pandac.PandaModules import Point3
from direct.gui.OnscreenText import OnscreenText, TextNode

class Demo(object):
    
    def __init__(self):
        base.disableMouse()
        base.camera.setPos(18, 60, 25)
        base.camera.lookAt(18, 0, 0) 
        
        self.model = {}
        
        self.jack("normal", 12)
        self.jack("easeIn", 7)
        self.jack("easeOut", 2)
        self.jack("easeInOut", -3)
        
        self.label("Normal", -0.38)
        self.label("Ease In", -0.22)
        self.label("Ease Out", -0.08)
        self.label("Ease In/Out", 0.05)
        
        self.moveBy = 35
        self.value = 0
        
        taskMgr.add(self.moveTask, "Move Jack")
    
    def label(self, text, ypos):
        OnscreenText(text=text, align=TextNode.ALeft,
            style=1, fg=(1,1,1,1),
            pos=(-1.2, ypos), scale = .07)
    
    def jack(self, name, position):
        self.model[name] = loader.loadModel('jack')
        self.model[name].reparentTo(render)
        self.model[name].setY(position)
    
    def moveJack(self, name, value):
        self.model[name].setX(self.moveBy * value)
    
    def moveTask(self, task):
        delta = globalClock.getDt()
        self.value += delta*0.3
        if self.value >= 1.5:
            self.value = 0
        if self.value >= 1:
            return task.cont
        
        self.moveJack('normal', self.value)
        self.moveJack('easeIn', Tween.easeIn(self.value) )
        self.moveJack('easeOut', Tween.easeOut(self.value) )
        self.moveJack('easeInOut', Tween.easeInOut(self.value) )
        
        return task.cont

Demo()
run()

Tween Class code edited to use static method as suggested by pro-rsoft

oh I see what you’re getting at, this class doesn’t actually move anything, it just returns the numbers for what movements to make.

hm yeah that is incorrect terminology. A “tween” in actionscript actually moves things around; you just set the tween and it goes without needing any more attention from you. What you have done is just the easing function end of things (so like the term would just be “easing functions”.)

That tutorial you linked to is pretty confusing about the terminology though, plus the use of “tween” in Actionscript is pretty confusing anyway. Like, when I first encountered tweens I got confused because to animators (and I’ve been an animator longer than a programmer) the term means something completely different.


Incidentally, after getting used to using tweens in Actionscript these past couple of months I’ve been thinking of writing a library for tweens in whatever game engine I settle on. So like TweenLite ported to Python.

Yeah, I think the proper terminology I’m looking for is value easing, according to a few other libraries.

Panda already has something like actionscript tweening, Intervals. It’s pretty handy if a bit unpythonic, even though the Intervals module looks like its mostly implemented in Python. Would be nice if we could take the syntax of cocos2d actions which implements tweens/intervals pretty beautifully.

Interesting, I’ll have to look into Intervals.