一款游戏一般肯定不止有一个scene(啥?你就做了一个?回去洗洗睡吧),从一个scene到另一个scene的过程就是本篇讨论的中心。假设当前在FirstScene,然后执行如下代码:
[[CCDirector sharedDirector] replaceScene:[OtherScene scene]];
将会引发一系列的方法被调用,如下:
1. scene: OtherScene的
2. init: OtherScene的
3. onEnter: OtherScene的
4. Transition 发生.
5. onExit: FirstScene的
6. onEnterTransitionDidFinish: OtherScene的
7. dealloc: FirstScene的
当一个scene被搬上“台面”,它会收到onEnter,原来的scene会收到onExit,最后交替完成在台面上的scene收到onEnterTransitionDidFinish。从中我们可以看出,只有当登台的scene完全加载完成,下场的scene才会被释放。两个scene在某一帧是同时处在内存里的,内存自然会表示压力很大。
两个资源密集型的scene在切换时,不仅对内存有很大压力,加载时间有时也会长到让用户果断按下home键。书中给出了一个巧妙的解决方案:通过引入一个轻量的中间scene,使源scene先切换到中间scene,再切换到目标scene。这样不仅避免了源scene和目标scene的重叠,还可以在中间scene显示loading等字样。中间scene的名字叫LoadingScene,代码如下:
//LoadingScene.h
typedef enum
{
TargetSceneFirstScene,
TargetSceneOtherScene,
} TargetScenes; //定义几个target scene,还是使用enum来提高可读性
@interface LoadingScene : CCScene { //直接继承CCScene,这里完全不需要CCLayer
TargetScenes targetScene_;
}
+(id) sceneWithTargetScene:(TargetScenes)targetScene;
-(id) initWithTargetScene:(TargetScenes)targetScene;
//LoadingScene.m
+(id) sceneWithTargetScene:(TargetScenes)targetScene
{
return [[[self alloc] initWithTargetScene:targetScene] autorelease];
}
-(id) initWithTargetScene:(TargetScenes)targetScene
{
if (self = [super init]) {
targetScene_ = targetScene;
//这里可以放个CCLabel来显示loading什么的,不是重点,不写了。
[self scheduleUpdate]; //最关键的一句!等待一帧,让源scene的内存都释放掉,下一帧进入update
}
return self;
}
-(void) update:(ccTime)delta
{
[self unscheduleAllSelectors]; //取消schedule,update不会再被调用了
switch (targetScene_)
{
case TargetSceneFirstScene:
[[CCDirector sharedDirector] replaceScene:[FirstScene scene]]; break;
case TargetSceneOtherScene:
[[CCDirector sharedDirector] replaceScene:[OtherScene scene]]; break;
default:
//error
break;
}
}
有了LoadingScene作为中介,scene的切换就可以这样写了:
[[CCDirector sharedDirector] replaceScene:[LoadingScene sceneWithTargetScene:TargetSceneOtherScene]];
written by Magic
转载请注明原地址: http://blog.sina.com.cn/s/blog_77013e2b0100qosh.html