《Cocos2D权威指南》——3.2 CCNode节点类

3.2 CCNode节点类

CCNode是Cocos2D中最重要的类,同时也是所有节点的基类。它是一个抽象类,没有视觉表现,定义了所有节点都通用的属性和方法。
在Cocos2D中,所有要绘制到屏幕的对象,或是自身包含要绘制到屏幕中的对象,都属于CCNode类。最重要的几个CCNode类分别是CCScene、CCLayer、CCSprite、CCMenu,这也是我们本章要重点学习的内容。
CCNode的主要作用:
包含其他的CCNode节点(addChild、getChildByTag、removeChild等方法);
通过定时器预定消息(schedule、unschedule等方法);
执行动作(runAction、stopAction等方法)。
注意 作为抽象类,CCNode是没有自身纹理的。
3.2.1 CCNode类的属性
CCNode类的常见属性包括以下各种。
(1)anchorPoint
anchorPoint表示锚点。节点的变形和定位操作都要依据锚点来确定。锚点的变量类型是CGPoint。
锚点值通常在0~1之间,(0,0)代表左下角,而(1,1)代表右上角。默认CCNode节点锚点值是(0,0),也就是节点左下角。另外,还有anchorPointInPoints属性,区别在于其采用绝对像素值为单位。
(2)camera
camera用于设置游戏中的视角,利用OpenGL ES中的gluLookAt()。变量类型是CCCamera。
只有在创建3D效果时才会用到camera属性。如果使用了该属性,就不能再同时使用rotation、scale、position这些属性。
注意 Cocos2D不推荐直接使用camera。如果需要实现一个视差滚动的背景(人物向前移动时,游戏场景向身后移动,并且远近不同的背景移动速度还不一样,近的物体移动速度快,远的物体移动速度慢,即所谓的视差),通过移动camera来实现会变得更复杂,而且会使Cocos2D本身的一些功能特性遭受破坏。推荐的作法是使用CCParallaxNode,后面章节中我们会向大家演示如何做。
(3)children
children为节点的子节点数组。变量类型是CCArray。
CCArray是专门为了性能优化而设计的类,它的功能和NSMutablArray差不多。推荐在Cocos2D中尽量使用CCArray替代NSMutableArray。
(4)contentSize
contentSize为未经转换的节点大小,以points(点值)为单位。contentSize的变量类型是CGSize,默认值为(0,0)。
无论节点如何缩放或旋转,contentSize属性值始终不变。所有的节点都有大小,而Layer(层)和Screen(场景)大小就是屏幕大小。
contentSize主要用于碰撞检测,我们可以根据节点当前所在位置以及节点纹理本身的大小来计算碰撞矩形区域,具体代码如代码清单3-2所示。
代码清单3-2 计算碰撞矩形区域

-(CGRect) rectOfSprite:(CCSprite*)sprite{
    return CGRectMake(sprite.position.x - sprite.contentSize.width / 2,
                   sprite.position.y - sprite.contentSize.height /2,
                   sprite.contentSize.width, sprite.contentSize.height);
}

