Archive for the '全部' Category

密码保护:关于最近的一点想法

星期二, 一月 17th, 2012

这是一篇受密码保护的文章。您需要提供访问密码:


我收藏的科技博客

星期一, 一月 16th, 2012

http://thenextweb.com/

密码保护:近期发展计划

星期日, 一月 15th, 2012

这是一篇受密码保护的文章。您需要提供访问密码:


密码保护:某日与麦总的倾谈

星期一, 一月 9th, 2012

这是一篇受密码保护的文章。您需要提供访问密码:


jQuery plugin

星期四, 九月 22nd, 2011

http://docs.jquery.com/Plugins/Authoring

SVSegmentedControl

星期日, 七月 24th, 2011

https://github.com/samvermette/SVSegmentedControl

测试ifttt

星期三, 六月 29th, 2011

如题

HOW TO – 申请ios developer program license

星期四, 六月 16th, 2011

http://www.cocoachina.com/bbs/read.php?tid-13372.html

cocos2d notes(5)

星期三, 六月 15th, 2011

粒子效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    [self removeChildByTag:1 cleanup:YES];
   
    CCParticleSystem* system;
   
    switch (particleType)
    {
        case ParticleTypeExplosion:
            system = [CCParticleExplosion node];
            break;
        case ParticleTypeFire:
            system = [CCParticleFire node];
            break;
        case ParticleTypeFireworks:
            system = [CCParticleFireworks node];
            break;
        case ParticleTypeFlower:
            system = [CCParticleFlower node];
            break;
        case ParticleTypeGalaxy:
            system = [CCParticleGalaxy node];
            break;
        case ParticleTypeMeteor:
            system = [CCParticleMeteor node];
            break;
        case ParticleTypeRain:
            system = [CCParticleRain node];
            break;
        case ParticleTypeSmoke:
            system = [CCParticleSmoke node];
            break;
        case ParticleTypeSnow:
            system = [CCParticleSnow node];
            break;
        case ParticleTypeSpiral:
            system = [CCParticleSpiral node];
            break;
        case ParticleTypeSun:
            system = [CCParticleSun node];
            break;
           
        default:
            // do nothing
            break;
    }

    [self addChild:system z:1 tag:1];

自定义粒子效果

1
2
3
4
5
6
7
8
#import <Foundation/Foundation.h>
#import "cocos2d.h"
// Depending on the targeted device the ParticleEffectSelfMade class will either derive
// from CCPointParticleSystem or CCQuadParticleSystem
@interface ParticleEffectSelfMade : ARCH_OPTIMAL_PARTICLE_SYSTEM
{
}
@end

ARCH_OPTIMAL_PARTICLE_SYSTEM宏将自动判断使用效率较高的父类(CCPointParticleSystem or CCQuadParticleSystem)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#import "ParticleEffectSelfMade.h"


@implementation ParticleEffectSelfMade

-(id) init
{
    return [self initWithTotalParticles:250];
}

