COCOS2D(4) 使用过渡场景在多个场景的切换

本文详细介绍了如何在Cocos2d-X中使用CCDirector的replaceScene方法替换场景,包括onEnter、onExit和onEnterTransitionDidFinish方法的使用,以及如何创建自定义场景类LoadingScene进行场景过渡。通过代码示例,展示了如何在不同场景间平滑过渡,并且确保资源正确释放和加载,避免内存泄漏。同时,提供了场景编号和加载策略的实现细节,以及如何在场景间传递状态的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CCNode有三个方法,使用CCDirector的replaceScene方法替换场景时,每个节点都会调用这三个方法:

onEnter与onExit方法在改变场景过程中的特定时刻被调用,这取决于是否使用CCTransitionScene。

onEnterTransitionDidFinish方法在替换结束时调用。

必须总是调用这些方法的超类实现来避免难输入问题和内存泄漏。

-(void) onEnter
{
	CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
    
	// must call super here:
	[super onEnter];
}

-(void) onEnterTransitionDidFinish
{
	CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
    
	// must call super here:
	[super onEnterTransitionDidFinish];
}

-(void) onExit
{
	CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
	
	// must call super here:
	[super onExit];
}

编写过渡场景:

LoadingScene充当一个中间场景的角色,它是cocos2d中的CCScene类的派生类,不必为每一次场景创建一个新的LoadingScene。

代码清单:LoadingScene.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"

typedef enum
{
	TargetSceneINVALID = 0,
	TargetSceneFirstScene,
	TargetSceneOtherScene,
	TargetSceneMAX,
} TargetScenes;

@interface LoadingScene : CCScene {
    
    TargetScenes targetScene_;
}

+(id) sceneWithTargetScene:(TargetScenes)targetScene;
-(id) initWithTargetScene:(TargetScenes)targetScene;

@end

使用enum给各个场景编个号,而且将enum的第一个值设为0,在Objective-c中变量的值会自动初始化为0.并在最后设了个MAX值。

代码清单:LoadingScene.m

#import "LoadingScene.h"
#import "MyFirstScene.h"
#import "OtherScene.h"

@interface LoadingScene (PrivateMethods)
-(void) update:(ccTime)delta;
@end

@implementation LoadingScene
+(id) sceneWithTargetScene:(TargetScenes)targetScene;
{
	CCLOG(@"===========================================");
	CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
    
	// This creates an autorelease object of self (the current class: LoadingScene)
	return [[[self alloc] initWithTargetScene:targetScene] autorelease];
	
	// Note: this does the exact same, it only replaced self with LoadingScene. The above is much more common.
	//return [[[LoadingScene alloc] initWithTargetScene:targetScene] autorelease];
}

-(id) initWithTargetScene:(TargetScenes)targetScene
{
	if ((self = [super init]))
	{
		targetScene_ = targetScene;
        
		CCLabelTTF* label = [CCLabelTTF labelWithString:@"Loading ..." fontName:@"Marker Felt" fontSize:64];
		CGSize size = [[CCDirector sharedDirector] winSize];
		label.position = CGPointMake(size.width / 2, size.height / 2);
		[self addChild:label];
		
		// Must wait one frame before loading the target scene!
		// Two reasons: first, it would crash if not. Second, the Loading label wouldn't be displayed.
		[self scheduleUpdate];
	}
	
	return self;
}

-(void) update:(ccTime)delta
{
	// It's not strictly necessary, as we're changing the scene anyway. But just to be safe.
	[self unscheduleAllSelectors];
	
	// Decide which scene to load based on the TargetScenes enum.
	// You could also use TargetScene to load the same with using a variety of transitions.
	switch (targetScene_)
	{
		case TargetSceneFirstScene:
			[[CCDirector sharedDirector] replaceScene:[MyFirstScene scene]];
			break;
		case TargetSceneOtherScene:
			[[CCDirector sharedDirector] replaceScene:[OtherScene scene]];
			break;
			
		default:
			// Always warn if an unspecified enum value was used. It's a reminder for yourself to update the switch
			// whenever you add more enum values.
			NSAssert2(nil, @"%@: unsupported TargetScene %i", NSStringFromSelector(_cmd), targetScene_);
			break;
	}
	
	// Tip: example usage of the INVALID and MAX enum values to iterate over all enum values
	for (TargetScenes i = TargetSceneINVALID + 1; i < TargetSceneMAX; i++)
	{
	}
}