(5)glServerState
glServerState表示OpenGLES服务器端状态,从Cocos2D v2.0版本开始使用。变量类型是ccGLServerState,可参考ccGLState.h。
(6)grid
在对节点应用某些特殊效果时会用到此属性。变量类型是CCGridBase。
(7)isRelativeAnchorPoint
该属性为YES时,节点的变形将基于锚点进行。变量类型是BOOL。
对于精灵、标签和其他可调整大小的节点会默认启用该属性;而对于场景、层和其他“全屏”对象,会默认禁用该属性。
(8)isRunning
isRunning用于判断当前节点是否在运行。变量类型是BOOL。
(9)orderOfArrival
当使用同样的z值对子节点进行排序的时候,用该属性来决定子节点的顺序,不要手动更改该数值。变量类型是NSUInteger。
(10)parent
parent表示对节点父节点的弱引用,通常很少用到。变量类型是CCNode。
(11)position
position表示节点在屏幕中的位置。变量类型是CGPoint,以points(点值)为单位,屏幕的左下角坐标是(0,0)。
此外,positionInPixels属性同样表示节点在屏幕中的位置,不过单位为pixels(像素值),变量类型是CGPoint,默认值为(0,0)。
(12)rotation
rotation表示节点沿顺时针方向旋转的角度。变量类型是float,默认值为0。
(13)scale
scale表示节点的缩放比例。变量类型是float,有三个属性,默认值为(scaleX=1,scaleY=1)。
scale:节点沿x和y坐标轴的整体缩放比例。
scaleX:节点沿x轴的缩放比例。
scaleY:节点沿y轴的缩放比例。
(14)shaderProgram
shaderProgram表示着色程序。变量类型是GLProgram。
该属性从Cocos2D v2.0版本开始使用,详细信息可参考GLProgram.h。后面会专门用一章介绍如何为CCNode编写定制的shader程序。
(15)skew
skew表示节点的变形角度。变量类型是float。
skewX:沿x轴方向顺时针切向畸变角度(y轴和节点形状左边缘之间的角度),默认值为0。
skewY:沿y轴方向逆时针切向畸变角度(x轴和节点形状底边的角度),默认值为0。
(16)tag
tag用于识别节点的标识值。变量类型是NSInteger。
无论是创建、引用还是删除节点,tag值都有用武之地。比如,tag参数允许通过getChildByTag方法获取指定节点。如果有多个节点拥有相同tag数值,getChildByTag会将找到的第一个节点返回,将不再访问其他节点,所以要确保为节点指定独有的tag数值。
tag在很多应用场景以及Cocos2D游戏编程过程中都起到重要作用。最简单的应用就是在其他scheduler的selector函数里通过getChildByTag得到对应tag节点,这样无需在类的定义里声明过多的节点弱引用(weak ref)。此外,tag还有一个重要的应用场景。多个CCMenuItem共用一个selector时,可以给menuItem赋予不同tag,然后在selector里根据tag值判断玩家具体触碰的是哪一个按钮。
(17)userData
userData为用户自定义的数据指针对象。变量类型是void。
userData经常用于selector之间的数据传递,或者其他需要节点携带传递数据的场合。
(18)visible
visible用于判断节点是否可见。变量类型是BOOL,默认值为YES。
(19)zOrder
zOrder表示节点相对于其“兄弟”节点(拥有共同的父节点)Z顺序值。变量类型是NSInteger。
对于像CCSprite这样有视觉呈现的节点,该参数决定了节点的绘制顺序,拥有最小Z值的节点会首先被绘制,拥有最大Z值的节点最后被绘制。如果多个节点拥有相同Z值,绘制顺序将由它们的添加顺序来决定。
(20)vertexZ
vertexZ表示真正的OpenGL Z顶点。OpenGL Z顶点和Cocos2D Z顺序的区别如下:
OpenGL Z修改Z顶点,而非父节点和子节点间的Z顺序;
OpenGL Z可能需要设置2D投影;
如果所有节点使用相同的OpenGL Z顶点,Cocos2D Z顺序仍然保持正常。
使用该值可能会破坏Cocos2D中的父节点–子节点Z顺序,所以通常较少使用。
以上只是对CCNode类属性的简单介绍,要真正了解每个属性在开发Cocos2D游戏中的作用,需要在实际开发中逐渐体会。在开发过程中大家可以随时回顾本章查找相关属性。第2章的示例代码运用了一部分CCNode属性,大家可以多多学习并修改代码,体会这些属性的用途。
3.2.2 CCNode类的方法
CCNode类中所实现的方法可以分为三个大类,分别是对子节点的处理、使用定时器预定消息,以及执行动作。此外有些方法不属于以上三大类,下面将一一介绍。
1 . 处理子节点
CCNode类实现了所有添加、获取和删除子节点的方法。以下是一些处理子节点的方法:
1)创建一个新的节点。示例代码如下:

CCNode* childNode = [CCNode node];

请注意,这行代码等同于:

