2012-06-07 22 views
9

मैं चारों ओर CAEmitterLayer साथ खेल रहा हूँ के लिए फेंकना और मैं कुछ समस्याओं का सामना करना पड़ता है अब :(CAEmitterLayer कैसे थोड़े समय के बार-बार

मैं एक छोटी कण प्रभाव की जरूरत है - एक हिट या विस्फोट की तरह - उदाहरण के लिए एक स्थान पर (तो मेरे पास इस जगह पर छोटा UIView है)। मुझे यह कैसे करना चाहिए?

1, मुझे एक विचार था - emitterLayer को इसके कणों के साथ बनाएं और जीवन को 0 पर सेट करें। और जब मुझे इसकी आवश्यकता हो तो मैंने जीवन समय निर्धारित किया उदाहरण के लिए 1 और थोड़ी देर बाद मैं इसे 0 पर सेट कर सकता हूं - लेकिन यह कुछ भी नहीं कर रहा है :(

2, दूसरा विचार हर बार जब मुझे इसकी आवश्यकता होती है और इसे परतों के उपन्यास के रूप में जोड़ना होता है तो [CAEmitterLayer परत] बनाना था। लेकिन मैं सोच रहा हूं कि जब मैं इसे दो बार उदाहरण के लिए दोहराता हूं तो क्या होता है ... मेरे पास एक जीवित और 9 "मृत" के साथ 10 sublayers है? सामान्य रूप से उत्सर्जित करना बंद कैसे करें? मैंने कुछ समय बाद जीवनकाल को 0 और अन्य चयनकर्ता को लंबे समय तक अंतराल के साथ सेट करने के लिए चयन किया है ... लेकिन यह इतना सुंदर नहीं है क्योंकि मैं इसे प्राप्त करना चाहता हूं :(क्या कोई और "उचित" तरीका है?

मुझे लगता है बहुत से sublayers मेरी दूसरी समस्या से संबंधित है ... मैं सिर्फ एक कण उत्सर्जित करना चाहता हूं। और जब मैं ऐसा करता हूं यह काम करता है। लेकिन कुछ बार यह तीन कणों को छोड़ देता है, कभी-कभी दो ... और यह मुझे इसके बारे में पागल बनाता है। जब मैं emitter को नहीं रोकता यह हर बार कणों की सही संख्या ...

तो सवाल दे रही है ...

कैसे थोड़े समय के लिए कणों फेंकना कैसे उन लोगों के साथ काम करने के लिए -। सेंट की तरह सेशन, माता पिता परत से निकालने के लिए, ... कैसे कणों

का सिर्फ सही संख्या फेंकना

संपादित करें:

emitter = [CAEmitterLayer layer]; 
emitter.emitterPosition = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2); 
emitter.emitterMode = kCAEmitterLayerPoints; 
emitter.emitterShape = kCAEmitterLayerPoint; 
emitter.renderMode  = kCAEmitterLayerOldestFirst; 
emitter.lifetime = 0; 


particle = [CAEmitterCell emitterCell]; 
[particle setName:@"hit"]; 
particle.birthRate  = 1; 
particle.emissionLongitude = 3*M_PI_2;//270deg 
particle.lifetime  = 0.75; 
particle.lifetimeRange  = 0; 
particle.velocity  = 110; 
particle.velocityRange  = 20; 
particle.emissionRange  = M_PI_2;//PI/2 = 90degrees 
particle.yAcceleration  = 200; 
particle.contents  = (id) [[UIImage imageNamed:@"50"] CGImage]; 
particle.scale   = 1.0; 
particle.scaleSpeed  = -0.5; 
particle.alphaSpeed  = -1.0; 

emitter.emitterCells = [NSArray arrayWithObject:particle]; 
[(CAEmitterLayer *)self.view.layer addSublayer: emitter]; 

इस मुझे क्या करना तो विधि में बटन के साथ जुड़ा हुआ:

emitter.lifetime = 1.0; 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.9 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{ 
    emitter.lifetime = 0; 
}); 

संपादित और अपडेट @ डेविड रोन्न्क्विस्ट रवैये में बदलने के बाद

CAEmitterCell *dustCell = [CAEmitterCell emitterCell]; 
[dustCell setBirthRate:1]; 
[dustCell setLifetime:1.5]; 
[dustCell setName:@"dust"]; 
[dustCell setContents:(id) [[UIImage imageNamed:@"smoke"] CGImage]]; 
[dustCell setVelocity:50]; 
[dustCell setEmissionRange:M_PI]; 
// Various configurations for the appearance... 
// This is the only cell with configured scale, 
// color, content, emissionLongitude, etc... 

[emitter setEmitterCells:[NSArray arrayWithObject:dustCell]]; 
[(CAEmitterLayer *)self.view.layer addSublayer:emitter]; 

// After one burst, change the birth rate of the cloud to 0 
// so that there is only one burst per side. 
double delayInSeconds = 0.5; // One cloud will have been created by now, but not two 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 

    [emitter setLifetime:0.0]; 
    [emitter setValue:[NSNumber numberWithFloat:0.0] 
       forKeyPath:@"emitterCells.dust.birthRate"]; 
}); 
+0

