本文章主要是總結BarrageRenderer實現的思路,所以只是很簡單的說明下使用方法,關于詳細的使用方法請看DEMO。
首先說下如何使用
1.首先初始化BarrageRenderer,并且把畫布添加到當前UIView中。
2.然后調用start方法,并且需要通過定時器加載你配置的彈幕參數。
3.最后你的彈幕就動起來了。。。(基本的使用超級簡單)
項目目錄
然后分析下這個項目的框架。一共3個大模塊:BarrageEngine(彈幕引擎),BarrageLoader(彈幕加載),BarrageSprite(彈幕精靈),各個模塊的職責如下:
BarrageSprite:主要處理彈幕邏輯
彈幕的畫布(BarrageCanvas)*
彈幕時計時器(BarrageClock)*
彈幕負載均衡邏輯(BarrageDispatcher)*
彈幕元素模型(BarrageDescriptor)
彈幕的UI控制邏輯(BarrageRenderer)
彈幕的模型轉化(BarrageSpriteFactory)
BarrageLoader:
主要應該是優化彈幕加載時間,我下載的是1.9.1版本,作者沒有實現改功能。
BarrageSprite:主要處理各種不用類型的彈幕
這個模塊下主要分2個類型的彈幕,懸浮彈幕(BarrageFloatSprite)和左右滑動彈幕(BarrageWalkSprite)。
BarrageSprite(彈幕精靈的基類)
BarrageSpriteProtocol(彈幕遵守的協議)
BarrageWalkSprite(左右滑動彈幕的基類)
BarrageWalkTextSprite(左右滑動彈幕+文字)
BarrageWalkImageSprite(左右滑動彈幕+圖片)
BarrageFloatSprite(懸浮彈幕的基類)
BarrageFloatTextSprite(懸浮彈幕+文字)
BarrageFloatTextSprite(懸浮彈幕+圖片)
彈幕是如何動起來的:
以左右滑動彈幕為例,首先我們初始化BarrageRenderer對象,在調用init后,實際我們同時已經初始化好BarrageCanvas(畫布),BarrageClock(計時器)。
接下來需要我們調用BarrageRenderer的start實例方法,其實這個方法里面就初始化BarrageDispatcher(彈幕負載均衡邏輯)。 這時關于處理彈幕邏輯的3大模塊都已經初始化好了。并且這時已經開打的BarrageClock(定時器)開始循環的執行 - (void)update 方法。
然后調用 - (void)receive:(BarrageDescriptor*)descriptor 方法才能夠把轉化好的彈幕精靈(BarrageSprite)添加到 _waitingSprites 數組中,等待顯示出來。
一旦當update方法執行時就會開始派發精靈(dispatchSprites)并且更新派發精靈數組中每一個精靈的 frame。這樣彈幕就動起來了。
項目負載均衡的邏輯
接下來會說下一些細節邏輯,例如:
1.每條彈幕的初始位置(還沒有顯示時)時如何計算的。(左右滑動彈幕為例)
2.如何動態的更改已經顯示的彈幕移動速度。
3.如何實現彈幕的回退。
1.每條彈幕的初始位置(還沒有顯示時)時如何計算的
以左右滑動彈幕為例在BarrageWalkSprite中 - (CGPoint)originInBounds:(CGRect)rect withSprites:(NSArray*)sprites方法實現
使用這個方法需要2個參數rect,sprites。
rect為當前畫布的寬和高。
sprites為正在顯示并且是已經完全顯示的彈幕精靈數組。
循環能顯示的總行數(stripNum),并且遍歷當前已經顯示的彈幕(狀態相同的)數組。計算出lastDistanceAllOut這個值。我理解這個值的含義是:新添加的彈幕是否能夠添加到當前界面中。如果有空余位置給這個新彈幕顯示就顯示出來。如果沒有就選擇最短個數(或者最短時間)。
這個邏輯里面關鍵的幾個參數,availableFrom:計算下一條彈幕應該在第幾行顯示。
2.如何動態的更改已經顯示的彈幕移動速度。
更改renderer對象的speed屬性,就會執行計時器(BarrageClock)的- (void)setSpeed:(CGFloat)speed ,然后一旦當定時器執行到 - (void)updateTime 時。self.time 就會被更改。在通過block傳遞到BarrageRenderer中。
3.如何實現彈幕的回退。
在彈幕的調度器中(BarrageDispatcher)一共聲明3個可變數組分別是:
_activeSprites 記錄當前正在活躍的彈幕數據
_waitingSprites 記錄還沒有顯示出來,等待顯示的彈幕數據
_deadSprites 記錄已經顯示出來的彈幕數據
所以需要遍歷_deadSprites數組,把這個數據重新放入_waitingSprites數組中,并且要把已經放入_waitingSprites的數據需要在_deadSprites 中刪除。因為當等待數據顯示完還需要加入到_deadSprites數組中。