/*
* cocos2d for iPhone: http://www.cocos2d-iphone.org
*
* Copyright (c) 2008-2009 Jason Booth
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/*
* Elastic, Back and Bounce actions based on code from:
* http://github.com/NikhilK/silverlightfx/
*
* by http://github.com/NikhilK
*/
#import "CCActionEase.h"
#ifndef M_PI_X_2
#define M_PI_X_2 (float)M_PI * 2.0f
#endif
#pragma mark EaseAction
//
// EaseAction
//
@implementation CCActionEase
+(id) actionWithAction: (CCActionInterval*) action
{
return [[[self alloc] initWithAction: action] autorelease ];
}
-(id) initWithAction: (CCActionInterval*) action
{
NSAssert( action!=nil, @"Ease: arguments must be non-nil");
if( (self=[super initWithDuration: action.duration]) )
other = [action retain];
return self;
}
-(id) copyWithZone: (NSZone*) zone
{
CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease]];
return copy;
}
-(void) dealloc
{
[other release];
[super dealloc];
}
-(void) startWithTarget:(id)aTarget
{
[super startWithTarget:aTarget];
[other startWithTarget:target_];
}
-(void) stop
{
[other stop];
[super stop];
}
-(void) update: (ccTime) t
{
[other update: t];
}
-(CCActionInterval*) reverse
{
return [[self class] actionWithAction: [other reverse]];
}
@end
#pragma mark -
#pragma mark EaseRate
//
// EaseRateAction
//
@implementation CCEaseRateAction
@synthesize rate;
+(id) actionWithAction: (CCActionInterval*) action rate:(float)aRate
{
return [[[self alloc] initWithAction: action rate:aRate] autorelease ];
}
-(id) initWithAction: (CCActionInterval*) action rate:(float)aRate
{
if( (self=[super initWithAction:action ]) )
self.rate = aRate;
return self;
}
-(id) copyWithZone: (NSZone*) zone
{
CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease] rate:rate];
return copy;
}
-(void) dealloc
{
[super dealloc];
}
-(CCActionInterval*) reverse
{
return [[self class] actionWithAction: [other reverse] rate:1/rate];
}
@end
//
// EeseIn
//
@implementation CCEaseIn
-(void) update: (ccTime) t
{
[other update: powf(t,rate)];
}
@end
//
// EaseOut
//
@implementation CCEaseOut
-(void) update: (ccTime) t
{
[other update: powf(t,1/rate)];
}
@end
//
// EaseInOut
//
@implementation CCEaseInOut
-(void) update: (ccTime) t
{
int sign =1;
int r = (int) rate;
if (r % 2 == 0)
sign = -1;
t *= 2;
if (t < 1)
[other update: 0.5f * powf (t, rate)];
else
[other update: sign*0.5f * (powf (t-2, rate) + sign*2)];
}
// InOut and OutIn are symmetrical
-(CCActionInterval*) reverse
{
return [[self class] actionWithAction: [other reverse] rate:rate];
}
@end
#pragma mark -
#pragma mark EaseExponential
//
// EaseExponentialIn
//
@implementation CCEaseExponentialIn
-(void) update: (ccTime) t
{
[other update: (t==0) ? 0 : powf(2, 10 * (t/1 - 1)) - 1 * 0.001f];
}
- (CCActionInterval*) reverse
{
return [CCEaseExponentialOut actionWithAction: [other reverse]];
}
@end
//
// EaseExponentialOut
//
@implementation CCEaseExponentialOut
-(void) update: (ccTime) t
{
[other update: (t==1) ? 1 : (-powf(2, -10 * t/1) + 1)];
}
- (CCActionInterval*) reverse
{
return [CCEaseExponentialIn actionWithAction: [other reverse]];
}
@end
//
// EaseExponentialInOut
//
@implementation CCEaseExponentialInOut
-(void) update: (ccTime) t
{
t /= 0.5f;
if (t < 1)
t = 0.5f * powf(2, 10 * (t - 1));
else
t = 0.5f * (-powf(2, -10 * (t -1) ) + 2);
[other update:t];
}
@end
#pragma mark -
#pragma mark EaseSin actions
//
// EaseSineIn
//
@implementation CCEaseSineIn
-(void) update: (ccTime) t
{
[other update:-1*cosf(t * (float)M_PI_2) +1];
}
- (CCActionInterval*) reverse
{
return [CCEaseSineOut actionWithAction: [other reverse]];
}
@end
//
// EaseSineOut
//
@implementation CCEaseSineOut
-(void) update: (ccTime) t
{
[other update:sinf(t * (float)M_PI_2)];
}
- (CCActionInterval*) reverse
{
return [CCEaseSineIn actionWithAction: [other reverse]];
}
@end
//
// EaseSineInOut
//
@implementation CCEaseSineInOut
-(void) update: (ccTime) t
{
[other update:-0.5f*(cosf( (float)M_PI*t) - 1)];
}
@end
#pragma mark -
#pragma mark EaseElastic actions
//
// EaseElastic
//
@implementation CCEaseElastic
@synthesize period = period_;
+(id) actionWithAction: (CCActionInterval*) action
{
return [[[self alloc] initWithAction:action period:0.3f] autorelease];
}
+(id) actionWithAction: (CCActionInterval*) action period:(float)period
{
return [[[self alloc] initWithAction:action period:period] autorelease];
}
-(id) initWithAction: (CCActionInterval*) action
{
return [self initWithAction:action period:0.3f];
}
-(id) initWithAction: (CCActionInterval*) action period:(float)period
{
if( (self=[super initWithAction:action]) )
period_ = period;
return self;
}
-(id) copyWithZone: (NSZone*) zone
{
CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[other copy] autorelease] period:period_];
return copy;
}
-(CCActionInterval*) reverse
{
NSAssert(NO,@"Override me");
return nil;
}
@end
//
// EaseElasticIn
//
@implementation CCEaseElasticIn
-(void) update: (ccTime) t
{
ccTime newT = 0;
if (t == 0 || t == 1)
newT = t;
else {
float s = period_ / 4;
t = t - 1;
newT = -powf(2, 10 * t) * sinf( (t-s) *M_PI_X_2 / period_);
}
[other update:newT];
}
- (CCActionInterval*) reverse
{
return [CCEaseElasticOut actionWithAction: [other reverse] period:period_];
}
@end
//
// EaseElasticOut
//
@implementation CCEaseElasticOut
-(void) update: (ccTime) t
{
ccTime newT = 0;
if (t == 0 || t == 1) {
newT = t;
} else {
float s = period_ / 4;
newT = powf(2, -10 * t) * sinf( (t-s) *M_PI_X_2 / period_) + 1;
}
[other update:newT];
}
- (CCActionInterval*) reverse
{
return [CCEaseElasticIn actionWithAction: [other reverse] period:period_];
}
@end
//
// EaseElasticInOut
//
@implementation CCEaseElasticInOut
-(void) update: (ccTime) t
{
ccTime newT = 0;
if( t == 0 || t == 1 )
newT = t;
else {
t = t * 2;
if(! period_ )
period_ = 0.3f * 1.5f;
ccTime s = period_ / 4;
t = t -1;
if( t < 0 )
newT = -0.5f * powf(2, 10 * t) * sinf((t - s) * M_PI_X_2 / period_);
else
newT = powf(2, -10 * t) * sinf((t - s) * M_PI_X_2 / period_) * 0.5f + 1;
}
[other update:newT];
}
- (CCActionInterval*) reverse
{
return [CCEaseElasticInOut actionWithAction: [other reverse] period:period_];
}
@end
#pragma mark -
#pragma mark EaseBounce actions
//
// EaseBounce
//
@implementation CCEaseBounce
-(ccTime) bounceTime:(ccTime) t
{
if (t < 1 / 2.75) {
return 7.5625f * t * t;
}
else if (t < 2 / 2.75) {
t -= 1.5f / 2.75f;
return 7.5625f * t * t + 0.75f;
}
else if (t < 2.5 / 2.75) {
t -= 2.25f / 2.75f;
return 7.5625f * t * t + 0.9375f;
}
t -= 2.625f / 2.75f;
return 7.5625f * t * t + 0.984375f;
}
@end
//
// EaseBounceIn
//
@implementation CCEaseBounceIn
-(void) update: (ccTime) t
{
ccTime newT = 1 - [self bounceTime:1-t];
[other update:newT];
}
- (CCActionInterval*) reverse
{
return [CCEaseBounceOut actionWithAction: [other reverse]];
}
@end
@implementation CCEaseBounceOut
-(void) update: (ccTime) t
{
ccTime newT = [self bounceTime:t];
[other update:newT];
}
- (CCActionInterval*) reverse
{
return [CCEaseBounceIn actionWithAction: [other reverse]];
}
@end
@implementation CCEaseBounceInOut
-(void) update: (ccTime) t
{
ccTime newT = 0;
if (t < 0.5) {
t = t * 2;
newT = (1 - [self bounceTime:1-t] ) * 0.5f;
} else
newT = [self bounceTime:t * 2 - 1] * 0.5f + 0.5f;
[other update:newT];
}
@end
#pragma mark -
#pragma mark Ease Back actions
//
// EaseBackIn
//
@implementation CCEaseBackIn
-(void) update: (ccTime) t
{
ccTime overshoot = 1.70158f;
[other update: t * t * ((overshoot + 1) * t - overshoot)];
}
- (CCActionInterval*) reverse
{
return [CCEaseBackOut actionWithAction: [other reverse]];
}
@end
//
// EaseBackOut
//
@implementation CCEaseBackOut
-(void) update: (ccTime) t
{
ccTime overshoot = 1.70158f;
t = t - 1;
[other update: t * t * ((overshoot + 1) * t + overshoot) + 1];
}
- (CCActionInterval*) reverse
{
return [CCEaseBackIn actionWithAction: [other reverse]];
}
@end
//
// EaseBackInOut
//
@implementation CCEaseBackInOut
-(void) update: (ccTime) t
{
ccTime overshoot = 1.70158f * 1.525f;
t = t * 2;
if (t < 1)
[other update: (t * t * ((overshoot + 1) * t - overshoot)) / 2];
else {
t = t - 2;
[other update: (t * t * ((overshoot + 1) * t + overshoot)) / 2 + 1];
}
}
@end