CCNode* childNode = [[[CCNode alloc]init]autorelease];

2)将新节点添加为当前节点的子节点,并设置子节点的Z值和tag值。
如果将该子节点添加到“运行”模式,则立即调用“onEnter”和“onEnterTransitionDidFinish”方法。示例代码如下:

[thisNodeaddChild:childNode z:0 tag:1];

3)使用节点的标识获取子节点。示例代码如下:

CCNode* childNode = [thisNode getChildByTag:1];

4)通过tag删除子节点。
如果cleanup的参数值为YES,则停止任何运行中的动作。示例代码如下:

[thisNode removeChildByTag:1 cleanup:YES];

5)通过节点指针删除子节点。
如果cleanup的参数值为YES,则停止任何运行中的动作。示例代码如下:

[thisNoderemoveChild:childNode cleanup:YES];

6)删除一个节点的所有子节点。
如果cleanup的参数值为YES,则停止任何运行中的动作。示例代码如下:

[thisNoderemoveAllChildrenWithCleanup:YES];

7)从当前节点的父节点删除当前节点。
如果cleanup的参数值为YES,将删除所有的动作和回调方法;如果当前节点没有父节点,则不执行任何操作。示例代码如下:

[thisNoderemoveFromParentAndCleanup:YES];

2 . 执行动作
CCNode可以使用动作(Actions)让节点执行某些动作。本书第4章将专门讲述动作的详细内容,现在我们只需要知道使用动作可以让节点移动、旋转和缩放,以及做一些其他事情。
1)运行某个特定的动作。示例代码如下:

[thisNode runAction:action];

其中action是使用CCAction定义的某个动作。
2)停止所有在该节点上运行的动作。示例代码如下:

[thisNode stopAllActions];

3)停止在该节点上运行的某个特定动作。示例代码如下:

[thisNode stopAction:action];

其中action是使用CCAction定义的某个动作。
4)停止运行的动作列表中的某个特定动作,使用tag标识来区分。示例代码如下:

[thisNode stopActionByTag:123];

5)获取当前运行的动作清单中的某个特定动作,使用tag标识来区分。示例代码如下:

myAction  = [thisNode getActionByTag:123];

如果想在以后使用此动作,可以使用这个方法。
6)获取运行动作的数量。
包括正在运行的动作,还包括预定运行的动作(在actionsToAdd和动作数组中的动作),复合动作算一个动作。示例代码如下:

numberofActions = [thisNode numberOfRunningActions];

3 . 预定消息
CCNode节点可以预定消息,其实就是每隔一段时间调用一次方法。在很多游戏中需要节点调用特定的更新方法来处理某些情况,比如碰撞测试等。
1)每帧都调用的更新方法,每个节点只可预定一个update方法。示例代码如下:

-(void) scheduleUpdates
{
       [self scheduleUpdate];
}
-(void) update:(ccTime)delta
{
// 游戏的每一帧都会调用该方法
}

其中,delta参数表示该方法的上一次调用到目前所经过的游戏时间。
2)仍然是每帧都会调用的更新方法,每个节点只可预定一个update方法,与1)的区别在于使用该方法可以安排更新方法的优先次序。更新方法的调用是按照优先级数值从小到大的次序。示例代码如下:

// 在节点1中
-(void) scheduleUpdates
{[self scheduleUpdate];
}
// 在节点2中
-(void) scheduleUpdates
{
[self scheduleUpdateWithPriority:1];
}
// 在节点3中
-(void) scheduleUpdates
{
[self scheduleUpdateWithPriority:-1];
}
-(void) update:(ccTime)delta
{
// 游戏的每一帧都会调用该方法
}

所有节点(节点1、2、3)都会调用-(void)update: (ccTime) delta方法。但因为使用了优先级设置,将会首先运行节点3的更新方法;然后是调用节点1的更新方法,因为节点1默认优先级设定为0;节点2的更新方法最后调用,因为它的优先级数值最大。
如果每帧都调用相同的更新方法,上述做法很适用。不过有时需要用到更灵活的更新方法。
3)指定运行特定的更新方法,并设置调用的时间间隔。示例代码如下:

-(void) scheduleUpdates{
       [self schedule:@selector(updateTenTimesPerSecond:) interval:0.1f];
}
-(void) updateTenTimesPerSecond:(ccTime)delta
{
//根据时间间隔来调用该方法,每秒10次
}

如果需要每一帧都触发某个方法,应该使用scheduleUpdate方法,并把要定时处理的逻辑放到update方法中。但是update方法只有一个,所以,大部分情况下大家会使用上述代码来触发不同的定时更新逻辑。
4)指定运行特定的更新方法,并设置调用的延迟时间,但只运行一次。示例代码如下:

-(void) scheduleUpdates{
       [self schedule:@selector(specialMethod:) delay:2.0f];
}

5)停止节点的某个指定选择器,但该方法不会停止scheduleUpdate中设置的预定更新方法。想要停止scheduleUpdate中设置的预定更新方法,可以使用unscheduleUpdate方法。示例代码如下:

[self unschedule:@selector(updateTenTimesPerSecond:)];

6)停止节点的所有选择器(selector),包括在scheduleUpdate里设置的update选择器,该方法不会影响节点的动作(action)。示例代码如下:

[self unscheduleAllSelectors];

7)用_cmd关键词停止当前方法的预定。示例代码如下:

-(void) scheduleUpdates
{
       [self schedule:@selector(tenMinutesElapsed:) interval:600];
}
-(void) tenMinutesElapsed:(ccTime)delta
{
// 用_cmd关键词停止当前方法的预定
[self unschedule:_cmd];
}

4 . 其他方法
(1)-(CGRect)boundingBox
该方法用于获取节点的边框,返回的坐标是相对于其父节点的。以points(点值)为单位,返回CGRect变量类型的值。
boundingBox在进行游戏物体碰撞检测时非常有用,功能类似之前定义的rectOfSprite方法。比如,可以把第2章示例游戏中的碰撞检测部分更新为代码清单3-3。
代码清单3-3 碰撞检测代码更新