-(id) initWithTotalParticles:(int)numParticles
{
    if ((self = [super initWithTotalParticles:numParticles]))
    {
        // DURATION
        // most effects use infinite duration
        self.duration = kCCParticleDurationInfinity;
        // for timed effects use a number in seconds how long particles should be emitted
        //self.duration = 2.0f;
        // If the particle system runs for a fixed time, this will remove the particle system node from
        // its parent once all particles have died. Has no effect for infinite particle systems.
        self.autoRemoveOnFinish = YES;

        // MODE
        // particles are affected by gravity
        self.emitterMode = kCCParticleModeGravity;
        // particles move in a circle instead
        //self.emitterMode = kCCParticleModeRadius;
       
        // some properties must only be used with a specific emitterMode!
        if (self.emitterMode == kCCParticleModeGravity)
        {
            // centerOfGravity is misleading as it determines the offset where particles appear. The actual
            // center of gravity is the node's position.
            self.centerOfGravity = CGPointMake(-15, 0);
            // gravity determines the particle's speed in the x and y directions
            self.gravity = CGPointMake(-50, -90);
            // radial acceleration affects how fast particles move depending on their distance to the emitter
            // positive radialAccel means particles speed up as they move away, negative means they slow down
            self.radialAccel = -90;
            self.radialAccelVar = 20;
            // tangential acceleration lets particles rotate around the emitter position,
            // and they speed up as they rotate around (slingshot effect)
            self.tangentialAccel = 120;
            self.tangentialAccelVar = 10;
            // speed is of course how fast particles move in general
            self.speed = 15;
            self.speedVar = 4;
        }
        else if (self.emitterMode == kCCParticleModeRadius)
        {
            // the distance from the emitter position that particles will be spawned and sent out
            // in a radial (circular) fashion
            self.startRadius = 100;
            self.startRadiusVar = 0;
            // the end radius the particles move towards, if less than startRadius particles will move
            // inwards, if greater than startRadius particles will move outward
            // you can use the keyword kCCParticleStartRadiusEqualToEndRadius to create a perfectly circular rotation
            self.endRadius = 10;
            self.endRadiusVar = 0;
            // how fast the particles rotate around
            self.rotatePerSecond = 180;
            self.rotatePerSecondVar = 0;
        }

        // EMITTER POSITION
        // emitter position is at the center of the node (default)
        // this is where new particles will appear
        self.position = CGPointZero;
        self.posVar = CGPointZero;
        // The positionType determines if existing particles should be repositioned when the node is moving
        // (kCCPositionTypeGrouped) or if the particles should remain where they are (kCCPositionTypeFree).
        self.positionType = kCCPositionTypeFree;
       
        // PARTICLE SIZE
        // size of individual particles in pixels
        self.startSize = 40.0f;
        self.startSizeVar = 0.0f;
        self.endSize = kCCParticleStartSizeEqualToEndSize;
        self.endSizeVar = 0;

        // ANGLE (DIRECTION)
        // the direction in which particles are emitted, 0 means upwards
        self.angle = 0;
        self.angleVar = 0;
       
        // PARTICLE LIFETIME
        // how long each individual particle will "life" (eg. stay on screen)
        self.life = 5.0f;
        self.lifeVar = 0.0f;
       
        // PARTICLE EMISSION RATE
        // how many particles per second are created (emitted)
        // particle creation stops if self.particleCount >= self.totalParticles
        // you can use this to create short burst effects with pauses between each burst
        self.emissionRate = 30;
        // normally set with initWithTotalParticles but you can change that number
        self.totalParticles = 250;

        // PARTICLE COLOR
        // A valid startColor must be set! Otherwise the particles may be invisible. The other colors are optional.
        // These colors determine the color of the particle at the start and the end of its lifetime.
        startColor.r = 1.0f;
        startColor.g = 0.25f;
        startColor.b = 0.12f;
        startColor.a = 1.0f;

        startColorVar.r = 0.0f;
        startColorVar.g = 0.0f;
        startColorVar.b = 0.0f;
        startColorVar.a = 0.0f;
       
        endColor.r = 0.0f;
        endColor.g = 0.0f;
        endColor.b = 0.0f;
        endColor.a = 1.0f;
       
        endColorVar.r = 0.0f;
        endColorVar.g = 0.0f;
        endColorVar.b = 1.0f;
        endColorVar.a = 0.0f;
       
        // BLEND FUNC
        // blend func influences how transparent colors are calculated
        // the first parameter is for the source, the second for the target
        // available blend func parameters are:
        // GL_ZERO   GL_ONE   GL_SRC_COLOR   GL_ONE_MINUS_SRC_COLOR   GL_SRC_ALPHA
        // GL_ONE_MINUS_SRC_ALPHA   GL_DST_ALPHA   GL_ONE_MINUS_DST_ALPHA
        self.blendFunc = (ccBlendFunc){GL_SRC_ALPHA, GL_DST_ALPHA};
        // shortcut to set the blend func to: GL_SRC_ALPHA, GL_ONE
        //self.blendAdditive = YES;
       
        // PARTICLE TEXTURE
        self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"];
    }
   
    return self;
}

@end

粒子设计工具
http://particledesigner.71squared.com/ 下载ParticleDesigner

