這個(gè)文章的前置文章是:LNDanmakuMaster
軌道組的由來
假設(shè)產(chǎn)品經(jīng)理提出這樣的需求:所有App鉆石會(huì)員用戶發(fā)的彈幕只能出現(xiàn)在頂部前三排奠宜,黃金會(huì)員用戶第4到6排吼句、白銀用戶第7到9排隅熙;如果我們?nèi)匀徊捎靡粋€(gè)Player/Dispatcher策略涛碑,彈幕的播放條件可能會(huì)互相影響:假設(shè)白銀軌道特別繁忙躯概,一條鉆石軌道的彈幕此時(shí)插入到隊(duì)尾,雖然鉆石軌道當(dāng)前十分空閑,但這條鉆石彈幕不得不等所有隊(duì)列中的白銀彈幕出隊(duì)列之后才能播放,說句實(shí)話這對(duì)氪金大佬十分不友好实苞。
軌道組就是為這種有播放條件彈幕的場(chǎng)景設(shè)計(jì),形成:播放器 -> 多個(gè)軌道組 -> 多個(gè)軌道的結(jié)構(gòu)烈疚,用戶可以挑選任意的軌道放入一個(gè)帶有某種含義的軌道組中黔牵;在插入彈幕時(shí)不是將彈幕插入播放器,而是插入軌道組中胞得;這樣這條彈幕出現(xiàn)的位置就只可能是這個(gè)軌道組所包含的那些軌道荧止。
所以,針對(duì)上面這種場(chǎng)景阶剑,我們只要?jiǎng)?chuàng)建三個(gè)軌道組,diamondTrackGroup危号、goldTrackGroup牧愁、silverTrackGroup, 并將對(duì)應(yīng)的9條軌道分別放入三個(gè)軌道組,在分發(fā)彈幕時(shí)根據(jù)彈幕特性外莲,分別放入不同的軌道組猪半,這樣就實(shí)現(xiàn)了“條件分發(fā)”。這種條件分發(fā)不會(huì)發(fā)生不同種類彈幕之間的相互阻塞偷线,因?yàn)槊總€(gè)軌道組的Dispatcher中存儲(chǔ)的彈幕都是同類彈幕磨确。
軌道組的實(shí)現(xiàn)
軌道組包含了一個(gè)Dispatcher和一組TrackGroup。在這個(gè)TrackGroup小范圍內(nèi)的分發(fā)策略是由這個(gè)Dispatcher決定的声邦,因此乏奥,分發(fā)策略甚至可以與Player整體策略不一致,以下是TrackGroup的屬性定義:
@interface LNDanmakuTrackGroup : NSObject
@property (nonatomic, strong, readonly) LNDanmakuAbstractDispatcher *dispatcher;
@property (nonatomic, copy, readonly) NSArray<LNDanmakuAbstractTrackController *> *currentTrackControllers;
- (void)addTrack:(LNDanmakuAbstractTrackController *)trackController;
- (void)removeTrack:(LNDanmakuAbstractTrackController *)trackController;
- (void)clear;
@end
一個(gè)TrackGroup的工作方式與Player是一致的亥曹,但是它自身不含Clock驅(qū)動(dòng)邓了,依賴Player的驅(qū)動(dòng)工作;在Player每次收到Clock回調(diào)后都會(huì)先更新自己的trackController和dispatcher媳瞪,最后檢查一下軌道組是否也需要同樣的操作:
- (void)danmakuClockUpdateTimeInterval:(NSTimeInterval)time
{
/**省略**/
[self trackGroupUpdateTimeInterval:time];
}
遍歷軌道組的列表骗炉,先驅(qū)動(dòng)TrackController更新已有彈幕,再檢查Dispatcher是否有機(jī)會(huì)分發(fā)新的彈幕:
- (void)trackGroupUpdateTimeInterval:(NSTimeInterval)time
{
for (LNDanmakuTrackGroup *trackGroup in self.trackGroupMArr) {
[trackGroup.dispatcher danmakuClockUpdateTimeInterval:time];
for (LNDanmakuAbstractTrackController *trackController in trackGroup.currentTrackControllers) {
[trackController update:time];
}
[trackGroup.dispatcher dispatchNewAttributesToFreeTracks:
[NSArray arrayWithArray:trackGroup.currentTrackControllers]];
}
}
(省略了一些判斷的代碼蛇受,展示主要邏輯)
再舉個(gè)例子
Demo示例中這樣展示軌道組:
這個(gè)彈幕播放器中有7種顏色句葵,26條軌道,每種顏色都對(duì)應(yīng)一個(gè)軌道組,每個(gè)軌道組中有4條軌道乍丈,兩個(gè)軌道組間相交2條軌道:
紅 = (0熊响、1、2诗赌、3)
橙 = (2汗茄、3、4铭若、5)
黃 = (4洪碳、5、6叼屠、7 ) 以此類推
分發(fā)時(shí)會(huì)隨機(jī)選取一種顏色生成彈幕瞳腌,根據(jù)這個(gè)彈幕的顏色將他放入不同的軌道組中,就形成了上面的效果镜雨。這個(gè)例子也為了說明不同的軌道組之間也是可以共用軌道的嫂侍,紅和橙兩個(gè)軌道組之間共用了2、3軌道荚坞,因此挑宠,這兩個(gè)軌道上既可能出現(xiàn)紅色彈幕也可能出現(xiàn)橙色彈幕,這樣可以展現(xiàn)出一種融在一起的效果颓影。
軌道組的常見用途
送大型禮物的彈幕通常在屏幕頂端出現(xiàn)各淀,一般不會(huì)出現(xiàn)在中央。
左下角飄的聊天室信息也可以放在一個(gè)軌道組里诡挂。
帶圖片的彈幕通常只能在特殊軌道上播放碎浇,縮放、旋轉(zhuǎn)等璃俗,這種軌道通常要與普通橫向的軌道區(qū)分開奴璃。
劇情解說類型的彈幕作者通常會(huì)刻意發(fā)在中間一列的那種軌道上(在看一些世界觀比較大的番劇時(shí)通常會(huì)有熱心網(wǎng)友發(fā)彈幕解說或jutou)。
等等城豁。