本文由糖炒小蝦、Benna翻譯 ,校對:sai、u0u0、iven、子龍山人
iOS 5中的UIKit粒子系統教程
Ray的話:這是第15篇、也是最后一篇《iOS 5 盛宴》中的iOS 5教程!這篇教程來自我們的新書《iOS 5 教程》中的一篇免費預覽章節。這個禮拜三我們將迎來《iOS 5 盛宴》系列的最后一次發布——來自史詩般的《iOS 5 盛宴》奉送,最后一次#ios5feast的廣播!:]
這是篇教程由iOS教程小組成員Marin Todorov所撰寫,他是一位擁有超過12年經驗的軟件開發者,一位iOS的獨立開發者,同時他也是Touch Code Magazine的創立者。
你可能已經看過一些粒子系統,它們被應用于很多iOS應用程序和游戲中,諸如爆炸、火特效、下雨或者下雪等。然而,你所看到的這些特效類型可能大部分出現在游戲之中,因為UIKit不提供內置的功能來創建粒子系統----直到iOS 5的出現,這種情況將有所改變,本教程將采用UIKit來制作粒子系統!
現在,利用iOS 5你能直接在UIkit中使用粒子系統,給你的應用程序帶來很多令人興奮的視覺享受。這里有一些非常適用于使用粒子系統的例子:
希望能用UIKit粒子系統做些什么,也許你已經有一些很酷的想法啦。那么,讓我們開始吧!
在這個教程中,我們將開發一個叫“Draw with fire”的應用程序,讓你(你猜中了)在屏幕上繪制火焰。
你將和我一起完成粒子系統的創建與設置來實現屏幕上看到的效果,讓你能將你的想法一步步實現。當這個應用完成,你就能用它繪制一個用火焰標記的漂亮的問號,就像這個:
新的粒子 API
有兩個類在你創建粒子系統時將會需要使用,它們在QuartzCore框架中,名叫CAEmitterLayer和CAEmitterCell。
通常的想法是你創建一個CAEmitterLayer,并將一個或多個CAEmitterCell添加到里面。接著每個單元(cell)會按它配置的樣式產生粒子。
而且CAEmitterLayer繼承自CALayer,你能輕易地在UIKit分層的任何地方加入它!
我想這個新的UIKit粒子系統最酷的是一個單獨的CAEmitterLayer可以支持多個CAEmitterCell。這支持你完成一些相當復雜而且很酷的效果。例如當你創建泉水時,你能擁有一個cell發射水滴,另一個cell在泉水上發射水蒸汽!
Getting Started
打開Xcode,并從主菜單中選擇File/New/New PRoject,選擇iOS/application/Single View Application模版,點擊Next,鍵入程序名“DrawWithFire”,再鍵入DWF為前綴,選擇iphone for Device Family,確認勾選“Use automatic reference counting”(其他選擇框別選)。接著點擊Next,再點擊Create保存項目。
選擇你的項目,再選擇DrawWithFire的target。接著打開Build Phases選項卡,展開Link Binary With Libraies部分,再點擊“+”按鈕,雙擊QuartzCore.framework,將Quartz繪圖功能添加到項目里面。
我們將創建一個自定義UIView類來開始項目,這個類將有CAEmitterLayer作為它的層。事實上,完成這些非常簡單,通過重寫UIView類的+(Class)layerClass方法并返回一個CAEmitter類。相當酷哦!
創建一個新文件,采用iOS/Cocoa Touch/Objective-C類模板,類名為DWFParticleView,繼承于UIView。
打開DWFParticleView.m并替換為如下代碼:
#import "DWFParticleView.h"#import <QuartzCore/QuartzCore.h> @implementation DWFParticleView{ CAEmitterLayer* fireEmitter; //1} -(void)awakeFromNib{ //set ref to the layer fireEmitter = (CAEmitterLayer*)self.layer; //2} + (Class) layerClass //3{ //configure the UIView to have emitter layer return [CAEmitterLayer class];} @end
讓我們重溫下初始代碼:
接下來,讓我們將視圖控制器的根視圖轉到DWFParticleView。打開DWFViewController.xib并實現如下步驟:
1、 確認Utilities工具條是可見的(在這張圖上突出的按鈕都改被按下)。
2、 選擇Interface Builder中的灰色區域——這是這個視圖控制器的根視圖。
3、 點擊Identity Inspector選項卡。
4、 在Custom Class面板,在文本框中輸入DWFParticleView。
現在,我們已經將UI全都設置好——干得好!讓我們在圖中添加一些粒子。
A Particle Examined
為了發射火焰、煙霧、瀑布或者其他什么,你將需要一份好的PNG文件來啟動你的粒子。你可以在任何圖像編輯程序中自己制作它。看看我為這個教程制作的圖片(它被放大了并置于黑色背景中,這樣你才能看清楚它的形狀):
我的粒子文件大小是32*32像素,這是份透明的PNG文件,我僅使用有點時髦的筆刷,隨意地用白色繪制而成。對粒子來說,最好的就是使用白色,因為粒子發射器可以用我們想要的顏色對提供的圖像著色。讓粒子圖像呈半透明也是個很好的想法,如此粒子系統就能將粒子通過它們自己混合在一起(你可以通過少量不同的圖像文件理解它如何工作)。
這樣,你就能創建自己的粒子或者就使用我制作的這個,但是要確定它添加到你的Xcode項目中并命名為Particles_fire.png。
讓我們開始產生粒子吧!
是時候添加代碼讓我們的CAEmitterLayer做一些神奇的事情啦!
打開DWFParticleView.m 將如下代碼添加到awakeFromNib:中
//configure the emitter layerfireEmitter.emitterPosition = CGPointMake(50, 50);fireEmitter.emitterSize = CGSizeMake(10, 10);
上面的代碼是用來設置emitter的坐標(view的坐標系下) 和生成粒子的大小的。
然后,在awakeFromNib后面添加一個CAEmitterCell到CAEmitterLayer上,讓我們最終能在屏幕上看到粒子效果
CAEmitterCell* fire = [CAEmitterCell emitterCell];fire.birthRate = 200;fire.lifetime = 3.0;fire.lifetimeRange = 0.5;fire.color = [[UIColor colorWithRed:0.8 green:0.4 blue:0.2 alpha:0.1] CGColor];fire.contents = (id)[[UIImage imageNamed:@"Particles_fire.png"] CGImage];[fire setName:@"fire"]; //add the cell to the layer and we're donefireEmitter.emitterCells = [NSArray arrayWithObject:fire];
我們生成了一個cell實例,并設置了一些屬性。然后設置CAEmitterLayer中emitterCells的屬性---一個包含cells的NSArray數組。現在emitterCell們已經設置好了,CAEmitterLayer準備好發射粒子了!
剛才設置了很多CAEmitterCell的屬性,讓我們一一過下
運行程序,來測試一下我們的粒子效果!
好吧,它工作了,但是并不像我們想象的那么酷。你甚至可以毫不掩飾的承認,它看起來像一個橘黃色的斑點。
讓我們做一些小改動使粒子變得更具有動感。把這些代碼添加到setName: on the cell前面
fire.velocity = 10;fire.velocityRange = 20;fire.emissionRange = M_PI_2;
(編譯并運行來)檢查一下我們的成果
這次看起來好點,距離我們的目標不遠了!如果你想把這些屬性是如何影響粒子發生器理解的更透徹,那就去自由發揮吧,修改屬性值看效果。
再添加兩行,來結束cell的設置
fire.scaleSpeed = 0.3;fire.spin = 0.5;
再次運行:
現在看起來有點像鐵銹色的煙,這是為什么呢?CAEmitterCell有很多屬性來調整,天空類型在這里受限制。在設置fireEmitter.emitterSize后面加這么一句話
fireEmitter.renderMode = kCAEmitterLayerAdditive;
這一行代碼用于讓我們鐵銹色的煙變成沸騰的火球,運行來查看效果
發生了什么?遞增渲染模式(additive render mode)基本上是告訴系統不要用普通的方式——一個蓋住一個的繪制粒子,而是換了一種更酷的方法:如果粒子相互重疊的話他們的顏色強度會增加!所以,你會在粒子發生器的區域里面看到大量的白色亮斑,但在區域外是火球,那里因為粒子不斷消亡而數量減少,色彩漸變到原來的鐵銹色。太棒了!
你現在可能會覺得火焰非常不真實。的確,你可以通過修改cell的屬性讓火焰的效果更好。但是我們需要這么厚的效果,因為我們要去繪制它。當你在設備屏幕上拖動手指的時候,屏幕上會收到相對少的觸摸點,所以我們用厚重的火球來補償他。
玩兒火吧!
現在,你終于可以玩火了(在現實生活中我們被告知永遠不要玩火):]
下面來實現用手指在屏幕上畫火焰,我們需要通過用戶觸摸點來修改粒子發生器的位置
首先在DWFParticleView.h中聲明一個方法:
-(void)setEmitterPositionFromTouch: (UITouch*)t;
然后在DWFParticleView.m中實現它
-(void)setEmitterPositionFromTouch: (UITouch*)t{ //change the emitter's position fireEmitter.emitterPosition = [t locationInView:self];}
這個方法獲得一個觸摸點并作為實參, 將觸摸點信息轉移到ParticleView的坐標系中,并修改粒子發生器的坐標
我們需要在view controller中控制它,所以我們下一步是在viewController中定義接口
#import <UIKit/UIKit.h>#import "DWFParticleView.h" @interface DWFViewController : UIViewController{ IBOutlet DWFParticleView* fireView;}@end
之后打開DWFViewController.xib 然后按住control從File’s Owner向root view拖動,在彈出的選項卡中選擇fireView正如你所見,我們import了我們的自定義view類,并且在DWFParticleView中定義了實例變量。
現在我們能通過view controller 訪問emitter 層。打開DWFViewController.m 刪掉所有自動生成的代碼,添加如下代碼
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [fireView setEmitterPositionFromTouch: [touches anyObject]];}
試著用更快或者更慢的速度拖動它,來看對粒子產生所造成的影響運行,觸摸并向四周拖動,你會看到粒子發生器跟著移動并留下一串很酷的火焰
動態修改Cell
今天最后的話題是在emitter 層動態的改動cell們。現在,粒子發生器一直在產生粒子。沒能給用戶一種是他們畫上去的感覺,讓我們來將粒子發生的條件改為僅當手指觸摸到屏幕的時候產生粒子.那么一開始就不要產生了,于是將DWFParticleView.m的awakeFromNib method方法中 粒子的birthrate設為0
fire.birthRate = 0;
如果你現在運行的話,會發現屏幕空空如也,很好!下面添加一個方法來作為粒子發生(發射)器的開關。首先在DWFParticeView的頭文件中定義如下方法
-(void)setIsEmitting:(BOOL)isEmitting;
然后在DWFParticleView.m實現它
-(void)setIsEmitting:(BOOL)isEmitting{ //turn on/off the emitting of particles [fireEmitter setValue:[NSNumber numberWithInt:isEmitting?200:0] forKeyPath:@"emitterCells.fire.birthRate"];}
這里使用setValue:forKeyPath:方法來改動一個cell, 是因為我們早先將cell的名字添加到了emitter中。我們使用”emitterCells.fire.birthRate”做keypath是因為birthRate是emitterCells數組中一個叫做叫fire的cells的屬性。
最后我們需要在觸摸開始的時候打開粒子發生器的開關,在抬起手指的時候關掉它。在DWFViewController
中添加如下代碼
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [fireView setEmitterPositionFromTouch: [touches anyObject]]; [fireView setIsEmitting:YES];} - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [fireView setIsEmitting:NO];} - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [fireView setIsEmitting:NO];}
完成并運行~觀察效果咯~記住,你在玩兒火:-)
Where To Go From Here?
這里是樣例工程的全部代碼。
如果你喜歡這個教程,這里有更多你可以研究的東西。你可以
以上內容是轉載別人的,這里是我自己實現的粒子效果Demo,下載下來就可以跑啦。下載地址:TestFire.zip
新聞熱點
疑難解答