आप सेब नमूना कोड को देखा है ([पटाखे ] (http://developer.apple.com/library/mac/#samplecode/Fireworks/Listings/ReadMe_txt.html)) इसके लिए? वे मूल रूप से करते हैं जो आप करने की कोशिश कर रहे हैं (कणों का एक छोटा विस्फोट) –

+0

हाँ, मेरे पास है। लेकिन ऐसा लगता है कि यह छोटा उत्सर्जन करता है। आम तौर पर जागने के बाद एक परत (एमिटर के साथ) दृश्य में जोड़ा जाता है और फिर यह "आतिशबाज़ी" को गोल और गोल करता है। लेकिन स्थिति की कल्पना करें जब आप बटन को टैप करते समय केवल एक आतिशबाजी शुरू करना चाहते हैं। आप वह कैसे करेंगें? यही वही है जो मैं इंगित कर रहा हूं। – D33

उत्तर

9

आप थि कर सकते हैं सबकुछ एक बार कॉन्फ़िगर करके (प्रत्येक बार एक नया एमिटर सेल न जोड़ें) और birthRate से 0 पर सेट करें (कोई कण नहीं बनाया जाएगा)। फिर जब आप अपने कणों को बनाना चाहते हैं तो आप प्रति सेकंड कणों की संख्या में birthRate सेट कर सकते हैं जिन्हें आप बनाना चाहते हैं। एक निश्चित समय के बाद आप birthRate को 0 पर वापस सेट करें ताकि उत्सर्जन बंद हो जाए। इस देरी को करने के लिए आप dispatch_after() जैसे कुछ का उपयोग कर सकते हैं।


मैंने कुछ समय पहले ऐसा कुछ किया और इसे हल किया। निम्नलिखित कणों का एक त्वरित विस्फोट पैदा करेगा। अगली बार जब आप कणों फेंकना चाहते हैं, आप के लिए 1.

CAEmitterCell *dustCell = [[CAEmitterCell alloc] init]; 
[dustCell setBirthRate:7000]; 
[dustCell setLifetime:3.5]; 
// Various configurations for the appearance... 
// This is the only cell with configured scale, 
// color, content, emissionLongitude, etc... 

CAEmitterCell *dustCloud = [CAEmitterCell emitterCell]; 
[dustCloud setBirthRate:1.0]; // Create one cloud every second 
[dustCloud setLifetime:0.06]; // Emit dustCells for 0.06 seconds 
[dustCloud setEmitterCells:[NSArray arrayWithObject:dustCell]]; 
[dustCloud setName:@"cloud"]; // Use this name to change the birthRate later 

[dustEmitter setEmitterPosition:myPositionForDustEmitter]; 
[rightDustEmitter setEmitterCells:[NSArray arrayWithObject:dustCloud]]; 

// After one burst, change the birth rate of the cloud to 0 
// so that there is only one burst per side. 
double delayInSeconds = 0.5; // One cloud will have been created by now, but not two 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { 

    // For some reason, setting the birthRate of the "cloud" to 0 
    // has a strange side effect that when you set it back to 1 all 
    // the missed emissions seems to happen at once during the first 
    // emission and then it goes back to only emitting once per 
    // second. (Thanks D33 for pointing this out). 
    // By instead changing the birthRate of the "dust" particle 
    // to 0 and then back to (in my case) 7000 gives the visual 
    // effect that I'm expecting. I'm not sure why it works 
    // this way but at least this works for me... 
    // NOTE: This is only relevant in case you want to re-use 
    // the emitters for a second emission later on by setting 
    // the birthRate up to a non-zero value. 
    [dustEmitter setValue:[NSNumber numberWithFloat:0.0] 
       forKeyPath:@"emitterCells.cloud.emitterCells.dust.birthRate"]; 
}); 
+0