-(void) dealloc
{
	CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
	
	// don't forget to call "super dealloc"
	[super dealloc];
}
@end

由于LoadingScene类由CCScene派生出来,所以不需要调用[CCScene node],sceneWithTargetScene方法先为self分配空间,然后调用initWithTargetScene初始化


在MyFirstScene中调用LoadingScene:

    CCScene *newScene = [LoadingScene sceneWithTargetScene:TargetSceneOtherScene];
    [[CCDirector sharedDirector] replaceScene:newScene];

在OtherScene中调用基本类似,请读者自行实践。



下面给出了在执行过程中的一些输出信息,它详细的说明了各个方法的调用顺序:
2012-10-06 13:50:03.404 MutiScene[1884:1be03] ===========================================
2012-10-06 13:50:03.405 MutiScene[1884:1be03] scene: MyFirstScene
2012-10-06 13:50:03.406 MutiScene[1884:1be03] init : <MyFirstScene = 0x94e2540 | Tag = -1>
2012-10-06 13:50:08.610 MutiScene[1884:1be03] cocos2d: animation started with frame interval: 60.00
2012-10-06 13:50:08.613 MutiScene[1884:1be03] cocos2d: surface size: 480x320
2012-10-06 13:50:08.614 MutiScene[1884:1be03] onEnter: <MyFirstScene = 0x94e2540 | Tag = -1>
2012-10-06 13:50:08.615 MutiScene[1884:1be03] onEnterTransitionDidFinish: <MyFirstScene = 0x94e2540 | Tag = -1>
2012-10-06 13:50:11.844 MutiScene[1884:1be03] ===========================================
2012-10-06 13:50:11.845 MutiScene[1884:1be03] scene: OtherScene
2012-10-06 13:50:11.846 MutiScene[1884:1be03] init: <OtherScene = 0x9418280 | Tag = -1>
2012-10-06 13:50:16.907 MutiScene[1884:1be03] onEnter: <OtherScene = 0x9418280 | Tag = -1>
2012-10-06 13:50:19.944 MutiScene[1884:1be03] onExit: <MyFirstScene = 0x94e2540 | Tag = -1>
2012-10-06 13:50:19.945 MutiScene[1884:1be03] onEnterTransitionDidFinish: <OtherScene = 0x9418280 | Tag = -1>
2012-10-06 13:50:19.947 MutiScene[1884:1be03] dealloc : <MyFirstScene = 0x94e2540 | Tag = -1>
2012-10-06 13:50:29.953 MutiScene[1884:1be03] ===========================================
2012-10-06 13:50:29.954 MutiScene[1884:1be03] sceneWithTargetScene:: LoadingScene
2012-10-06 13:50:29.961 MutiScene[1884:1be03] onExit: <OtherScene = 0x9418280 | Tag = -1>
2012-10-06 13:50:29.962 MutiScene[1884:1be03] dealloc: <OtherScene = 0x9418280 | Tag = -1>
2012-10-06 13:50:29.977 MutiScene[1884:1be03] ===========================================
2012-10-06 13:50:29.979 MutiScene[1884:1be03] scene: MyFirstScene
2012-10-06 13:50:29.980 MutiScene[1884:1be03] init : <MyFirstScene = 0x9418280 | Tag = -1>
2012-10-06 13:50:35.031 MutiScene[1884:1be03] dealloc: <LoadingScene = 0x11a59950 | Tag = -1>
2012-10-06 13:50:35.032 MutiScene[1884:1be03] onEnter: <MyFirstScene = 0x9418280 | Tag = -1>
2012-10-06 13:50:35.032 MutiScene[1884:1be03] onEnterTransitionDidFinish: <MyFirstScene = 0x9418280 | Tag = -1>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值