11

When i call relpaceScene or pushScene in cocos2d, I can add some transitions to it like:

[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1 scene:scene]];

but when i call popScene, it takes no parameters, and no transition can be added. Is that so? How can i popScene with desired transitions?

willzeng
  • 169
  • 1
  • 5

5 Answers5

20

Per Guy in the cocos2d forums this seems to work: Link to Forum

Add this to CCDirector.h, just after the declaration -(void)popScene (line 402):

    - (void) popSceneWithTransition: (Class)c duration:(ccTime)t;

Then add this to CCDirector.m, just after the definition of -(void)popScene (line 768):

    -(void) popSceneWithTransition: (Class)transitionClass duration:(ccTime)t;
    {
    NSAssert( runningScene_ != nil, @"A running Scene is needed");

    [scenesStack_ removeLastObject];
    NSUInteger c = [scenesStack_ count];
    if( c == 0 ) {
        [self end];
    } else {
        CCScene* scene = [transitionClass transitionWithDuration:t scene:[scenesStack_ objectAtIndex:c-1]];
        [scenesStack_ replaceObjectAtIndex:c-1 withObject:scene];
        nextScene_ = scene;
    }
}

You can call the method like this:

[[CCDirector sharedDirector] popSceneWithTransition:[CCSlideInRTransition class] durat
Pinwheeler
  • 1,061
  • 2
  • 13
  • 26
ScottPetit
  • 814
  • 5
  • 6
  • Wonderful, it worked. Previously I didn't know that I have to modify cocos2d for this thing. Thanks very much. – willzeng Aug 16 '11 at 12:58
  • 1
    @willzeng You should mark correct answers as correct, to help people in the future. – ScottPetit Aug 18 '11 at 14:14
  • @Scottpetit, why line `[scenesStack_ replaceObjectAtIndex:c-1 withObject:scene];` is required at all? – Vasu Feb 01 '13 at 09:22
3

You can use Category as follows:

@interface CCDirector (PopTransition)

- (void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t;

@end

@implementation CCDirector (PopTransition)

- (void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t {

    [self popScene];

    // Make Transition
    if (nextScene_) {
        CCScene* scene = [transitionClass transitionWithDuration:t scene:nextScene_];
        [scenesStack_ replaceObjectAtIndex:([scenesStack_ count] - 1) withObject:scene];
        nextScene_ = scene;
    }
}

@end

This way you need not to modify CCDirector class.

Vasu
  • 4,862
  • 8
  • 42
  • 48
0

I modified Kailash's answer to work with cocos2d 2.1.

CCDirector+additions.h

#import "cocos2d.h"

@interface CCDirector (additions)
-(void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t;
@end

CCDirector+additions.m

#import "CCDirector+additions.h"

@implementation CCDirector (additions)
-(void)popSceneWithTransition:(Class)transitionClass duration:(ccTime)t {
    [self popScene];

    // Make Transition
    if (_nextScene) {
        CCScene* scene = [transitionClass transitionWithDuration:t scene:_nextScene];
        [_scenesStack replaceObjectAtIndex:([_scenesStack count] - 1) withObject:scene];
        _nextScene = scene;
    }
}
@end
Jonny
  • 15,955
  • 18
  • 111
  • 232
0

A more concise version of the above that actually releases the scene so it and its textures can be cleaned up as needed.

CCDirector+addition.h

#import "cocos2d.h"

@interface CCDirector (addition)

- (void) popSceneWithTransition:(Class)transitionClass duration:(ccTime)t;

@end

CCDirector+addition.m

#import "CCDirector+addition.h"

@implementation CCDirector (addition)

- (void) popSceneWithTransition:(Class)transitionClass duration:(ccTime)t {
    [_scenesStack removeLastObject];

    NSUInteger count = [_scenesStack count];
    NSAssert(count > 0, @"Don't popScene when there aren't any!");

    CCScene* scene = [transitionClass transitionWithDuration:t scene:[_scenesStack lastObject]];
    [self replaceScene:scene];
}

@end
0

Without having to mess with Cocos2d internals you can do it like:

CCDirector *director  = [CCDirector sharedDirector];
CCScene *currentScene = [director runningScene];
CGSize contentSize    = [currentScene contentSize];
CCLayerColor *black   = [[CCLayerColor alloc] initWithColor:ccc4(0, 0, 0, 0) width:contentSize.width height:contentSize.height];
[currentScene addChild:black];
[black runAction:[CCSequence actionOne:[CCFadeTo actionWithDuration:1.0f opacity:255]
                                   two:[CCCallFunc actionWithTarget:director selector:@selector(popScene)]]];
patrick
  • 9,290
  • 13
  • 61
  • 112