summary refs log tree commit diff stats
path: root/libs/cocos2d/CCActionInterval.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/CCActionInterval.m')
-rwxr-xr-xlibs/cocos2d/CCActionInterval.m1355
1 files changed, 1355 insertions, 0 deletions
diff --git a/libs/cocos2d/CCActionInterval.m b/libs/cocos2d/CCActionInterval.m new file mode 100755 index 0000000..17bef40 --- /dev/null +++ b/libs/cocos2d/CCActionInterval.m
@@ -0,0 +1,1355 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2011 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28
29#import "CCActionInterval.h"
30#import "CCSprite.h"
31#import "CCSpriteFrame.h"
32#import "CCAnimation.h"
33#import "CCNode.h"
34#import "Support/CGPointExtension.h"
35
36//
37// IntervalAction
38//
39#pragma mark -
40#pragma mark IntervalAction
41@implementation CCActionInterval
42
43@synthesize elapsed = elapsed_;
44
45-(id) init
46{
47 NSAssert(NO, @"IntervalActionInit: Init not supported. Use InitWithDuration");
48 [self release];
49 return nil;
50}
51
52+(id) actionWithDuration: (ccTime) d
53{
54 return [[[self alloc] initWithDuration:d ] autorelease];
55}
56
57-(id) initWithDuration: (ccTime) d
58{
59 if( (self=[super init]) ) {
60 duration_ = d;
61
62 // prevent division by 0
63 // This comparison could be in step:, but it might decrease the performance
64 // by 3% in heavy based action games.
65 if( duration_ == 0 )
66 duration_ = FLT_EPSILON;
67 elapsed_ = 0;
68 firstTick_ = YES;
69 }
70 return self;
71}
72
73-(id) copyWithZone: (NSZone*) zone
74{
75 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] ];
76 return copy;
77}
78
79- (BOOL) isDone
80{
81 return (elapsed_ >= duration_);
82}
83
84-(void) step: (ccTime) dt
85{
86 if( firstTick_ ) {
87 firstTick_ = NO;
88 elapsed_ = 0;
89 } else
90 elapsed_ += dt;
91
92 [self update: MIN(1, elapsed_/duration_)];
93}
94
95-(void) startWithTarget:(id)aTarget
96{
97 [super startWithTarget:aTarget];
98 elapsed_ = 0.0f;
99 firstTick_ = YES;
100}
101
102- (CCActionInterval*) reverse
103{
104 NSAssert(NO, @"CCIntervalAction: reverse not implemented.");
105 return nil;
106}
107@end
108
109//
110// Sequence
111//
112#pragma mark -
113#pragma mark Sequence
114@implementation CCSequence
115+(id) actions: (CCFiniteTimeAction*) action1, ...
116{
117 va_list params;
118 va_start(params,action1);
119
120 CCFiniteTimeAction *now;
121 CCFiniteTimeAction *prev = action1;
122
123 while( action1 ) {
124 now = va_arg(params,CCFiniteTimeAction*);
125 if ( now )
126 prev = [self actionOne: prev two: now];
127 else
128 break;
129 }
130 va_end(params);
131 return prev;
132}
133
134+(id) actionsWithArray: (NSArray*) actions
135{
136 CCFiniteTimeAction *prev = [actions objectAtIndex:0];
137
138 for (NSUInteger i = 1; i < [actions count]; i++)
139 prev = [self actionOne:prev two:[actions objectAtIndex:i]];
140
141 return prev;
142}
143
144+(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
145{
146 return [[[self alloc] initOne:one two:two ] autorelease];
147}
148
149-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
150{
151 NSAssert( one!=nil && two!=nil, @"Sequence: arguments must be non-nil");
152 NSAssert( one!=actions_[0] && one!=actions_[1], @"Sequence: re-init using the same parameters is not supported");
153 NSAssert( two!=actions_[1] && two!=actions_[0], @"Sequence: re-init using the same parameters is not supported");
154
155 ccTime d = [one duration] + [two duration];
156
157 if( (self=[super initWithDuration: d]) ) {
158
159 // XXX: Supports re-init without leaking. Fails if one==one_ || two==two_
160 [actions_[0] release];
161 [actions_[1] release];
162
163 actions_[0] = [one retain];
164 actions_[1] = [two retain];
165 }
166
167 return self;
168}
169
170-(id) copyWithZone: (NSZone*) zone
171{
172 CCAction *copy = [[[self class] allocWithZone:zone] initOne:[[actions_[0] copy] autorelease] two:[[actions_[1] copy] autorelease] ];
173 return copy;
174}
175
176-(void) dealloc
177{
178 [actions_[0] release];
179 [actions_[1] release];
180 [super dealloc];
181}
182
183-(void) startWithTarget:(id)aTarget
184{
185 [super startWithTarget:aTarget];
186 split_ = [actions_[0] duration] / duration_;
187 last_ = -1;
188}
189
190-(void) stop
191{
192 [actions_[0] stop];
193 [actions_[1] stop];
194 [super stop];
195}
196
197-(void) update: (ccTime) t
198{
199 int found = 0;
200 ccTime new_t = 0.0f;
201
202 if( t >= split_ ) {
203 found = 1;
204 if ( split_ == 1 )
205 new_t = 1;
206 else
207 new_t = (t-split_) / (1 - split_ );
208 } else {
209 found = 0;
210 if( split_ != 0 )
211 new_t = t / split_;
212 else
213 new_t = 1;
214 }
215
216 if (last_ == -1 && found==1) {
217 [actions_[0] startWithTarget:target_];
218 [actions_[0] update:1.0f];
219 [actions_[0] stop];
220 }
221
222 if (last_ != found ) {
223 if( last_ != -1 ) {
224 [actions_[last_] update: 1.0f];
225 [actions_[last_] stop];
226 }
227 [actions_[found] startWithTarget:target_];
228 }
229 [actions_[found] update: new_t];
230 last_ = found;
231}
232
233- (CCActionInterval *) reverse
234{
235 return [[self class] actionOne: [actions_[1] reverse] two: [actions_[0] reverse ] ];
236}
237@end
238
239//
240// Repeat
241//
242#pragma mark -
243#pragma mark CCRepeat
244@implementation CCRepeat
245@synthesize innerAction=innerAction_;
246
247+(id) actionWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times
248{
249 return [[[self alloc] initWithAction:action times:times] autorelease];
250}
251
252-(id) initWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times
253{
254 ccTime d = [action duration] * times;
255
256 if( (self=[super initWithDuration: d ]) ) {
257 times_ = times;
258 self.innerAction = action;
259
260 total_ = 0;
261 }
262 return self;
263}
264
265-(id) copyWithZone: (NSZone*) zone
266{
267 CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[innerAction_ copy] autorelease] times:times_];
268 return copy;
269}
270
271-(void) dealloc
272{
273 [innerAction_ release];
274 [super dealloc];
275}
276
277-(void) startWithTarget:(id)aTarget
278{
279 total_ = 0;
280 [super startWithTarget:aTarget];
281 [innerAction_ startWithTarget:aTarget];
282}
283
284-(void) stop
285{
286 [innerAction_ stop];
287 [super stop];
288}
289
290
291// issue #80. Instead of hooking step:, hook update: since it can be called by any
292// container action like Repeat, Sequence, AccelDeccel, etc..
293-(void) update:(ccTime) dt
294{
295 ccTime t = dt * times_;
296 if( t > total_+1 ) {
297 [innerAction_ update:1.0f];
298 total_++;
299 [innerAction_ stop];
300 [innerAction_ startWithTarget:target_];
301
302 // repeat is over ?
303 if( total_== times_ )
304 // so, set it in the original position
305 [innerAction_ update:0];
306 else {
307 // no ? start next repeat with the right update
308 // to prevent jerk (issue #390)
309 [innerAction_ update: t-total_];
310 }
311
312 } else {
313
314 float r = fmodf(t, 1.0f);
315
316 // fix last repeat position
317 // else it could be 0.
318 if( dt== 1.0f) {
319 r = 1.0f;
320 total_++; // this is the added line
321 }
322 [innerAction_ update: MIN(r,1)];
323 }
324}
325
326-(BOOL) isDone
327{
328 return ( total_ == times_ );
329}
330
331- (CCActionInterval *) reverse
332{
333 return [[self class] actionWithAction:[innerAction_ reverse] times:times_];
334}
335@end
336
337//
338// Spawn
339//
340#pragma mark -
341#pragma mark Spawn
342
343@implementation CCSpawn
344+(id) actions: (CCFiniteTimeAction*) action1, ...
345{
346 va_list params;
347 va_start(params,action1);
348
349 CCFiniteTimeAction *now;
350 CCFiniteTimeAction *prev = action1;
351
352 while( action1 ) {
353 now = va_arg(params,CCFiniteTimeAction*);
354 if ( now )
355 prev = [self actionOne: prev two: now];
356 else
357 break;
358 }
359 va_end(params);
360 return prev;
361}
362
363+(id) actionsWithArray: (NSArray*) actions
364{
365 CCFiniteTimeAction *prev = [actions objectAtIndex:0];
366
367 for (NSUInteger i = 1; i < [actions count]; i++)
368 prev = [self actionOne:prev two:[actions objectAtIndex:i]];
369
370 return prev;
371}
372
373+(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
374{
375 return [[[self alloc] initOne:one two:two ] autorelease];
376}
377
378-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two
379{
380 NSAssert( one!=nil && two!=nil, @"Spawn: arguments must be non-nil");
381 NSAssert( one!=one_ && one!=two_, @"Spawn: reinit using same parameters is not supported");
382 NSAssert( two!=two_ && two!=one_, @"Spawn: reinit using same parameters is not supported");
383
384 ccTime d1 = [one duration];
385 ccTime d2 = [two duration];
386
387 if( (self=[super initWithDuration: MAX(d1,d2)] ) ) {
388
389 // XXX: Supports re-init without leaking. Fails if one==one_ || two==two_
390 [one_ release];
391 [two_ release];
392
393 one_ = one;
394 two_ = two;
395
396 if( d1 > d2 )
397 two_ = [CCSequence actionOne:two two:[CCDelayTime actionWithDuration: (d1-d2)] ];
398 else if( d1 < d2)
399 one_ = [CCSequence actionOne:one two: [CCDelayTime actionWithDuration: (d2-d1)] ];
400
401 [one_ retain];
402 [two_ retain];
403 }
404 return self;
405}
406
407-(id) copyWithZone: (NSZone*) zone
408{
409 CCAction *copy = [[[self class] allocWithZone: zone] initOne: [[one_ copy] autorelease] two: [[two_ copy] autorelease] ];
410 return copy;
411}
412
413-(void) dealloc
414{
415 [one_ release];
416 [two_ release];
417 [super dealloc];
418}
419
420-(void) startWithTarget:(id)aTarget
421{
422 [super startWithTarget:aTarget];
423 [one_ startWithTarget:target_];
424 [two_ startWithTarget:target_];
425}
426
427-(void) stop
428{
429 [one_ stop];
430 [two_ stop];
431 [super stop];
432}
433
434-(void) update: (ccTime) t
435{
436 [one_ update:t];
437 [two_ update:t];
438}
439
440- (CCActionInterval *) reverse
441{
442 return [[self class] actionOne: [one_ reverse] two: [two_ reverse ] ];
443}
444@end
445
446//
447// RotateTo
448//
449#pragma mark -
450#pragma mark RotateTo
451
452@implementation CCRotateTo
453+(id) actionWithDuration: (ccTime) t angle:(float) a
454{
455 return [[[self alloc] initWithDuration:t angle:a ] autorelease];
456}
457
458-(id) initWithDuration: (ccTime) t angle:(float) a
459{
460 if( (self=[super initWithDuration: t]) )
461 dstAngle_ = a;
462
463 return self;
464}
465
466-(id) copyWithZone: (NSZone*) zone
467{
468 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] angle:dstAngle_];
469 return copy;
470}
471
472-(void) startWithTarget:(CCNode *)aTarget
473{
474 [super startWithTarget:aTarget];
475
476 startAngle_ = [target_ rotation];
477 if (startAngle_ > 0)
478 startAngle_ = fmodf(startAngle_, 360.0f);
479 else
480 startAngle_ = fmodf(startAngle_, -360.0f);
481
482 diffAngle_ =dstAngle_ - startAngle_;
483 if (diffAngle_ > 180)
484 diffAngle_ -= 360;
485 if (diffAngle_ < -180)
486 diffAngle_ += 360;
487}
488-(void) update: (ccTime) t
489{
490 [target_ setRotation: startAngle_ + diffAngle_ * t];
491}
492@end
493
494
495//
496// RotateBy
497//
498#pragma mark -
499#pragma mark RotateBy
500
501@implementation CCRotateBy
502+(id) actionWithDuration: (ccTime) t angle:(float) a
503{
504 return [[[self alloc] initWithDuration:t angle:a ] autorelease];
505}
506
507-(id) initWithDuration: (ccTime) t angle:(float) a
508{
509 if( (self=[super initWithDuration: t]) )
510 angle_ = a;
511
512 return self;
513}
514
515-(id) copyWithZone: (NSZone*) zone
516{
517 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] angle: angle_];
518 return copy;
519}
520
521-(void) startWithTarget:(id)aTarget
522{
523 [super startWithTarget:aTarget];
524 startAngle_ = [target_ rotation];
525}
526
527-(void) update: (ccTime) t
528{
529 // XXX: shall I add % 360
530 [target_ setRotation: (startAngle_ +angle_ * t )];
531}
532
533-(CCActionInterval*) reverse
534{
535 return [[self class] actionWithDuration:duration_ angle:-angle_];
536}
537
538@end
539
540//
541// MoveTo
542//
543#pragma mark -
544#pragma mark MoveTo
545
546@implementation CCMoveTo
547+(id) actionWithDuration: (ccTime) t position: (CGPoint) p
548{
549 return [[[self alloc] initWithDuration:t position:p ] autorelease];
550}
551
552-(id) initWithDuration: (ccTime) t position: (CGPoint) p
553{
554 if( (self=[super initWithDuration: t]) )
555 endPosition_ = p;
556
557 return self;
558}
559
560-(id) copyWithZone: (NSZone*) zone
561{
562 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: endPosition_];
563 return copy;
564}
565
566-(void) startWithTarget:(CCNode *)aTarget
567{
568 [super startWithTarget:aTarget];
569 startPosition_ = [(CCNode*)target_ position];
570 delta_ = ccpSub( endPosition_, startPosition_ );
571}
572
573-(void) update: (ccTime) t
574{
575 [target_ setPosition: ccp( (startPosition_.x + delta_.x * t ), (startPosition_.y + delta_.y * t ) )];
576}
577@end
578
579//
580// MoveBy
581//
582#pragma mark -
583#pragma mark MoveBy
584
585@implementation CCMoveBy
586+(id) actionWithDuration: (ccTime) t position: (CGPoint) p
587{
588 return [[[self alloc] initWithDuration:t position:p ] autorelease];
589}
590
591-(id) initWithDuration: (ccTime) t position: (CGPoint) p
592{
593 if( (self=[super initWithDuration: t]) )
594 delta_ = p;
595
596 return self;
597}
598
599-(id) copyWithZone: (NSZone*) zone
600{
601 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: delta_];
602 return copy;
603}
604
605-(void) startWithTarget:(CCNode *)aTarget
606{
607 CGPoint dTmp = delta_;
608 [super startWithTarget:aTarget];
609 delta_ = dTmp;
610}
611
612-(CCActionInterval*) reverse
613{
614 return [[self class] actionWithDuration:duration_ position:ccp( -delta_.x, -delta_.y)];
615}
616@end
617
618
619//
620// SkewTo
621//
622#pragma mark -
623#pragma mark SkewTo
624
625@implementation CCSkewTo
626+(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy
627{
628 return [[[self alloc] initWithDuration: t skewX:sx skewY:sy] autorelease];
629}
630
631-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy
632{
633 if( (self=[super initWithDuration:t]) ) {
634 endSkewX_ = sx;
635 endSkewY_ = sy;
636 }
637 return self;
638}
639
640-(id) copyWithZone: (NSZone*) zone
641{
642 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] skewX:endSkewX_ skewY:endSkewY_];
643 return copy;
644}
645
646-(void) startWithTarget:(CCNode *)aTarget
647{
648 [super startWithTarget:aTarget];
649
650 startSkewX_ = [target_ skewX];
651
652 if (startSkewX_ > 0)
653 startSkewX_ = fmodf(startSkewX_, 180.0f);
654 else
655 startSkewX_ = fmodf(startSkewX_, -180.0f);
656
657 deltaX_ = endSkewX_ - startSkewX_;
658
659 if ( deltaX_ > 180 ) {
660 deltaX_ -= 360;
661 }
662 if ( deltaX_ < -180 ) {
663 deltaX_ += 360;
664 }
665
666 startSkewY_ = [target_ skewY];
667
668 if (startSkewY_ > 0)
669 startSkewY_ = fmodf(startSkewY_, 360.0f);
670 else
671 startSkewY_ = fmodf(startSkewY_, -360.0f);
672
673 deltaY_ = endSkewY_ - startSkewY_;
674
675 if ( deltaY_ > 180 ) {
676 deltaY_ -= 360;
677 }
678 if ( deltaY_ < -180 ) {
679 deltaY_ += 360;
680 }
681}
682
683-(void) update: (ccTime) t
684{
685 [target_ setSkewX: (startSkewX_ + deltaX_ * t ) ];
686 [target_ setSkewY: (startSkewY_ + deltaY_ * t ) ];
687}
688
689@end
690
691//
692// CCSkewBy
693//
694@implementation CCSkewBy
695
696-(id) initWithDuration:(ccTime)t skewX:(float)deltaSkewX skewY:(float)deltaSkewY
697{
698 if( (self=[super initWithDuration:t skewX:deltaSkewX skewY:deltaSkewY]) ) {
699 skewX_ = deltaSkewX;
700 skewY_ = deltaSkewY;
701 }
702 return self;
703}
704
705-(void) startWithTarget:(CCNode *)aTarget
706{
707 [super startWithTarget:aTarget];
708 deltaX_ = skewX_;
709 deltaY_ = skewY_;
710 endSkewX_ = startSkewX_ + deltaX_;
711 endSkewY_ = startSkewY_ + deltaY_;
712}
713
714-(CCActionInterval*) reverse
715{
716 return [[self class] actionWithDuration:duration_ skewX:-skewX_ skewY:-skewY_];
717}
718@end
719
720
721//
722// JumpBy
723//
724#pragma mark -
725#pragma mark JumpBy
726
727@implementation CCJumpBy
728+(id) actionWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j
729{
730 return [[[self alloc] initWithDuration: t position: pos height: h jumps:j] autorelease];
731}
732
733-(id) initWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j
734{
735 if( (self=[super initWithDuration:t]) ) {
736 delta_ = pos;
737 height_ = h;
738 jumps_ = j;
739 }
740 return self;
741}
742
743-(id) copyWithZone: (NSZone*) zone
744{
745 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] position:delta_ height:height_ jumps:jumps_];
746 return copy;
747}
748
749-(void) startWithTarget:(id)aTarget
750{
751 [super startWithTarget:aTarget];
752 startPosition_ = [(CCNode*)target_ position];
753}
754
755-(void) update: (ccTime) t
756{
757 // Sin jump. Less realistic
758// ccTime y = height * fabsf( sinf(t * (CGFloat)M_PI * jumps ) );
759// y += delta.y * t;
760// ccTime x = delta.x * t;
761// [target setPosition: ccp( startPosition.x + x, startPosition.y + y )];
762
763 // parabolic jump (since v0.8.2)
764 ccTime frac = fmodf( t * jumps_, 1.0f );
765 ccTime y = height_ * 4 * frac * (1 - frac);
766 y += delta_.y * t;
767 ccTime x = delta_.x * t;
768 [target_ setPosition: ccp( startPosition_.x + x, startPosition_.y + y )];
769
770}
771
772-(CCActionInterval*) reverse
773{
774 return [[self class] actionWithDuration:duration_ position: ccp(-delta_.x,-delta_.y) height:height_ jumps:jumps_];
775}
776@end
777
778//
779// JumpTo
780//
781#pragma mark -
782#pragma mark JumpTo
783
784@implementation CCJumpTo
785-(void) startWithTarget:(CCNode *)aTarget
786{
787 [super startWithTarget:aTarget];
788 delta_ = ccp( delta_.x - startPosition_.x, delta_.y - startPosition_.y );
789}
790@end
791
792
793#pragma mark -
794#pragma mark BezierBy
795
796// Bezier cubic formula:
797// ((1 - t) + t)3 = 1
798// Expands to…
799// (1 - t)3 + 3t(1-t)2 + 3t2(1 - t) + t3 = 1
800static inline float bezierat( float a, float b, float c, float d, ccTime t )
801{
802 return (powf(1-t,3) * a +
803 3*t*(powf(1-t,2))*b +
804 3*powf(t,2)*(1-t)*c +
805 powf(t,3)*d );
806}
807
808//
809// BezierBy
810//
811@implementation CCBezierBy
812+(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c
813{
814 return [[[self alloc] initWithDuration:t bezier:c ] autorelease];
815}
816
817-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c
818{
819 if( (self=[super initWithDuration: t]) ) {
820 config_ = c;
821 }
822 return self;
823}
824
825-(id) copyWithZone: (NSZone*) zone
826{
827 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] bezier:config_];
828 return copy;
829}
830
831-(void) startWithTarget:(id)aTarget
832{
833 [super startWithTarget:aTarget];
834 startPosition_ = [(CCNode*)target_ position];
835}
836
837-(void) update: (ccTime) t
838{
839 float xa = 0;
840 float xb = config_.controlPoint_1.x;
841 float xc = config_.controlPoint_2.x;
842 float xd = config_.endPosition.x;
843
844 float ya = 0;
845 float yb = config_.controlPoint_1.y;
846 float yc = config_.controlPoint_2.y;
847 float yd = config_.endPosition.y;
848
849 float x = bezierat(xa, xb, xc, xd, t);
850 float y = bezierat(ya, yb, yc, yd, t);
851 [target_ setPosition: ccpAdd( startPosition_, ccp(x,y))];
852}
853
854- (CCActionInterval*) reverse
855{
856 ccBezierConfig r;
857
858 r.endPosition = ccpNeg(config_.endPosition);
859 r.controlPoint_1 = ccpAdd(config_.controlPoint_2, ccpNeg(config_.endPosition));
860 r.controlPoint_2 = ccpAdd(config_.controlPoint_1, ccpNeg(config_.endPosition));
861
862 CCBezierBy *action = [[self class] actionWithDuration:[self duration] bezier:r];
863 return action;
864}
865@end
866
867//
868// BezierTo
869//
870#pragma mark -
871#pragma mark BezierTo
872@implementation CCBezierTo
873-(void) startWithTarget:(id)aTarget
874{
875 [super startWithTarget:aTarget];
876 config_.controlPoint_1 = ccpSub(config_.controlPoint_1, startPosition_);
877 config_.controlPoint_2 = ccpSub(config_.controlPoint_2, startPosition_);
878 config_.endPosition = ccpSub(config_.endPosition, startPosition_);
879}
880@end
881
882
883//
884// ScaleTo
885//
886#pragma mark -
887#pragma mark ScaleTo
888@implementation CCScaleTo
889+(id) actionWithDuration: (ccTime) t scale:(float) s
890{
891 return [[[self alloc] initWithDuration: t scale:s] autorelease];
892}
893
894-(id) initWithDuration: (ccTime) t scale:(float) s
895{
896 if( (self=[super initWithDuration: t]) ) {
897 endScaleX_ = s;
898 endScaleY_ = s;
899 }
900 return self;
901}
902
903+(id) actionWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy
904{
905 return [[[self alloc] initWithDuration: t scaleX:sx scaleY:sy] autorelease];
906}
907
908-(id) initWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy
909{
910 if( (self=[super initWithDuration: t]) ) {
911 endScaleX_ = sx;
912 endScaleY_ = sy;
913 }
914 return self;
915}
916
917-(id) copyWithZone: (NSZone*) zone
918{
919 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] scaleX:endScaleX_ scaleY:endScaleY_];
920 return copy;
921}
922
923-(void) startWithTarget:(CCNode *)aTarget
924{
925 [super startWithTarget:aTarget];
926 startScaleX_ = [target_ scaleX];
927 startScaleY_ = [target_ scaleY];
928 deltaX_ = endScaleX_ - startScaleX_;
929 deltaY_ = endScaleY_ - startScaleY_;
930}
931
932-(void) update: (ccTime) t
933{
934 [target_ setScaleX: (startScaleX_ + deltaX_ * t ) ];
935 [target_ setScaleY: (startScaleY_ + deltaY_ * t ) ];
936}
937@end
938
939//
940// ScaleBy
941//
942#pragma mark -
943#pragma mark ScaleBy
944@implementation CCScaleBy
945-(void) startWithTarget:(CCNode *)aTarget
946{
947 [super startWithTarget:aTarget];
948 deltaX_ = startScaleX_ * endScaleX_ - startScaleX_;
949 deltaY_ = startScaleY_ * endScaleY_ - startScaleY_;
950}
951
952-(CCActionInterval*) reverse
953{
954 return [[self class] actionWithDuration:duration_ scaleX:1/endScaleX_ scaleY:1/endScaleY_];
955}
956@end
957
958//
959// Blink
960//
961#pragma mark -
962#pragma mark Blink
963@implementation CCBlink
964+(id) actionWithDuration: (ccTime) t blinks: (NSUInteger) b
965{
966 return [[[ self alloc] initWithDuration: t blinks: b] autorelease];
967}
968
969-(id) initWithDuration: (ccTime) t blinks: (NSUInteger) b
970{
971 if( (self=[super initWithDuration: t] ) )
972 times_ = b;
973
974 return self;
975}
976
977-(id) copyWithZone: (NSZone*) zone
978{
979 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] blinks: times_];
980 return copy;
981}
982
983-(void) update: (ccTime) t
984{
985 if( ! [self isDone] ) {
986 ccTime slice = 1.0f / times_;
987 ccTime m = fmodf(t, slice);
988 [target_ setVisible: (m > slice/2) ? YES : NO];
989 }
990}
991
992-(CCActionInterval*) reverse
993{
994 // return 'self'
995 return [[self class] actionWithDuration:duration_ blinks: times_];
996}
997@end
998
999//
1000// FadeIn
1001//
1002#pragma mark -
1003#pragma mark FadeIn
1004@implementation CCFadeIn
1005-(void) update: (ccTime) t
1006{
1007 [(id<CCRGBAProtocol>) target_ setOpacity: 255 *t];
1008}
1009
1010-(CCActionInterval*) reverse
1011{
1012 return [CCFadeOut actionWithDuration:duration_];
1013}
1014@end
1015
1016//
1017// FadeOut
1018//
1019#pragma mark -
1020#pragma mark FadeOut
1021@implementation CCFadeOut
1022-(void) update: (ccTime) t
1023{
1024 [(id<CCRGBAProtocol>) target_ setOpacity: 255 *(1-t)];
1025}
1026
1027-(CCActionInterval*) reverse
1028{
1029 return [CCFadeIn actionWithDuration:duration_];
1030}
1031@end
1032
1033//
1034// FadeTo
1035//
1036#pragma mark -
1037#pragma mark FadeTo
1038@implementation CCFadeTo
1039+(id) actionWithDuration: (ccTime) t opacity: (GLubyte) o
1040{
1041 return [[[ self alloc] initWithDuration: t opacity: o] autorelease];
1042}
1043
1044-(id) initWithDuration: (ccTime) t opacity: (GLubyte) o
1045{
1046 if( (self=[super initWithDuration: t] ) )
1047 toOpacity_ = o;
1048
1049 return self;
1050}
1051
1052-(id) copyWithZone: (NSZone*) zone
1053{
1054 CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] opacity:toOpacity_];
1055 return copy;
1056}
1057
1058-(void) startWithTarget:(CCNode *)aTarget
1059{
1060 [super startWithTarget:aTarget];
1061 fromOpacity_ = [(id<CCRGBAProtocol>)target_ opacity];
1062}
1063
1064-(void) update: (ccTime) t
1065{
1066 [(id<CCRGBAProtocol>)target_ setOpacity:fromOpacity_ + ( toOpacity_ - fromOpacity_ ) * t];
1067}
1068@end
1069
1070//
1071// TintTo
1072//
1073#pragma mark -
1074#pragma mark TintTo
1075@implementation CCTintTo
1076+(id) actionWithDuration:(ccTime)t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b
1077{
1078 return [[(CCTintTo*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease];
1079}
1080
1081-(id) initWithDuration: (ccTime) t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b
1082{
1083 if( (self=[super initWithDuration:t] ) )
1084 to_ = ccc3(r,g,b);
1085
1086 return self;
1087}
1088
1089-(id) copyWithZone: (NSZone*) zone
1090{
1091 CCAction *copy = [(CCTintTo*)[[self class] allocWithZone: zone] initWithDuration:[self duration] red:to_.r green:to_.g blue:to_.b];
1092 return copy;
1093}
1094
1095-(void) startWithTarget:(id)aTarget
1096{
1097 [super startWithTarget:aTarget];
1098
1099 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1100 from_ = [tn color];
1101}
1102
1103-(void) update: (ccTime) t
1104{
1105 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1106 [tn setColor:ccc3(from_.r + (to_.r - from_.r) * t, from_.g + (to_.g - from_.g) * t, from_.b + (to_.b - from_.b) * t)];
1107}
1108@end
1109
1110//
1111// TintBy
1112//
1113#pragma mark -
1114#pragma mark TintBy
1115@implementation CCTintBy
1116+(id) actionWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b
1117{
1118 return [[(CCTintBy*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease];
1119}
1120
1121-(id) initWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b
1122{
1123 if( (self=[super initWithDuration: t] ) ) {
1124 deltaR_ = r;
1125 deltaG_ = g;
1126 deltaB_ = b;
1127 }
1128 return self;
1129}
1130
1131-(id) copyWithZone: (NSZone*) zone
1132{
1133 return[(CCTintBy*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:deltaR_ green:deltaG_ blue:deltaB_];
1134}
1135
1136-(void) startWithTarget:(id)aTarget
1137{
1138 [super startWithTarget:aTarget];
1139
1140 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1141 ccColor3B color = [tn color];
1142 fromR_ = color.r;
1143 fromG_ = color.g;
1144 fromB_ = color.b;
1145}
1146
1147-(void) update: (ccTime) t
1148{
1149 id<CCRGBAProtocol> tn = (id<CCRGBAProtocol>) target_;
1150 [tn setColor:ccc3( fromR_ + deltaR_ * t, fromG_ + deltaG_ * t, fromB_ + deltaB_ * t)];
1151}
1152
1153- (CCActionInterval*) reverse
1154{
1155 return [CCTintBy actionWithDuration:duration_ red:-deltaR_ green:-deltaG_ blue:-deltaB_];
1156}
1157@end
1158
1159//
1160// DelayTime
1161//
1162#pragma mark -
1163#pragma mark DelayTime
1164@implementation CCDelayTime
1165-(void) update: (ccTime) t
1166{
1167 return;
1168}
1169
1170-(id)reverse
1171{
1172 return [[self class] actionWithDuration:duration_];
1173}
1174@end
1175
1176//
1177// ReverseTime
1178//
1179#pragma mark -
1180#pragma mark ReverseTime
1181@implementation CCReverseTime
1182+(id) actionWithAction: (CCFiniteTimeAction*) action
1183{
1184 // casting to prevent warnings
1185 CCReverseTime *a = [super alloc];
1186 return [[a initWithAction:action] autorelease];
1187}
1188
1189-(id) initWithAction: (CCFiniteTimeAction*) action
1190{
1191 NSAssert(action != nil, @"CCReverseTime: action should not be nil");
1192 NSAssert(action != other_, @"CCReverseTime: re-init doesn't support using the same arguments");
1193
1194 if( (self=[super initWithDuration: [action duration]]) ) {
1195 // Don't leak if action is reused
1196 [other_ release];
1197 other_ = [action retain];
1198 }
1199
1200 return self;
1201}
1202
1203-(id) copyWithZone: (NSZone*) zone
1204{
1205 return [[[self class] allocWithZone: zone] initWithAction:[[other_ copy] autorelease] ];
1206}
1207
1208-(void) dealloc
1209{
1210 [other_ release];
1211 [super dealloc];
1212}
1213
1214-(void) startWithTarget:(id)aTarget
1215{
1216 [super startWithTarget:aTarget];
1217 [other_ startWithTarget:target_];
1218}
1219
1220-(void) stop
1221{
1222 [other_ stop];
1223 [super stop];
1224}
1225
1226-(void) update:(ccTime)t
1227{
1228 [other_ update:1-t];
1229}
1230
1231-(CCActionInterval*) reverse
1232{
1233 return [[other_ copy] autorelease];
1234}
1235@end
1236
1237//
1238// Animate
1239//
1240
1241#pragma mark -
1242#pragma mark Animate
1243@implementation CCAnimate
1244
1245@synthesize animation = animation_;
1246
1247+(id) actionWithAnimation: (CCAnimation*)anim
1248{
1249 return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:YES] autorelease];
1250}
1251
1252+(id) actionWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b
1253{
1254 return [[[self alloc] initWithAnimation:anim restoreOriginalFrame:b] autorelease];
1255}
1256
1257+(id) actionWithDuration:(ccTime)duration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL)b
1258{
1259 return [[[self alloc] initWithDuration:duration animation:anim restoreOriginalFrame:b] autorelease];
1260}
1261
1262-(id) initWithAnimation: (CCAnimation*)anim
1263{
1264 NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil");
1265 return [self initWithAnimation:anim restoreOriginalFrame:YES];
1266}
1267
1268-(id) initWithAnimation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b
1269{
1270 NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil");
1271
1272 if( (self=[super initWithDuration: [[anim frames] count] * [anim delay]]) ) {
1273
1274 restoreOriginalFrame_ = b;
1275 self.animation = anim;
1276 origFrame_ = nil;
1277 }
1278 return self;
1279}
1280
1281-(id) initWithDuration:(ccTime)aDuration animation: (CCAnimation*)anim restoreOriginalFrame:(BOOL) b
1282{
1283 NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil");
1284
1285 if( (self=[super initWithDuration:aDuration] ) ) {
1286
1287 restoreOriginalFrame_ = b;
1288 self.animation = anim;
1289 origFrame_ = nil;
1290 }
1291 return self;
1292}
1293
1294
1295-(id) copyWithZone: (NSZone*) zone
1296{
1297 return [[[self class] allocWithZone: zone] initWithDuration:duration_ animation:animation_ restoreOriginalFrame:restoreOriginalFrame_];
1298}
1299
1300-(void) dealloc
1301{
1302 [animation_ release];
1303 [origFrame_ release];
1304 [super dealloc];
1305}
1306
1307-(void) startWithTarget:(id)aTarget
1308{
1309 [super startWithTarget:aTarget];
1310 CCSprite *sprite = target_;
1311
1312 [origFrame_ release];
1313
1314 if( restoreOriginalFrame_ )
1315 origFrame_ = [[sprite displayedFrame] retain];
1316}
1317
1318-(void) stop
1319{
1320 if( restoreOriginalFrame_ ) {
1321 CCSprite *sprite = target_;
1322 [sprite setDisplayFrame:origFrame_];
1323 }
1324
1325 [super stop];
1326}
1327
1328-(void) update: (ccTime) t
1329{
1330 NSArray *frames = [animation_ frames];
1331 NSUInteger numberOfFrames = [frames count];
1332
1333 NSUInteger idx = t * numberOfFrames;
1334
1335 if( idx >= numberOfFrames )
1336 idx = numberOfFrames -1;
1337
1338 CCSprite *sprite = target_;
1339 if (! [sprite isFrameDisplayed: [frames objectAtIndex: idx]] )
1340 [sprite setDisplayFrame: [frames objectAtIndex:idx]];
1341}
1342
1343- (CCActionInterval *) reverse
1344{
1345 NSArray *oldArray = [animation_ frames];
1346 NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:[oldArray count]];
1347 NSEnumerator *enumerator = [oldArray reverseObjectEnumerator];
1348 for (id element in enumerator)
1349 [newArray addObject:[[element copy] autorelease]];
1350
1351 CCAnimation *newAnim = [CCAnimation animationWithFrames:newArray delay:animation_.delay];
1352 return [[self class] actionWithDuration:duration_ animation:newAnim restoreOriginalFrame:restoreOriginalFrame_];
1353}
1354
1355@end