CCScene"场景",
运行游戏时需要通过
[CCDirector sharedDirector]runWithScene:<#(CCScene *)#>]
启动第一个场景,也可以通过代理的
-(CCScene *)startScene
方法,创建并返回第一个场景。
当然,游戏复杂的话,会包含很多个场景,
场景的切换,也是通过CCDirector来完成。
CCScene是个抽象的概念,也没有可视化显示的功能,
// // IntroScene.h // 31_cocos2D入门 // // Created by beyond on 14-9-5. // Copyright com.beyond 2014年. All rights reserved. // // Importing cocos2d.h and cocos2d-ui.h, will import anything you need to start using cocos2d-v3 #import "cocos2d.h" #import "cocos2d-ui.h" /** * The intro scene * Note, that scenes should now be based on CCScene, and not CCLayer, as previous versions * Main usage for CCLayer now, is to make colored backgrounds (rectangles) * */ @interface IntroScene : CCScene + (IntroScene *)scene; - (id)init; @end
// // IntroScene.m // 31_cocos2D入门 // // Created by beyond on 14-9-5. // Copyright com.beyond 2014年. All rights reserved. // #import "IntroScene.h" #import "HelloWorldScene.h" @implementation IntroScene #pragma mark - 生命周期 + (IntroScene *)scene { return [[self alloc] init]; } - (id)init { self = [super init]; if (!self) return(nil); // 创建背景颜色为深灰色 CCNodeColor *background = [CCNodeColor nodeWithColor:[CCColor colorWithRed:0.2f green:0.2f blue:0.2f alpha:1.0f]]; [self addChild:background]; // 创建文字标签 Chalkduster Courier New CCLabelTTF *label = [CCLabelTTF labelWithString:@"Hello Beyond" fontName:@"Courier New" fontSize:36.0f]; // 紫色:红 + 0 + 蓝 // 黄色:红 + 绿 + 0 // 青色:0 + 绿 + 蓝 label.color = [CCColor redColor]; label.positionType = CCPositionTypeNormalized; // 屏幕的正中间 注意这里是笛卡尔坐标系,原点在左下方 label.position = ccp(0.5f, 0.5f); [self addChild:label]; // 创建一个开始按钮,点击后进入下一个场景 CCButton *helloWorldButton = [CCButton buttonWithTitle:@"[ Start ]" fontName:@"Verdana-Bold" fontSize:18.0f]; helloWorldButton.positionType = CCPositionTypeNormalized; // 屏幕的中间靠下方 注意这里是笛卡尔坐标系,原点在左下方 helloWorldButton.position = ccp(0.5f, 0.35f); // 监听点击事件 [helloWorldButton setTarget:self selector:@selector(onSpinningClicked:)]; [self addChild:helloWorldButton]; // 返回创建好的场景对象 return self; } #pragma mark - 按钮点击事件,切换至下一场景 - (void)onSpinningClicked:(id)sender { // 动画切换至下一个场景 [[CCDirector sharedDirector] replaceScene:[HelloWorldScene scene] withTransition:[CCTransition transitionPushWithDirection:CCTransitionDirectionLeft duration:1.0f]]; } @end
常用操作
1.运行第一个场景
一般是在应用程序代理AppDelegate的applicationDidFinishLaunching:方法游戏参数,
在代理的startScene方法里面,创建并返回游戏的第一个场景
// // AppDelegate.m // 31_cocos2D入门 // // Created by beyond on 14-9-5. // Copyright com.beyond 2014年. All rights reserved. // AppDelegate 继承自 CCAppDelegate /* CCAppDelegate 继承自NSObect,遵守协议:<UIApplicationDelegate, CCDirectorDelegate> CCAppDelegate 拥有成员:UIWindow *window_ * 大多 Cocos2d 应用 应该重写 CCAppDelegate, CCAppDelegate作为应用的程序入口. 至少应该复写 startScene 方法,以便 返回应用要展示的首个场景 如果想更进一步定制 Cocos2d(例如自定义显示的像素模式), 请复写 applicaton:didFinishLaunchingWithOptions: 方法 */ #import "AppDelegate.h" #import "IntroScene.h" #import "HelloWorldScene.h" @implementation AppDelegate // -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 当继承自CCAppDelegate,唯一要实现的方法就是这一个方法,应用首次启动就会第一个执行本方法 // 在这儿,可以设置 Cocos2D 各参数的默认值 // There are a number of simple options you can change. // 如果你还嫌调用setupCocos2dWithOptions方法,不够灵活自由,那么你可以自己顶置 Cocos2D [self setupCocos2dWithOptions:@{ // 显示 FPS (frame per second) CCSetupShowDebugStats: @(YES), // 使用降低了的帧率 CCSetupAnimationInterval: @(1.0/30.0), // 使用一个加快的帧率 // CCSetupFixedUpdateInterval: @(1.0/180.0), // 设置屏幕为竖屏模式 // CCSetupScreenOrientation: CCScreenOrientationPortrait, // 使用16位颜色: // CCSetupPixelFormat: kEAGLColorFormatRGB565, // 使用一个统一的固定的坐标系统 // CCSetupScreenMode: CCScreenModeFixed, // Make iPad's act like they run at a 2x content scale. (iPad retina 4x) // CCSetupTabletScale2X: @(YES), // 更多内容请参阅 CCAppDelegate.h }]; return YES; } -(CCScene *)startScene { // 本方法返回应用启动时,第一个要展示的场景 return [IntroScene scene]; } @end
这里的[IntroScene scene]返回的是一个CCScene对象
2.替换场景
<span style="font-size:18px;">[[CCDirector sharedDirector] replaceScene:scene];</span>
这个方法会用新的场景替换旧的场景,
cocos2d会释放旧场景的内存,
删除旧场景中所有的节点,
停止所有动作和消息调度,
因此不用手动释放旧场景的内存
3.推入和弹出场景
用replaceScene:来运行一个新场景,
但是会释放掉旧场景的内存。
有时候希望在不释放旧场景内存的前提下 运行一个新场景,
这时候就要用到CCDirector的pushScene:和popScene两个方法了。
1> 使用pushScene:方法推入一个新场景,
新场景会层叠在旧场景的上面,
但并没有释放旧场景的内存,旧场景继续保留在内存中
<span style="font-size:18px;">[[CCDirector sharedDirector] pushScene:scene];</span>
2> 使用popScene方法弹出最上层的场景并释放其内存,
使保留在内存中的旧场景重新显示出来
<span style="font-size:18px;">[[CCDirector sharedDirector] popScene];</span>
CCTransition
上面介绍了场景的切换,不过都是瞬间完成的,
有时候想在场景切换的时候有些过渡效果,
即以动画的形式切换场景,称之为"场景过渡"。
要想做场景过渡效果,
就必须用CCTransition的子类,
CCTransition本身继承了CCScene,
它包含了非常多的子类,每个子类都有不同的场景过渡效果,
cocos2d中有非常多的过渡效果可以使用,
都是CCTransition的子类,
类名一般都是以CCTransition开头的。
注意:CCTransition只能使用在replaceScene:和pushScene:的时候,
在popScene弹出场景时是不能用这个过渡效果的
节点的生命周期
说到场景过渡,那就不得不说一下节点的生命周期,
即一个节点从开始被添加到屏幕上 到 从屏幕中移除的过程,
CCNode提供了相应的生命周期方法:
<span style="font-size:18px;">// 节点被添加到屏幕上 或者 重新显示到屏幕上 时调用 -(void) onEnter; // 调用完onEnter后就会调用此方法,如果使用了场景过渡效果,将在场景过渡完毕后才调用此方法 -(void) onEnterTransitionDidFinish; // 节点从屏幕中移除 或者 暂时离开屏幕 时调用 -(void) onExit;</span>
场景切换时,节点生命周期方法存在一定的调用顺序
抽出一个继承了CCLayerColor的公共父类BaseLayer,
在它里面完成一些公共操作,然后让子类都继承它
BaseLayer的代码
<span style="font-size:18px;">// BaseLayer.h #import "cocos2d.h" @interface BaseLayer : CCLayerColor // 用来创建图层所在的场景 + (CCScene *)scene; // 图层的背景颜色,交给子类去实现 + (ccColor4B)bgColor; @end</span>
<span style="font-size:18px;">// BaseLayer.m #import "BaseLayer.h" @implementation BaseLayer #pragma mark - 初始化场景 + (CCScene *)scene { // 获取当前类的背景颜色 ccColor4B color = [self bgColor]; // 根据当前类名创建图层 BaseLayer *layer = [[self class] layerWithColor:color]; // 接收触摸输入 layer.isTouchEnabled = YES; CCScene *scene = [CCScene node]; [scene addChild:layer]; return scene; } #pragma mark - 打印生命周期方法 - (void)onEnter { // _cmd 代表着当前的selector [super onEnter]; // 第一个%@是打印类名,第二个%@是打印方法名 NSLog(@"%@ --> %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); } - (void)onEnterTransitionDidFinish { [super onEnterTransitionDidFinish]; NSLog(@"%@ --> %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); } - (void)onExit { [super onExit]; NSLog(@"%@ --> %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); } @end</span>