使用ParticleDesigner生成的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
-(void) runEffect
{
    // remove any previous particle FX
    [self removeChildByTag:1 cleanup:YES];
   
    CCParticleSystem* system;
   
    switch (particleType)
    {
        case ParticleTypeDesignedFX:
            // by using ARCH_OPTIMAL_PARTICLE_SYSTEM either the CCQuadParticleSystem or CCPointParticleSystem class is
            // used depending on the current target.
            system = [ARCH_OPTIMAL_PARTICLE_SYSTEM particleWithFile:@"designed-fx.plist"];
            break;
        case ParticleTypeDesignedFX2:
            // uses a plist with the texture already embedded
            system = [CCQuadParticleSystem particleWithFile:@"designed-fx2.plist"];
            system.positionType = kCCPositionTypeFree;
            break;
        case ParticleTypeDesignedFX3:
            // same effect but different texture (scaled down by Particle Designer)
            system = [CCQuadParticleSystem particleWithFile:@"designed-fx3.plist"];
            system.positionType = kCCPositionTypeFree;
            break;
        case ParticleTypeSelfMade:
            system = [ParticleEffectSelfMade node];
            break;
       
        default:
            // do nothing
            break;
    }

    CGSize winSize = [[CCDirector sharedDirector] winSize];
    system.position = CGPointMake(winSize.width / 2, winSize.height / 2);
    [self addChild:system z:1 tag:1];
   
    [label setString:NSStringFromClass([system class])];
}

在之前的射击游戏中加入爆炸粒子效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-(void) gotHit
{
    hitPoints--;
    if (hitPoints <= 0)
    {
        self.visible = NO;
       
        // Play a particle effect when the enemy was destroyed
        CCParticleSystem* system;
        if (type == EnemyTypeBoss)
        {
            system = [ARCH_OPTIMAL_PARTICLE_SYSTEM particleWithFile:@"fx-explosion2.plist"];
        }
        else
        {
            system = [ARCH_OPTIMAL_PARTICLE_SYSTEM particleWithFile:@"fx-explosion.plist"];
        }
       
        // Set some parameters that can't be set in Particle Designer
        system.positionType = kCCPositionTypeFree;
        system.autoRemoveOnFinish = YES;
        system.position = self.position;
       
        // Add the particle effect to the GameScene, for these reasons:
        // - self is a sprite added to a spritebatch and will only allow CCSprite nodes (it crashes if you try)
        // - self is now invisible which might affect rendering of the particle effect
        // - since the particle effects are short lived, there is no harm done by adding them directly to the GameScene
        [[GameScene sharedGameScene] addChild:system];
    }
}

Cocos2d notes(3)

星期日, 六月 12th, 2011

Scene显示或被替换的3个重要事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-(void) onEnter
{
        // Called right after a node’s init method is called.
        // If using a CCTransitionScene: called when the transition begins.
        [super onEnter];
}
-(void) onEnterTransitionDidFinish
{
        // Called right after onEnter.
        // If using a CCTransitionScene: called when the transition has ended.
        [super onEnterTransitionDidFinish];
}
-(void) onExit
{
        // Called right before node’s dealloc method is called.
        // If using a CCTransitionScene: called when the transition has ended.
        [super onExit];
}

Scene替换时发生的事件顺序

1
2
3
4
5
6
7
2011-06-12 19:35:39.374 ScenesAndLayers[21353:207] ===========================================
2011-06-12 19:35:39.375 ScenesAndLayers[21353:207] scene: OtherScene
2011-06-12 19:35:39.375 ScenesAndLayers[21353:207] init: <OtherScene = 06465B40 | Tag = -1>
2011-06-12 19:35:44.743 ScenesAndLayers[21353:207] onEnter: <OtherScene = 06465B40 | Tag = -1>
2011-06-12 19:35:47.760 ScenesAndLayers[21353:207] onExit: <FirstScene = 0783AD30 | Tag = -1>
2011-06-12 19:35:47.761 ScenesAndLayers[21353:207] onEnterTransitionDidFinish: <OtherScene = 06465B40 | Tag = -1>
2011-06-12 19:35:47.761 ScenesAndLayers[21353:207] dealloc: <FirstScene = 0783AD30 | Tag = -1>

由此可知,在init后才发生onEnter,如果init初始化数据较多,就会导致画面tingdun,所以要加入loading scene

一个范例方法
LoadScene.h

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef enum
{
        TargetSceneINVALID = 0,
        TargetSceneFirstScene,
        TargetSceneOtherScene,
        TargetSceneMAX,
} TargetScenes;
 
// LoadingScene is derived directly from Scene. We don't need a CCLayer for this scene.
@interface LoadingScene : CCScene
{
        TargetScenes targetScene_;
}

