cocos2d 学习 第五章

当你用CCDirector replaceScene方法替换场景时, 每个节点都会调用CCNode所带的三个方法。

这三个方法是:onEnter, onEnterTransitionDidFinish和onExit。 

取决于是否使用了CCTransitionScene, onEnter和onExit会在场景转换过程中的某个时间点被调用。对于这三个方法, 你必须调用它们的super方法以避免触摸输入问题和内存泄漏的问题。 

-(void) onEnter
{

  // 节点调用init方法以后将会调用此方法
  // 如果使用了CCTransitionScene,将会在过渡效果开始以后调用此方法

  [super onEnter];

}

-(void) onEnterTransitionDidFinish
{

    // 调用onEnter以后将会调用此方法
    // 如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法

    [super onEnterTransitionDidFinish];

}
-(void) onExit

    // 节点调用dealloc方法之前将会调用此方法
    // 如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法

    [super onExit]; 


如果你不在onEnter方法里调用它的super方法的话,你的新场景可能不会对触摸或者加速计的输入有任何反应。

如果你不在onExit方法里调用它的super方法,当前场景可能不会从内存里释放。 

你可以在场景转换之前或者之后,通过使用上述方法在节点中完成一些特定的 操作。因为在程序进入onEnter方法的时候,场景中的所有节点都已经设置完成 了;同时,在onExit方法中,所有节点都还存在于内存中。 

1. scene: OtherScene
2. init: 
3. onEnter: 
4. // ......
5. onExit: 
6. onEnterTransitionDidFinish: 

7. dealloc: 

replaceScene -> Other Scene.

===========================================

scene: OtherScene

init: <OtherScene = 0x1835e10 | Tag = -1>

onExit: <FirstScene = 0x436170 | Tag = -1>  // 因为切换到OhterScene时,FirstScene还在内存中,过程是先初始化OhterScene,之后从内存中清空FirstScene

dealloc: <FirstScene = 0x436170 | Tag = -1>

onEnter: <OtherScene = 0x1835e10 | Tag = -1>

onEnterTransitionDidFinish: <OtherScene = 0x1835e10 | Tag = -1>

 

#import <Foundation/Foundation.h>

#import "cocos2d.h"

typedefenum

{

    TargetSceneINVALID = 0,

    TargetSceneFirstScene,

    TargetSceneOtherScene,

    TargetSceneMAX,

}

TargetScenes;

 

@interface LoadingScene : CCScene

{

    TargetScenes targetScene_;

}

+(id)sceneWithTargetScene:(TargetScenes)targetScene;

-(id)initWithTargetScene:(TargetScenes)targetScene;

@end

 

 

#import "LoadingScene.h"

#import "FirstScene.h"

#import "OtherScene.h"

 

@implementation LoadingScene

+(id)sceneWithTargetScene:(TargetScenes)targetScene

{

    return [[[self alloc] initWithTargetScene:targetScene] autorelease];

}

 

-(id)initWithTargetScene:(TargetScenes)targetScene

{

    if((self = [super init]))

    {

        targetScene_ = targetScene;

        CCLabelTTF *label = [CCLabelTTFlabelWithString:@"Loading..."

                                               fontName:@"Marker Felt"

                                               fontSize:64];

        CGSize size = [[CCDirectorsharedDirector] winSize];

        label.position = CGPointMake(size.width*0.5, size.height*0.5);

        [self addChild:label];

        [selfscheduleUpdate];

    }

    returnself;

}

 

-(void)update:(ccTime)delta

{

    [selfunscheduleAllSelectors];

    switch (targetScene_) {

        caseTargetSceneFirstScene:

            [[CCDirectorsharedDirector] replaceScene:[FirstScenescene]];

            break;

        caseTargetSceneOtherScene:

            [[CCDirectorsharedDirector] replaceScene:[OtherScenescene]];

            break;

        default:

            NSAssert2(nil, @"%@:unsupported TargetScene %i", NSStringFromSelector(_cmd), targetScene_);

            break;

    }

}

@end

 

因为 LoadingScene 继承自 CCScene,并且要求传递一个新的参数给它,所以仅 仅调用[CCScene node]是不够的。SceneWithTargetScene 方法首先会完成对 self 的内存分配,然后调用 initWithTargetScene 方法,最后返回一个新的自 动释放对象。 