मैं इसके बारे में थोड़ा हताश हूं। मैंने कोशिश की कि आपने क्या कहा। लेकिन बिना किसी सफलता के। लेकिन थोड़ी सी आगे आगे बढ़ने के साथ। मैं अपने मूल प्रश्न में जोड़े गए कोड में जैसे डीडलोड को देखने में एमिटर बना रहा हूं। यह काफी अच्छी तरह से काम करता है लेकिन देरी के साथ :(जब मैं बटन दबाता हूं, कुछ भी नहीं होता है। और एक सेकंड के बाद यह मुझे वह कण देता है। जब मैं दो बार बटन दबाता हूं तो दूसरी बात होती है :( मैंने पहले ही काम करने की कोशिश की है जन्म के साथ। लेकिन जब मैंने उत्सर्जन शुरू करने के लिए इसे 1 पर सेट किया, तो उसने मुझे एक के बजाय 10 कणों को और अधिक दिया ... – D33

+0

मुझे नहीं पता। अगर प्रेषण_फिर अजीब व्यवहार कर रहा है तो आप अपने एमिटर परत के साथ एक सेल उत्सर्जित कर सकते हैं BirthRate = 1 जो बदले में आपके वास्तविक कोशिकाओं को उत्सर्जित करता है। इस तरह आप अपने कणों को उत्सर्जित करने के लिए बिना किसी गति और कस्टम जीवन समय के साथ एक पक्षियों को उत्सर्जित कर सकते हैं और फिर 0.5 सेकंड के बाद अपना जन्म दिनांक 0 पर सेट कर सकते हैं। इससे आपको एक विस्फोट मिलेगा कण –

+0

एचएम शायद मुझे आपके उत्तर को अच्छी तरह से समझ में नहीं आया। लेकिन मुझे प्रेषण (मुझे लगता है) में समस्या नहीं है। यह कुछ डेला के बाद उत्सर्जित करना शुरू कर रहा है वाई और मुझे नहीं पता क्यों। मुझे लगता है कि यह कुछ ऐसा है जब मैं एमिटर लेयर बनाता हूं, यह टाइमर चलने लगता है। और जब मैं उस समय तक जीवन भर बदलता हूं, तो यह अभी भी मौजूदा चलने वाले टाइमर के साथ काम कर रहा है। इसलिए यह तुरंत उत्सर्जित नहीं हो रहा है लेकिन सही समय आने पर ... और यह मुझे देरी देता है। हम्म। कोई विचार यह कैसे बचें? – D33

0

ठीक है, "बादल" की जन्मदर को बदलने वापस अंत में, परीक्षण के घंटे और बहुत अलग शैलियों की कोशिश कर रहा (आरंभ के बाद, हटाने, को विन्यस्त उत्सर्जक) मैं अंतिम परिणाम के साथ आया ... और वास्तव में यह मुझे बहुत परेशान करता है ...

--- यह संभव नहीं है!---

यहां तक ​​कि जब भी मैं एमिटर और उसके कणों को हर बार बनाता हूं, मुझे इसकी आवश्यकता होती है, अगर मैं उत्सर्जित करने के लिए केवल एक कण सेट करता हूं, तो यह मुझे सबसे अधिक समय एक कण देता है ... लेकिन यह 100% नहीं है और कभी-कभी यह तीन कणों, या दो उत्सर्जित करता है ... यह यादृच्छिक है। और वह बहुत बुरा है। क्योंकि यह दृश्य प्रभाव है ... किसी को यह कैसे हल करने के लिए एक टिप है :(

किसी भी तरह से करते हैं, तो कृपया मुझे बताएं ...

5

मैं भी एक समाधान के लिए देख रहा था और इस article पाया। । कॉन्फ़ेटी कण के लिए इस Gist, और इसके Stop Emitting विधि पर

नज़र

यह क्या करता है यह है:

  1. अपने प्रदर्शन दृश्य में कण दृश्य जोड़ें।
  2. जब तक आप चाहते हैं कण चलें।
  3. confettiEmitter.birthRate = 0.0; के साथ नए कणों के उत्सर्जन को रोकें।
  4. कुछ सेकंड प्रतीक्षा करें।
  5. कण दृश्य को हटा दें।

उम्मीद है कि यह मदद कर सकता है।

6

फाउंड्री उत्कृष्ट उत्तर over here के लिए धन्यवाद मैंने इस समस्या को हल किया। इसमें किसी भी विचार को छिपाना शामिल नहीं है। संक्षेप में, यह इस प्रकार है:

अपने emitter सेट अप के रूप में आप सामान्य रूप से, emitter कोशिकाओं नाम और उन्हें शून्य के जन्मदर मूल्य देना होगा:

-(void) setUpEmission { 
    # ... 
    # snip lots of config 
    # ... 
    [emitterCell1 setBirthrate:0]; 
    [emitterCell1 setName:@"emitter1"]; 
    [emitterCell2 setBirthrate:0]; 
    [emitterCell2 setName:@"emitter2"]; 
    emitterLayer.emitterCells = @[emitterCell1, emitterCell2]; 
    [self.view.layer addSublayer:emitterLayer]; 
} 

तो एक शुरुआत विधि है जो आप बंद हो जाता बनाने कुछ देर बाद उत्सर्जन, और एक को रोकने विधि:

-(void) startEmission { 
    [emitterLayer setValue:@600 forKeyPath:@"emitterCells.emitter1.birthRate"]; 
    [emitterLayer setValue:@250 forKeyPath:@"emitterCells.emitter2.birthRate"]; 
    [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(stopEmission) userInfo:nil repeats:NO]; 
} 

-(void) stopEmission { 
    [emitterLayer setValue:@0 forKeyPath:@"emitterCells.emitter1.birthRate"]; 
    [emitterLayer setValue:@0 forKeyPath:@"emitterCells.emitter2.birthRate"]; 
} 

इस उदाहरण मैं 600 और 250 के लिए जन्म दर निर्धारित किया है और टाइमर 0.2 सेकंड के बाद उत्सर्जन को बंद कर देता है, लेकिन जो कुछ भी उपयोग आपको योग्य।

इष्टतम समाधान होगा यदि ऐप्पल ने स्टार्ट/स्टॉप विधियों को लागू किया था, लेकिन इससे कम मुझे यह एक संतोषजनक समाधान मिल गया।

+1

यह एकमात्र उत्तर था जो मेरे लिए काम करता था। धन्यवाद –

+0

सरल और सुरुचिपूर्ण उत्तर के लिए धन्यवाद। मैं अभी भी उलझन में हूं कि मैं emitterlay1 पर emittercell1 और emittercell2 को दो अलग-अलग स्थानों में कैसे रख सकता हूं। धन्यवाद –

0

क्या आपने कैलियर के एनिमेटेबल गुणों का लाभ उठाने में देखा है?

func setEmitterProperties() { 

    backgroundColor = UIColor.clearColor().CGColor 
    birthRate = kStandardBirthRate 
    emitterShape = kCAEmitterLayerLine 
    emitterCells = [typeOneCell, typeTwoCell, typeOneCell] 
    preservesDepth = false 

    let birthRateDecayAnimation = CABasicAnimation() 
    birthRateDecayAnimation.removedOnCompletion = true 
    birthRateDecayAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 
    birthRateDecayAnimation.duration = CFTimeInterval(kStandardAnimationDuration) 
    birthRateDecayAnimation.fromValue = NSNumber(float: birthRate) 
    birthRateDecayAnimation.toValue = NSNumber(float: 0) 
    birthRateDecayAnimation.keyPath = kBirthRateDecayAnimationKey 
    birthRateDecayAnimation.delegate = self 

    } 
  1. प्रतिनिधि संपत्ति भी नहीं के बराबर है, तो आप, पूरा होने पर कुछ भी करने को animationDidStop में के रूप में नहीं करना चाहते हो सकता है: समाप्त हो गया:

  2. स्थिरांक kBirthRateDecayAnimationKey & kStandardAnimationDuration उपयोग मेरा सम्मेलन, ऐप्पल नहीं।

1

CAEmitter.birthRate एनिमेटेबल है।मान लें कि आप को देखने के लिए कुछ CAEmitterLayer रों जोड़ दिया है, आप ऐसा कर सकते जन्मदर के क्षय चेतन और फिर कुछ सेकंड के बाद फिर से शुरू:

- (void) startConfetti{ 
    for (CALayer *emitterLayer in self.layer.sublayers) { 
    if ([emitterLayer isKindOfClass: [CAEmitterLayer class]]) { 
     ((CAEmitterLayer *)emitterLayer).beginTime = CACurrentMediaTime(); 
     ((CAEmitterLayer *)emitterLayer).birthRate = 6; 

     // Decay over time 
     [((CAEmitterLayer *)emitterLayer) removeAllAnimations]; 

     [CATransaction begin]; 
     CABasicAnimation *birthRateAnim = [CABasicAnimation animationWithKeyPath:@"birthRate"]; 
     birthRateAnim.duration = 5.0f; 
     birthRateAnim.fromValue = [NSNumber numberWithFloat:((CAEmitterLayer *)emitterLayer).birthRate]; 
     birthRateAnim.toValue = [NSNumber numberWithFloat:0.0f]; 
     birthRateAnim.repeatCount = 0; 
     birthRateAnim.autoreverses = NO; 
     birthRateAnim.fillMode = kCAFillModeForwards; 
     [((CAEmitterLayer *)emitterLayer) addAnimation:birthRateAnim forKey:@"finishOff"]; 
     [CATransaction setCompletionBlock:^{ 
     ((CAEmitterLayer *)emitterLayer).birthRate = 0.f; 
     [self performSelector:@selector(startConfetti) withObject:nil afterDelay:10]; 
     }]; 
     [CATransaction commit]; 
    } 
    } 
}