LoadScene.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
+(id) sceneWithTargetScene:(TargetScenes)targetScene;
{
        // This creates an autorelease object of the current class (self ==  
LoadingScene)
        return [[[self alloc] initWithTargetScene:targetScene] autorelease];
}
 
-(id) initWithTargetScene:(TargetScenes)targetScene
{
        if ((self = [super init]))
        {
                targetScene_ = targetScene;
 
                CCLabel* label = [CCLabel 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!
                [self scheduleUpdate];
        }
 
        return self;
}
 
-(void) update:(ccTime)delta
{
        [self unscheduleAllSelectors];
 
        // Decide which scene to load based on the TargetScenes enum.
        switch (targetScene_)
        {
                case TargetSceneFirstScene:
                        [[CCDirector sharedDirector] replaceScene:[FirstScene scene]];
                        break;
                case TargetSceneOtherScene:
                        [[CCDirector sharedDirector] replaceScene:[OtherScene scene]];
                        break;
 
                default:
                        // Always warn if an unspecified enum value was used
                        NSAssert2(nil, @"%@: unsupported TargetScene %i",  
                                              NSStringFromSelector(_cmd), targetScene_);
                        break;
        }
}

为什么不能在LoadScene 的init方法中直接调用replaceScene
原因1:永远不要在node的init中调用CCDirector的replaceScene方法
原因2:这样调用会让app崩溃,因为无法在初始化(init)一个node的同时replace掉它

Singleton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
+(MultiLayerScene*) sharedLayer
{
        NSAssert(multiLayerSceneInstance != nil, @"MultiLayerScene not available!");
        return multiLayerSceneInstance;
}
 
-(void) dealloc
{
        // MultiLayerScene will be deallocated now, you must set it to nil
        multiLayerSceneInstance = nil;
 
        // don't forget to call "super dealloc"
        [super dealloc];
}

当一个Scene上有两个层重叠,如何判断哪个层接收touch事件
假设UserInterfaceLayer* uiLayer 在GameLayer* gameLayer之上
UserInterfacelayer.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
-(void) registerWithTouchDispatcher
{
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
}

// Implements logic to check if the touch location was in an area that this layer wants to handle as input.
-(bool) isTouchForMe:(CGPoint)touchLocation
{
    CCNode* node = [self getChildByTag:UILayerTagFrameSprite];
    return CGRectContainsPoint([node boundingBox], touchLocation);
}

-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event
{
    CGPoint location = [MultiLayerScene locationFromTouch:touch];
    bool isTouchHandled = [self isTouchForMe:location];
    if (isTouchHandled)
    {
        // Simply highlight the UI layer's sprite to show that it received the touch.
        CCNode* node = [self getChildByTag:UILayerTagFrameSprite];
        NSAssert([node isKindOfClass:[CCSprite class]], @"node is not a CCSprite");
       
        ((CCSprite*)node).color = ccRED;
        // 省略
    }

    return isTouchHandled;
}

-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event
{
    CCNode* node = [self getChildByTag:UILayerTagFrameSprite];
    NSAssert([node isKindOfClass:[CCSprite class]], @"node is not a CCSprite");
   
    ((CCSprite*)node).color = ccWHITE;
}

在registerWithTouchDispatcher中将自己获取touch的优先级设为最高,然后在-(BOOL) ccTouchBegan:withEvent:中如果返回YES,这次的touch将被uiLayer吞掉(swallow),如果返回NO,则由gameLayer继续处理。

使用CCMultiplexLayer在不同Layer间切换

1
2
3
4
5
6
7
8
CCLayer* layer1 = [CCLayer node];
CCLayer* layer2 = [CCLayer node];
CCMultiplexLayer* mpLayer = [CCMultiplexLayer layerWithLayers:layer1, layer2, nil];
// Switches to layer2 but keeps layer1 as child of mpLayer.
[mpLayer switchTo:1];
// Switches to layer1, removes layer2 from mpLayer and releases its memory.
// After this call you must not switch back to layer2 (index: 1) anymore!
[mpLayer switchToAndReleaseMe:0];

CCColorLayer

1
2
3
// Set background color to magenta. The most unobtrusive color imaginable.
CCColorLayer* colorLayer = [CCColorLayer layerWithColor:ccc4(255, 0, 255, 255)];
[self addChild:colorLayer z:0];

Sprite Class

Spider.h

1
2
3
4
5
6
7
8
9
@interface Spider : NSObject
{
        CCSprite* spiderSprite;
}
 
+(id) spiderWithParentNode:(CCNode*)parentNode;
-(id) initWithParentNode:(CCNode*)parentNode;
 
@end

Spider.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "Spider.h"
 
@implementation Spider
 
// Static autorelease initializer, mimics cocos2d's memory allocation scheme.
+(id) spiderWithParentNode:(CCNode*)parentNode
{
        return [[[self alloc] initWithParentNode:parentNode] autorelease];
}
 
-(id) initWithParentNode:(CCNode*)parentNode
{
        if ((self = [super init]))
        {
                CGSize screenSize = [[CCDirector sharedDirector] winSize];
 
                spiderSprite = [CCSprite spriteWithFile:@"spider.png"];
                spiderSprite.position = CGPointMake(CCRANDOM_0_1() *  
                                  screenSize.width, CCRANDOM_0_1() * screenSize.height);
                [parentNode addChild:spiderSprite];
 
                // Manually schedule update via the undocumented CCScheduler class.
                [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:0  
                                                                             paused:NO];
        }
 
        return self;
}
 
-(void) dealloc
{
        // Must manually unschedule, it is not done automatically.
        [[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self];
 
        [super dealloc];
}

通过注册CCScheduler的 scheduleUpdateForTarget:priority:方法
使Spider每帧调用update:方法

让Spider类实现CCTargetedTouchDelegate协议,使Spider类接收touch
@interface Spider : NSObject
{

}
修改后的Spider.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
-(id) initWithParentNode:(CCNode*)parentNode
{
        if ((self = [super init]))
        {
                …
                // Manually schedule update via the undocumented CCScheduler class.
                [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:0  
                                                                             paused:NO];
 
                // Manually add this class as receiver of targeted touch events.
                [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self  
                                                       priority:-1 swallowsTouches:YES];
        }
 
        return self;
}
 
-(void) dealloc
{
        // Must manually unschedule, it is not done automatically!
        [[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self];
 
        // Must manually remove this class as touch input receiver!
        [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
 
        [super dealloc];
}
 
// Extract common logic into a separate method accepting parameters.
-(void) moveAway:(float)duration position:(CGPoint)moveTo
{
        [spiderSprite stopAllActions];
        CCMoveBy* move = [CCMoveBy actionWithDuration:duration position:moveTo];
        [spiderSprite runAction:move];
}
 
-(void) update:(ccTime)delta
{
        numUpdates++;
        if (numUpdates > 50)
        {
                numUpdates = 0;
 
                // Move at regular speed.
                CGPoint moveTo = CGPointMake(CCRANDOM_0_1() * 200 - 100,  
                                                             CCRANDOM_0_1() * 100 - 50);
                [self moveAway:2 position:moveTo];
        }
}
 
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
        // Check if this touch is on the Spider's sprite.
        CGPoint touchLocation = [MultiLayerScene locationFromTouch:touch];
        BOOL isTouchHandled = CGRectContainsPoint([spiderSprite boundingBox],  
                                                                         touchLocation);
        if (isTouchHandled)
        {
               // Reset move counter.
                numUpdates = 0;
 
                // Move away from touch loation rapidly.
                CGPoint moveTo;
                float moveDistance = 60;
                float rand = CCRANDOM_0_1();
 
                // Randomly pick one of four corners to move away to.
                if (rand < 0.25f)
                        moveTo = CGPointMake(moveDistance, moveDistance);
                else if (rand < 0.5f)
                        moveTo = CGPointMake(-moveDistance, moveDistance);
                else if (rand < 0.75f)
                        moveTo = CGPointMake(moveDistance, -moveDistance);
                else
                        moveTo = CGPointMake(-moveDistance, -moveDistance);
                 
                // Move quickly:
                [self moveAway:0.1f position:moveTo];
        }
 
        return isTouchHandled;
}

CCProgressTimer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Progress timer is a sprite only partially displayed to visualize some kind of progress.
CCProgressTimer* timer = [CCProgressTimer progressWithFile:@"firething.png"];
timer.type = kCCProgressTimerTypeRadialCCW;
timer.percentage = 0;
[self addChild:timer z:1 tag:UILayerTagProgressTimer];
// The update is needed for the progress timer.
[self scheduleUpdate];

-(void) update:(ccTime)delta
{
    CCNode* node = [self getChildByTag:UILayerTagProgressTimer];
    NSAssert([node isKindOfClass:[CCProgressTimer class]], @"node is not a CCProgressTimer");
    // Updates the progress timer
    CCProgressTimer* timer = (CCProgressTimer*)node;
    timer.percentage += delta * 10;
    if (timer.percentage >= 100)
    {
        timer.percentage = 0;
    }
}

CCParallaxNode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Load the sprites for each parallax layer, from background to foreground.
CCSprite* para1 = [CCSprite spriteWithFile:@"parallax1.png"];
CCSprite* para2 = [CCSprite spriteWithFile:@"parallax2.png"];
CCSprite* para3 = [CCSprite spriteWithFile:@"parallax3.png"];
CCSprite* para4 = [CCSprite spriteWithFile:@"parallax4.png"];
// Set the correct offsets depending on the screen and image sizes.
para1.anchorPoint = CGPointMake(0, 1);
para2.anchorPoint = CGPointMake(0, 1);
para3.anchorPoint = CGPointMake(0, 0.6f);
para4.anchorPoint = CGPointMake(0, 0);
CGPoint topOffset = CGPointMake(0, screenSize.height);
CGPoint midOffset = CGPointMake(0, screenSize.height / 2);
CGPoint downOffset = CGPointZero;
// Create a parallax node and add the sprites to it.
CCParallaxNode* paraNode = [CCParallaxNode node];
[paraNode addChild:para1 z:1 parallaxRatio:CGPointMake(0.5f, 0) positionOffset:topOffset];
[paraNode addChild:para2 z:2 parallaxRatio:CGPointMake(1, 0) positionOffset:topOffset];
[paraNode addChild:para3 z:4 parallaxRatio:CGPointMake(2, 0) positionOffset:midOffset];
[paraNode addChild:para4 z:3 parallaxRatio:CGPointMake(3, 0) positionOffset:downOffset];
[self addChild:paraNode z:0 tag:ParallaxSceneTagParallaxNode];
// Move the parallax node to show the parallaxing effect.
CCMoveBy* move1 = [CCMoveBy actionWithDuration:5 position:CGPointMake(-160, 0)];
CCMoveBy* move2 = [CCMoveBy actionWithDuration:15 position:CGPointMake(160, 0)];
CCSequence* sequence = [CCSequence actions:move1, move2, nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequence];
[paraNode runAction:repeat];

CCRibbon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
-(void) resetRibbon
{
    // Removes the ribbon and creates a new one.
    [self removeChildByTag:ParallaxSceneTagRibbon cleanup:YES];
    CCRibbon* ribbon = [CCRibbon ribbonWithWidth:32 image:@"spider.png" length:32 color:ccc4(255, 255, 255, 255) fade:0.5f];
    [self addChild:ribbon z:5 tag:ParallaxSceneTagRibbon];
}

-(CCRibbon*) getRibbon
{
    CCNode* node = [self getChildByTag:ParallaxSceneTagRibbon];
    NSAssert([node isKindOfClass:[CCRibbon class]], @"node is not a CCRibbon");
    return (CCRibbon*)node;
}

-(void) addRibbonPoint:(CGPoint)point
{
    CCRibbon* ribbon = [self getRibbon];
    [ribbon addPointAt:point width:32];
}

-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event
{
    [self addRibbonPoint:[MultiLayerScene locationFromTouch:touch]];
    return YES;
}

-(void) ccTouchMoved:(UITouch*)touch withEvent:(UIEvent *)event
{
    [self addRibbonPoint:[MultiLayerScene locationFromTouch:touch]];
}

-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event
{
    [self resetRibbon];
}

CCMotionStreak
用来替换CCRibbon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-(void) resetMotionStreak
{
    // Removes the CCMotionStreak and creates a new one.
    [self removeChildByTag:ParallaxSceneTagRibbon cleanup:YES];
        CCMotionStreak* streak = [CCMotionStreak streakWithFade:0.7f minSeg:10
    image:@"spider.png" width:32 length:32 color:ccc4(255, 0, 255, 255)];
    [self addChild:streak z:5 tag:ParallaxSceneTagRibbon];
}

-(void) addMotionStreakPoint:(CGPoint)point
{
    CCMotionStreak* streak = [self getMotionStreak];
    [streak.ribbon addPointAt:point width:32];
}