这里的 init 方法把目标场景储存在一个成员变量里面,接着生成一个 “Loading...”标签,最后运行 scheduleUpdate 这个预约方法。 

为什么我们不在init方法里直接使用replaceScene方法呢?这里有两条规则需要遵守。规则一:永远不要在一个节点的init方法中调用CCDirector的replaceScene方法。

规则二:请遵守规则一。不遵守规则的后果是程序崩溃。Director无法容忍一个节点在初始化的同时进行场景替换。 

在过渡效果中使用LoadingScene可以优化内存的使用:因为你使用了一个简单 的过渡场景用于替换当前场景,然后用最终的目标场景替换这个过渡场景。在 这个替换的过程中,cocos2d将会有足够的时间来释放之前场景所占用的内存。 我们得到的实际效果是:不再会有两个复杂场景同时占用着内存的情况了,因 此在场景转换过程中也就减少了出现内存使用高峰的机会。 

 1 #import <Foundation/Foundation.h>
 2 #import "cocos2d.h"
 3 #import "GameLayer.h"
 4 #import "UserInterfaceLayer.h"
 5 
 6 typedef enum                // 定义二个层的Tag值
 7 {
 8     LayerTagGameLayer,      // 用于标示[游戏层]
 9     LayerTagUILayer,        // 用于标示[用户设置层]
10 } MultiLayerSceneTags;
11 
12 typedef enum                            // 定义动作Tag
13 {
14     ActionTagGameLayerMovesBack,
15     ActionTagGameLayerRotates,
16 } MultiLayerSceneActionTags;
17 
18 @interface MultiLayerScene : CCLayer
19 {
20     bool isToucheForUserInterface;      // 判断用户点击的是否为设置界面
21 }
22 @property (readonly) GameLayer *gameLayer;
23 @property (readonly) UserInterfaceLayer *uiLayer;
24 
25 +(MultiLayerScene *)sharedLayer;
26 +(CGPoint)locationFromTouch:(UITouch *)touch;
27 +(CGPoint)locationFromTouches:(UITouch *)touches;
28 +(id)scene;
29 
30 @end
 1 #import "MultiLayerScene.h"
 2 
 3 @implementation MultiLayerScene
 4 
 5 static MultiLayerScene* multiLayerSceneInstance;    // 定义静态的本场景变量
 6 
 7 +(MultiLayerScene *)sharedLayer     // 返回静态场景变量
 8 {
 9     NSAssert(multiLayerSceneInstance != nil, @"MultiLayerScene not available!");
10     return multiLayerSceneInstance;
11 }
12 
13 #pragma mark 返回游戏层
14 - (GameLayer *)gameLayer
15 {
16     CCNode *layer = [self getChildByTag:LayerTagGameLayer];
17     NSAssert([layer isKindOfClass:[GameLayer class]], @"%@: not a GameLayer!",NSStringFromSelector(_cmd));
18     return (GameLayer *)layer;
19 }
20 
21 #pragma mark 返回用户设置层
22 - (UserInterfaceLayer*)uiLayer
23 {
24     CCNode* layer = [[MultiLayerScene sharedLayer] getChildByTag:LayerTagUILayer];
25     NSAssert([layer isKindOfClass:[UserInterfaceLayer class]], @"%@: not a UserInterfaceLayer!", NSStringFromSelector(_cmd));
26     return (UserInterfaceLayer *)layer;
27 }
28 
29 #pragma mark 得到用户点击的坐标并转换为OpenGL坐标
30 +(CGPoint)locationFromTouch:(UITouch *)touch
31 {
32     // locationInView:函数返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。
33     // 调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置。
34     CGPoint touchLocation = [touch locationInView:[touch view]];
35     
36     // convertToGL:将ios坐标系转换为OpenGL坐标系,返回类型 CGPoint
37     return [[CCDirector sharedDirector] convertToGL:touchLocation];
38 }
39 
40 #pragma mark 如果用户是多点触摸,那么返回其中任意一个触摸点的OpenGL坐标
41 +(CGPoint) locationFromTouches:(NSSet *)touches
42 {
43     return [self locationFromTouch:[touches anyObject]];
44 }
45 
46 #pragma mark - 静态构造方法Scene
47 +(id) scene
48 {
49     CCScene* scene = [CCScene node];
50     MultiLayerScene* layer = [MultiLayerScene node];
51     [scene addChild:layer];
52     return scene;
53 }
54 
55 #pragma mark 初始化方法init
56 -(id) init
57 {
58     if ((self = [super init]))
59     {
60         NSAssert(multiLayerSceneInstance == nil, @"another MultiLayerScene is already in use!");
61         multiLayerSceneInstance = self;
62         
63         GameLayer* gameLayer = [GameLayer node];
64         [self addChild:gameLayer z:1 tag:LayerTagGameLayer];        // 将游戏层加入场景中,Z轴位置为 1,
65         // z:是指添加的ZOrder值,ZOrder是指该成员的层级(也可以说深度),z值大的成员在z值小的成员的上面;
66         
67         UserInterfaceLayer* uiLayer = [UserInterfaceLayer node];    // 将用户设置层加入场景中,Z轴位置为 2
68         [self addChild:uiLayer z:2 tag:LayerTagUILayer];
69     }
70     return self;
71 }
72 
73 -(void) dealloc
74 {
75     CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
76     multiLayerSceneInstance = nil;
77     [super dealloc];
78 }
79 
80 @end
 1 #import <Foundation/Foundation.h>
 2 #import "cocos2d.h"
 3 
 4 #pragma mark 游戏内容层
 5 @interface GameLayer : CCLayer
 6 {
 7     CGPoint gameLayerPosition;
 8     CGPoint lastTouchLocation;
 9 }
