Archive for the '全部' Category
我收藏的科技博客
星期一, 一月 16th, 2012http://thenextweb.com/
密码保护:近期发展计划
星期日, 一月 15th, 2012密码保护:某日与麦总的倾谈
星期一, 一月 9th, 2012jQuery plugin
星期四, 九月 22nd, 2011http://docs.jquery.com/Plugins/Authoring
SVSegmentedControl
星期日, 七月 24th, 2011https://github.com/samvermette/SVSegmentedControl
测试ifttt
星期三, 六月 29th, 2011如题
HOW TO – 申请ios developer program license
星期四, 六月 16th, 2011cocos2d 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, 2011Scene显示或被替换的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]; } |