-(void) collisionDetection:(ccTime)dt{
    CCSprite *enemy;
    CCARRAY_FOREACH(_enemySprites, enemy)
    {
        if (enemy.visible) {
            //1.bullet & enemy collision detection
            if (_bulletSprite.visible && CGRectIntersectsRect(enemy.boundingBox, _bulletSprite.boundingBox)) {
            …//此处省略了部分代码

            //2.enemy & player collision detection
            CCSprite *playerSprite = (CCSprite*)[self getChildByTag:kTagPalyer];
            if (playerSprite.visible &&
               playerSprite.numberOfRunningActions == 0
               && CGRectIntersectsRect(enemy.boundingBox, playerSprite.boundingBox)) {
               …//此处省略了部分代码

            }
        }
    }
}

(2)-(void)cleanup
该方法用于停止所有运行中的动作和预定方法。
(3)-(CGPoint)convertToNodeSpace:(CGPoint)worldPoint
该方法用于将点坐标转换成节点空间坐标。以points(点值)为单位,返回CGPoint变量类型的值。
(4)-(CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint
该方法用于将点坐标转换成相对于锚点的节点空间坐标。以points(点值)为单位,返回CGPoint变量类型的值。
(5)-(CGPoint)convertToWorldSpace:(CGPoint)nodePoint
该方法用于将节点空间坐标转换成世界空间坐标。以points(点值)为单位,返回CGPoint变量类型的值。
(6)-(CGPoint)convertToWorldSpace:(CGPoint)nodePoint
该方法用于将节点空间坐标转换成相对于锚点的世界空间坐标。以points(点值)为单位,返回CGPoint变量类型的值。
注意,第2章的示例游戏中,假如发射子弹的需求有所改变,比如只有玩家“点中”飞机才开始发射子弹,实现方式如代码清单3-4所示。
代码清单3-4 发射子弹实现

-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    //修改为必须点选中playerSprite才能够发射子弹
    //方法1:因为boundingBox是相对于世界坐标系而言的,所以要用
    //self convertTouchToNodeSpace转化成世界坐标系中的坐标
    UITouch *touch = [touches anyObject];
    CCSprite *playerSprite = (CCSprite*)[self getChildByTag:kTagPalyer];
    CGPoint pt;
//    pt = [touch locationInView:[touch view]];
//    pt = [[CCDirector sharedDirector] convertToGL:pt];
//    pt = [self convertToNodeSpace:pt];
    //上面三句调用可以简化为下面一句调用
    //CGPoint pt = [self convertTouchToNodeSpace:touch];
//    if (CGRectContainsPoint(playerSprite.boundingBox, pt)) {
//        _isTouchToShoot = YES;
//    }
    //===================================================================
    //方法2
//    pt = [touch locationInView:[touch view]];
//    pt = [[CCDirector sharedDirector] convertToGL:pt];
//    pt = [playerSprite convertToNodeSpace:pt];
    //简化为下面的一句代码调用
    pt = [playerSprite convertTouchToNodeSpace:touch];
    CCLOG(@"pt.x = %f, pt.y = %f",pt.x, pt.y);

    if (CGRectContainsPoint(playerSprite.textureRect, pt)) {
        _isTouchToShoot = YES;
        CCLOG(@"touched!");
    }

}

大家可以找到本章示例代码,根据代码注释体验4种检测玩家的触摸点是否在playerSprite区域内的方法,相信会对局部坐标和世界坐标有一定的了解,同时明白boundingBox是相对于节点所处的世界坐标来计算的。通过几个小实验,应该已经掌握boundingBox和textureRect的功能与区别。
(7)-(void)draw
覆盖该方法以绘制自己的节点。在Xcode中打开HelloWorldLayer.m,实现draw方法,如代码清单3-5所示。
代码清单3-5 draw方法实现

-(void) draw{
    [super draw];
    ccDrawColor4F(255,0,0,0);
    glLineWidth(8);
    ccDrawLine(ccp(10,10),ccp(200,200));
}

此时编译运行,我们并不能看到这条从(10,10)到(200,200)、红色、宽度为8像素的线。因为程序中添加了背景精灵图片,所以需要把之前添加背景图片的代码注释掉:

//2.add background
//        CCSprite *bgSprite = [CCSprite spriteWithFile:@"background.png"];
//        bgSprite.position = ccp(winSize.width / 2,winSize.height/2);
//        [self addChild:bgSprite z:-100];

编译并运行代码,将会得到如图3-3所示画面。
仔细观察的话大家会发现,在HelloWorldLayer里添加的任何节点,在经过这条红线时都会将红线上的点覆盖。因为Cocos2D的绘制是先调用节点自身的draw,然后再调用它所有子节点的draw方法。

(8)-(id)init
该方法用于初始化节点。
有一点需要注意,我们应该尽量把游戏场景中用到的sprite、label、menu、action、animation等对象在init方法中创建好。如果不想让玩家在进入场景时就看到,可以把些节点的visible属性先设置为NO;在后面需要使用这些预分配的对象时,就可以直接把visbile设置为YES,这样做能提高游戏性能。这种预先分配对象的策略,也叫做lazy loading。第2章示例中的玩家sprite和敌机sprite,以及子弹sprite都采用了这种方式,这种做法有助于提高游戏性能。
(9)- (CGAffineTransform) nodeToParentTransform
该方法返回一个矩阵,可以将节点(本地)空间坐标转换为父节点的空间坐标,该矩阵以像素值为单位。
(10)- (CGAffineTransform) nodeToWorldTransform
该方法返回一个世界坐标的仿射转换矩阵,该矩阵以像素值为单位。
(11)-(void)onEnter
该方法为回调方法,当CCNode节点进入“舞台”时调用。如果进入时带有过渡效果,则在过渡开始时调用。
(12)-(void)onEnterTransitionDidFinish
该方法为回调方法,当CCNode节点进入舞台时调用。如果带有过渡效果,则在过渡完成时调用。
(13)-(void)onExit
该方法为回调方法,当CCNode节点离开舞台时会被调用。如果带有过渡效果,则在过渡完成时调用。
(14)- (void) parentToNodeTransform
该方法返回一个矩阵,可以将父节点的空间坐标转换为节点(本地)空间坐标,该矩阵以像素值为单位。
(15)- (void) pauseSchedulerAndActions
该方法暂停所有预定的选择器方法和动作,由onExit方法在其内部调用。
(16)- (void) reorderChild: (CCNode *) childz:(NSInteger) zOrder
该方法重新设置子节点的次序,该子节点必须已经添加。
(17)- (void) resumeSchedulerAndActions
该方法继续所有预定的选择器方法和动作。该方法由onEnter方法在其内部调用。
(18)- (void) sortAllChildren
使用该方法可以改善游戏性能。该方法在每次绘制前对子节点数组进行排序,除非某个添加的子节点需要在同一帧被清除,不要手动调用该方法。
(19)- (void) transform
该方法根据节点的位置、比例、旋转和其他属性来执行OpenGLES视图–矩阵转换。
(20)- (void) transformAncestors
该方法从其祖先节点执行OpenGLES视图–矩阵转换。
(21)-(void)visit
该方法为递归方法,访问节点的子节点并绘制它们。
(22)- (CGAffineTransform) worldToNodeTransform
该方法返回逆向的世界坐标仿射转换矩阵,以像素值为单位。
以上就是CCNode类的主要方法,详细定义可以查看Cocos2D模板中的CCNode.h文件。

时间: 2024-10-06 10:57:46

《Cocos2D权威指南》——3.2 CCNode节点类的相关文章

《Cocos2D权威指南》——导读

前言 为什么要写这本书 2011年10月5日,秋风萧瑟,阴雨绵绵,在这颗蔚蓝色的美丽星球上,一代传奇伟人乔布斯在亲友的陪伴下安然离去,宛若流星划过天际,空留那辆银色的奔驰SL55AMG在落叶纷飞中孤独守候着曾经的主人.这个世界从此失去了一位引领科技创新的时代领袖. 从1976年在父母的车库中创业开始,乔布斯参与.开创并改变了几个行业-PC.电脑动画.数字音乐.移动互联网.他创办了苹果公司,中途又因某些原因被苹果驱逐.然而在苹果挣扎于濒死的边缘时,他又挺身而出将苹果救活,并把它推到无人可以企及的高

《Cocos2D权威指南》——3.6 CCSprite精灵类

3.6 CCSprite精灵类 CCSprite是Cocos2D游戏开发中最常用的类,用图片把精灵(sprite)显示在屏幕上. 在游戏开发中,经常会遇到精灵(sprite)这个术语.精灵是一个图像,可以在屏幕上独立地移动.一个精灵可能是玩家角色.敌人,或者是大的背景图像.一般情况下,精灵来自于开发者所准备的PNG或PVRTC图像.一旦图像载入内存,就会将精灵转换成纹理图,从而被iPhone GPU用于在屏幕上渲染.3.6.1 CCSprite类的属性及方法 生成精灵的最简单方法是把图片文件加载

《Cocos2D权威指南》——第3章 3.0 Cocos2D核心类

第3章 3.0 Cocos2D核心类 本章主要分析第2章代码示例,同时向大家展示构成Cocos2D的核心类如何组织在一起并构成一个完整的游戏.几乎任何一款Cocos2D游戏中都会用到这些类,所以了解它们的作用.属性和方法,以及如何使用这些类,有助于我们开发出更好的游戏.掌握了这些基本知识,大家会发现Cocos2D并没有想象的那么难:而且即使只用这些类,也可以创造出很有意思的游戏.掌握这些游戏构建的关键类和关键概念之后,我们在开始一个新的游戏项目时会更加得心应手.

《Cocos2D权威指南》——1.4 深入学习HelloCocos2D项目

1.4 深入学习HelloCocos2D项目 在完成了第一个HelloCocos2D项目后,如果读者不仅想看到飞机在屏幕上飞行,还想知道这一切是怎样实现的,我们不妨来一起探究其中的每一行代码.1.4.1 初识场景和节点 要想理解HelloCocos2D这个项目,首先要了解场景(CCScene).层(CCLayer)和节点(CCNode)的概念. Cocos2D游戏是由不同的场景构成的,由导演(CCDirector)负责运行和切换各个场景.在Cocos2D中,CCDirector在任何一个时间点上

《Cocos2D权威指南》——3.4 CCLayer层类

3.4 CCLayer层类 一个CCLayer是屏幕上可绘制的区域,可以是半透明的,这样就可以看到CCScene下面的其他层.在游戏编程的过程中,开发者大部分时间都需要跟层打交道.如图3-5所示,一个游戏场景包含3个层,背景层.动画层和菜单层. CCLayer直接继承自CCNode,作为精灵节点和其他节点的容器,它同时可以接收触摸输入和加速计输入的信息,前提是上述接收功能已经启用.3.4.1 CCLayer类的作用 CCLayer类的作用主要有三个. (1)其他子节点的容器和组织者 例如对一个层

《Cocos2D权威指南》——3.1 Cocos2D节点基础知识

3.1 Cocos2D节点基础知识 在Cocos2D中,CCNode.CCScene和CCLayer这些类是没有视觉呈现的,但它们之间存在一个层级关系.3.1.1 节点层级图 节点层级图是由所有目前活跃的Cocos2D节点组成的一个层级图,又叫场景继承关系图.除了场景本身,每一个节点只有一个父节点,但是可以有任意数量的子节点. 将节点添加到其他节点中时,就在构建节点场景图.图3-1描绘了一个虚拟的游戏场景图,在顶层是一个场景(CCScene)节点,接下来是层(CCLayer)节点. CCLaye

《Cocos2D权威指南》——3.3 CCScene场景类

3.3 CCScene场景类 CCScene是CCNode的子类,和CCNode一样,也是一个抽象类.事实上,CCScene和CCNode几乎完全相同,唯一差异在于CCScene的锚点位置默认在屏幕中心.如果打开模板中CCScene.h文件,大家会发现其中只说明CCScene继承自CCNode,并没有任何其他内容.图3-4是典型的游戏场景跳转示意图.当前版本的Cocos2D中,CCScene类基本上没有附加任何逻辑机制和特殊功能.通常建议将CCScene作为其他所有节点的父节点,看作CCLaye

《Cocos2D权威指南》——3.5 CCTexture纹理类

3.5 CCTexture纹理类 游戏运行中,所有图像文件(PNG.PVR)都被加载成GPU可以理解的OpenGL ES纹理,而精灵则对应着这些纹理图.Cocos2D内置一个纹理缓存管理器(CCTextureCache)来保存这些纹理图,这样可以极大加速创建新精灵,并充分利用已有的纹理图.不利的是,如果收到内存警报,Cocos2D会将当前未使用的纹理图(即引用计数为1的纹理图)全部从内存中清除. 首先我们了解一下和纹理相关的概念.3.5.1 纹理和纹理图集 所有游戏角色都是以图像的形式存储在iP

《Cocos2D权威指南》——3.8 垂直射击游戏—加载游戏数据

3.8 垂直射击游戏-加载游戏数据 为了使大家对CCSprite和各相关类的使用有更加直观的印象,下面我们结合前面的游戏示例,使用精灵表单优化游戏性能,同时在游戏开始和结束时添加菜单,让玩家对游戏有更多控制权.当然,在这个示例小游戏中,这种优化是看不出差别的.但这是最佳实践,建议读者以后编写游戏都以这种方式使用精灵. **3.8.1 注释draw方法和背景 ** 首先,在Xcode中打开之前的项目中把draw方法注释掉,同时恢复先前注释掉的添加游戏背景的代码段,编译并运行,如图3-6所示. 注意