10 
11 @end
  1 #import "GameLayer.h"
  2 #import "cocos2d.h"
  3 #import "MultiLayerScene.h"
  4 
  5 @interface GameLayer (PrivateMethod)
  6 -(void)addRandomThings;
  7 @end
  8 
  9 @implementation GameLayer
 10 -(id)init
 11 {
 12     if((self = [super init]))
 13     {
 14         gameLayerPosition = self.position;                                                      // 返回层的默认坐标(0,0)
 15         CGSize screenSize = [[CCDirector sharedDirector] winSize];
 16         CCSprite *background = [CCSprite spriteWithFile:@"grass.png"];                          // 载入“小草”精灵
 17         background.position = CGPointMake(screenSize.width * 0.5, screenSize.height * 0.5);     // 设置小草精灵的位置
 18         [self addChild:background];                                                             // 将小草加入游戏层中
 19         
 20         CCLabelTTF *label = [CCLabelTTF labelWithString:@"GameLayer"
 21                                              fontName:@"Marker Felt"
 22                                                fontSize:44];
 23         label.color = ccBLACK;
 24         label.position = CGPointMake(screenSize.width*0.5, screenSize.height * 0.5);
 25         //label.anchorPoint = CGPointMake(0.5f, 0.5f);
 26         [self addChild:label];                                                                  // 将文字标签加入游戏层
 27         
 28         [self addRandomThings];                                                             
 29         self.isTouchEnabled = YES;                                                              // 支持触屏
 30     }
 31     return self;
 32 }
 33 
 34 #pragma mark 在游戏层添加一些随机物品
 35 -(void)addRandomThings
 36 {
 37     CGSize screenSize = [[CCDirector sharedDirector] winSize];
 38     
 39     for (int i = 0; i<4; i++)                       // 添加4团随机的火元素
 40     {
 41         CCSprite *firething = [CCSprite spriteWithFile:@"firething.png"];
 42         firething.position = CGPointMake(CCRANDOM_0_1()*screenSize.width, CCRANDOM_0_1()*screenSize.height);
 43         [self addChild:firething];                  // 将火元素添加到游戏层中
 44         [self runRandomMoveSequence:firething];     // 随机移动此火元素
 45     }
 46     
 47     for (int i = 0; i<10; i++)                      // 添加10个随机的蜘蛛
 48     {
 49         CCSprite *spider = [CCSprite spriteWithFile:@"spider.png"];
 50         spider.position = CGPointMake(CCRANDOM_0_1()*screenSize.width, CCRANDOM_0_1()*screenSize.height);
 51         [self addChild:spider];
 52         [self runRandomMoveSequence:spider];        // 随机移动此火元素
 53     }
 54 }
 55 -(void) runRandomMoveSequence:(CCNode*)node
 56 {
 57     float duration = CCRANDOM_0_1() * 5 + 1;
 58     
 59     CCMoveBy *move1 = [CCMoveBy actionWithDuration:duration position:CGPointMake(-180, 0)];     // 在现在位置水平左移180个单位
 60     CCMoveBy* move2 = [CCMoveBy actionWithDuration:duration position:CGPointMake(0, -180)];
 61     CCMoveBy* move3 = [CCMoveBy actionWithDuration:duration position:CGPointMake(180, 0)];
 62     CCMoveBy* move4 = [CCMoveBy actionWithDuration:duration position:CGPointMake(0, 180)];
 63     CCSequence *sequence = [CCSequence actions:move1,move2,move3,move4, nil];                   // 定义一个动作执行序列
 64     CCRepeatForever *repeat = [CCRepeatForever actionWithAction:sequence];                      // 该类的作用就是无限期执行某个动作或动作序列,直到被停止
 65     [node runAction:repeat];
 66 }
 67 
 68 #pragma mark 在CCLayer中经常要注册Touch Dispatcher来让Layer处理Touch事件。 Dispatcher:调度员
 69 -(void)registerWithTouchDispatcher
 70 {
 71     // 设置此层可以接受手触发事件,且priority(优先级)为0,越小优先级越高,越先接受用户触摸事件,swallow(是否可以吞没事件)为YES
 72     [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
 73                                                               priority:0
 74                                                        swallowsTouches:YES];
 75 }
 76 
 77 #pragma mark 接受用户触摸事件
 78 -(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
 79 {
 80     CCLOG(@"GameLayer: ccTouchBegan");
 81     lastTouchLocation = [MultiLayerScene locationFromTouch:touch];  // 得到用户触摸开始点OpenGL坐标
 82     [self stopActionByTag:ActionTagGameLayerMovesBack];             // 停止此时可能存在加速动作
 83     return YES;                                                     // 如果是NO,那么就结束触摸事件传递,ccTouchMoved、ccTouchEnded将不执行
 84     
 85 }
 86 
 87 #pragma mark 接受用户滑动事件
 88 -(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
 89 {
 90     CCLOG(@"GameLayer: ccTouchMoved");
 91     CGPoint currentTouchLocaion = [MultiLayerScene locationFromTouch:touch];    // 在移动的过程中得到一系列新的目标点位
 92     CGPoint moveTo = ccpSub(lastTouchLocation, currentTouchLocaion);            // 得到二个点相减后的位置
 93     moveTo = ccpMult(moveTo, -1);                                               // 将moveTo的X,Y 都与-1相乘,得到原点将移动到新点位的值
 94     lastTouchLocation = currentTouchLocaion;                                    // 将现在点位更新为已经使用过的点位
 95     self.position = ccpAdd(self.position, moveTo);                              // 将本层原点向moveTo点位移动
 96 }
 97 
 98 #pragma mark 用户触摸事件结束后,本层内容恢复到原点
 99 -(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
100 {
101     CCLOG(@"GameLayer: ccTouchEnded");
102     CCMoveTo *move = [CCMoveTo actionWithDuration:1 position:gameLayerPosition];        // 返回原点
103     CCEaseIn *ease = [CCEaseIn actionWithAction:move rate:0.5f];                        // 在0.5秒内完成move动作,且开始运行时是加速状态的
104     ease.tag = ActionTagGameLayerMovesBack;                                             // 此加速动作的Tag = ActionTagGameLayerMovesBack
105     [self runAction:ease];
106 }
107 @end
 1 #import <Foundation/Foundation.h>
 2 #import "cocos2d.h"
 3 #pragma mark 用户设置层
 4 
 5 typedef enum
 6 {
 7     UIlayerTagFrameSprite,
 8 } UserInterfaceLayerTags;
 9 
10 @interface UserInterfaceLayer : CCLayer {
11     
12 }
13 -(BOOL) isTouchMe:(CGPoint)touchLocation;
14 @end
 1 #import "UserInterfaceLayer.h"
 2 #import "MultiLayerScene.h"
 3 
 4 @implementation UserInterfaceLayer
 5 -(id)init
 6 {
 7     if((self = [super init]))
 8     {
 9         CGSize screenSize = [[CCDirector sharedDirector] winSize];
10         CCSprite *uiframe = [CCSprite spriteWithFile:@"ui-frame.png"];
11         uiframe.position = CGPointMake(0,screenSize.height);
12         uiframe.anchorPoint = CGPointMake(0, 1);
13         [self addChild:uiframe z:0 tag:UIlayerTagFrameSprite];                  // 设置图片Tag = UIlayerTagFrameSprite
14         
15         CCLabelTTF *label = [CCLabelTTF labelWithString:@"这里可以显示程序积分" fontName:@"Courier" fontSize:22];
16         label.color = ccBLACK;
17         label.position = CGPointMake(screenSize.width * 0.5,screenSize.height);
18         label.anchorPoint = CGPointMake(0.5f, 1);
19         [self addChild:label];
20         self.isTouchEnabled = YES;
21     }
22     return self;
23 }
24 
25 -(void) registerWithTouchDispatcher
26 {
27     [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
28 }
29 -(BOOL)isTouchMe:(CGPoint)touchLocation
30 {
31     CCNode *node = [self getChildByTag:UIlayerTagFrameSprite];              // 查找到tag = UIlayerTagFrameSprite 的精灵对象
32     return CGRectContainsPoint([node boundingBox], touchLocation);          // 判断用户触摸点是否在node之中
33 }
34 
35 #pragma mark 当用户触摸标题栏时,gameLayer进行一系列操作
36 -(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
37 {
38     CGPoint location = [MultiLayerScene locationFromTouch:touch];                       // 得到用户点击的OpenGL坐标
39     bool isTouchHandled = [self isTouchMe:location];                                    // 判断用户点击的是否为UserInteface层
40     if(isTouchHandled)                                                                  // 如果 YES那么事件将被吞没不向下层传递了
41     {
42         CCNode *node = [self getChildByTag:UIlayerTagFrameSprite];
43         NSAssert([node isKindOfClass:[CCSprite class]], @"node is not a CCSprite");
44         ((CCSprite *)node).color = ccRED;                                               // 将UserInterface层显示的字体改为红色
45         
46         CCScaleTo *scaleDown = [CCScaleTo actionWithDuration:2 scale:0];                // 在2秒内缩放为0,消失了
47         CCScaleTo *scaleUp = [CCScaleTo actionWithDuration:2 scale:1];                  // 在2秒内还原为原来大小
48         CCSequence *sequence = [CCSequence actions:scaleDown,scaleUp, nil];             // 定义包括二种缩放方式的动作序列
49         sequence.tag = ActionTagGameLayerRotates;                                       // 将此序列的Tag = ActionTagGameLayerRotates
50         
51         GameLayer *gameLayer = [MultiLayerScene sharedLayer].gameLayer;                 // 得到gameLayer层
52         CCRotateBy *rotate = [CCRotateBy actionWithDuration:4 angle:360];               // 在4秒内旋转360度
53         [gameLayer stopActionByTag:ActionTagGameLayerRotates];                          // 停止可能存在的缩放序列
54         [gameLayer setRotation:0];                                                      // 初始化gameLayer层旋转角度为0
55         [gameLayer setScale:1];                                                         // 初始化gameLayer层缩放比例为1倍,既原始大小
56         [gameLayer runAction:rotate];                                                   // 执行旋转
57         [gameLayer runAction:sequence];                                                 // 执行缩放
58     }
59     return isTouchHandled;
60 }
61 
62 #pragma mark 用户触摸结束后恢复标题字体颜色
63 -(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
64 {
65     CCNode *node = [self getChildByTag:UIlayerTagFrameSprite];
66     NSAssert([node isKindOfClass:[CCSprite class]], @"node is not a CCSprite");
67     ((CCSprite *)node).color = ccWHITE;
68 }
69 
70 -(void)dealloc
71 {
72     CCLOG(@"%@: %@",NSStringFromSelector(_cmd),self);
73     [super dealloc];
74 }
75 @end
 1 #import <Foundation/Foundation.h>
 2 #import "cocos2d.h"
 3 
 4 // CCTargetedTouchDelegate,CCStandardTouchDelegate 协议将使对象支持触摸事件
 5 
 6 @interface Spider : NSObject <CCTargetedTouchDelegate>  
 7 {
 8     CCSprite *spiderSprite;         // 蜘蛛对象中有一个精灵对象
 9     int numUpdates;
10 }
11 
12 +(id)spiderWithParentNode:(CCNode *)parentNode;
13 -(id)initWithParentNode:(CCNode *)parentNode;
14 @end
 1 #import "Spider.h"
 2 #import "MultiLayerScene.h"
 3 
 4 @implementation Spider
 5 
 6 #pragma mark 一个像 CCNode类一样的静态自动释放的初始化方法。这是在模仿 cocos2d 的内存管理方式。
 7 +(id)spiderWithParentNode:(CCNode *)parentNode
 8 {
 9     return [[[self alloc] initWithParentNode:parentNode] autorelease];
10 }
11 
12 -(id)initWithParentNode:(CCNode *)parentNode
13 {
14     if((self = [super init]))
15     {
16         CGSize screenSize = [[CCDirector sharedDirector] winSize];
17         spiderSprite = [CCSprite spriteWithFile:@"spider.png"];
18         spiderSprite.position = CGPointMake(CCRANDOM_0_1()*screenSize.width,CCRANDOM_0_1()*screenSize.height);
19         [parentNode addChild:spiderSprite]; // 将预定好随机位置的蜘蛛加入到制定的节点对象(CCNode *)中
20         
21         // 自定义使用CCSchedule类手动预约更新方法
22         [[[CCDirector sharedDirector] scheduler] scheduleUpdateForTarget:self
23                                                                 priority:0
24                                                                   paused:NO];
25         // 让这个类可以接收定向的触摸事件
26         [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
27                                                                   priority:-1 swallowsTouches:YES];
28     }
29     return self;
30 }
31 
32 -(void)update:(ccTime)delta
33 {
34     numUpdates ++;
35     /*if(numUpdates > 50)
36     {
37         numUpdates = 0;
38         [spiderSprite stopAllActions];
39         CGPoint moveTo = CGPointMake(CCRANDOM_0_1()*200-100,CCRANDOM_0_1()*100 - 50);
40         CCMoveBy *move = [CCMoveBy actionWithDuration:1 position:moveTo];
41         [spiderSprite runAction:move];
42     }*/
43     if(numUpdates > 50)
44     {
45         numUpdates = 0;
46         CGPoint moveTo = CGPointMake(CCRANDOM_0_1()*200-100,CCRANDOM_0_1()*100 - 50);
47         [self moveAway:2 postion:moveTo];
48     }
49 }
50 
51 -(void)moveAway:(float)duration postion:(CGPoint)moveTo
52 {
53     [spiderSprite stopAllActions];
54     CCMoveBy *move = [CCMoveBy actionWithDuration:duration position:moveTo];
55     [spiderSprite runAction:move];
56 }
57 
58 - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
59 {
60     // CCLOG(@"Spride ccTouchBegan");
61     CGPoint touchLocaion = [MultiLayerScene locationFromTouch:touch];
62     BOOL isTouchHandled = CGRectContainsPoint([spiderSprite boundingBox], touchLocaion);
63     if(isTouchHandled)
64     {
65         numUpdates = 0;
66         CGPoint moveTo;
67         float moveDistance = 60;
68         float rand = CCRANDOM_0_1();
69         if(rand < 0.25f)
70         {
71             moveTo = CGPointMake(moveDistance, moveDistance);
72         }
73         else if (rand < 0.5f)
74         {
75             moveTo = CGPointMake(-moveDistance, moveDistance);
76         }
77         else if (rand <0.75f)
78         {
79             moveTo = CGPointMake(moveDistance, -moveDistance);
80         }
81         else
82         {
83             moveTo = CGPointMake(-moveDistance, -moveDistance);
84         }
85         [self moveAway:0.1f postion:moveTo];
86     }
87     return isTouchHandled;
88 }
89 
90 -(void)dealloc
91 {
92     // scheduler要求在dealloc方法中手动解除预约的更新方法
93     [[[CCDirector sharedDirector] scheduler] unscheduleUpdateForTarget:self];
94     
95     // CCTouchDispatcher(触摸调度程序) 也需要在dealloc方法中被移除。
96     [[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self];
97     [super dealloc];
98 }
原文地址:https://www.cnblogs.com/sell/p/2856649.html