2013-10-14 36 views
7

在我的遊戲我有成千上萬的「板磚」節點從而彌補了遊戲地圖(認爲模擬城市),我想知道的紋理什麼最幀率/內存有效的途徑並動畫每個節點將是?有一些獨特的瓷磚「類型」,每個都有自己的紋理圖集/動畫,所以確保紋理在可能時被重用。SpriteKit要加載紋理圖集千精靈

我所有的tile節點都是一個map節點的患兒,應地圖節點手柄識別瓦片型和加載必要的地圖集&動畫(例如,通過從plist中加載紋理&圖集名字嗎?)

或者,每個tile類型都是某個子類。對於每個SKSpriteNode磁貼來處理他們自己的精靈地圖集是否會更好。 [tileInstance texturise];(sprite工具包是如何處理這個問題的?這種方法會導致相同的紋理地圖集被加載到內存中用於某個tile類型的每個實例嗎?)

我一直在爲文檔更深入地解釋地圖集和紋理重新使用,但我不知道典型的程序是什麼樣的情景。任何幫助將不勝感激,謝謝。

回答

21

內存第一:不會有任何明顯的差異。您必須加載圖塊的紋理,紋理將至少佔Map + Tiles內存的99%,就是這樣。

紋理重用:紋理被重用/自動緩存。使用相同紋理的兩個精靈將引用相同的紋理,而不是每個都擁有自己的紋理副本。

Framerate/Batching:這是關於正確配料。 Sprite Kit通過按照它們被添加到子數組的順序渲染節點來處理節點的子節點。只要下一個子節點使用與前一個節點相同的紋理,它們將全部被分成一個繪製調用。可能最糟糕的事情是添加精靈,標籤,精靈,標籤等。儘可能按連續順序使用相同的紋理添加儘可能多的精靈。

阿特拉斯用法:在這裏你可以贏得最多。開發人員通常試圖對他們的地圖集進行分類,這是錯誤的方法。您不需要爲每個貼圖(及其動畫)創建一個貼圖,而是儘可能少地創建紋理貼圖,每個貼圖包含儘可能多的貼圖。在所有iOS 7設備上,紋理圖集可以是2048x2048,除iPhone 4和iPad 1之外,所有其他設備都可以使用最多4096x4096像素的紋理。

有此規則的例外,說如果你有這麼大的量的紋理,你不可能在一次加載它們都到內存中的所有設備。在這種情況下,請使用您的最佳判斷來查找內存使用情況與配料效率的良好折中。例如,一種解決方案可能是爲每個獨特場景創建一個或兩個紋理圖集,或者「風景」,即使這意味着要複製其他場景的其他紋理圖集中的某些圖塊。如果你的瓷磚幾乎總是出現在任何風景中,那麼把它們放在一個「共享」的地圖集中是有意義的。

至於子類瓷磚,我是一個強大的支持者,以避免繼承類節點。特別是如果子類化的主要原因是僅僅改變他們使用/動畫的紋理。一個精靈已經是一個紋理的容器,所以你可以改變精靈的紋理並從外部進行動畫處理。

要向節點添加數據或附加代碼,您可以通過創建自己的NSMutableDictionary並添加您需要的任何對象來細讀其userData屬性。一個典型的基於組件的的做法會是這樣的:

SKSpriteNode* sprite = [SKSpriteNode spriteWithWhatever..]; 
[self addChild:sprite]; 

// create the controller object 
sprite.userData = [NSMutableDictionary dictionary]; 
MyTileController* controller = [MyTileController controllerWithSprite:sprite]; 
[sprite.userData setObject: forKey:@"controller"]; 

該控制器對象,然後執行需要爲您的瓷磚任何自定義代碼。這可能是動畫瓷磚和其他任何事情。唯一重要的一點是使參考所屬節點(這裏:精靈)弱引用:

@interface MySpriteController 
@property (weak) sprite; // weak is important to avoid retain cycle! 
@end 

因爲精靈保留了字典。字典保留了控制器。如果控制器保留精靈,則精靈將無法釋放,因爲仍然會有一個保留引用 - 因此它將繼續保留保留控制器的字典,該控制器保留精靈。

使用基於組件的方法(也由青睞和實施Kobold Kit)的優點在於:

  • 如果適當設計,可以與任何或多個節點。如果有一天你想要一個標籤,效果,形狀節點瓦片呢?
  • 你不需要每個瓷磚的子類。有些瓷磚可能是簡單的靜態小精靈。所以對這些使用簡單的靜態SKSpriteNode。
  • 它允許您根據需要啓動/停止或添加/刪除單個方面。即使在您最初並不期望擁有或需要特定方面的瓷磚上。
  • 組件允許您構建您將經常需要並且甚至可能在其他項目中需要的功能庫。
  • 組件使更好的體系結構。經典的面向對象設計的錯誤是玩家和敵人的課程,然後意識到都需要能夠射箭和裝甲。所以你move the code to the root GameObject class,使代碼可用於所有的子類。通過組件,您只需將設備和拍攝組件添加到需要它的對象。
  • 基於組件的設計的巨大優勢是,您可以從其他事物開始分別開發各個方面,以便可以根據需要重複使用和添加它們。你幾乎自然會寫出更好的代碼,因爲你用不同的思維方式來處理事情。根據我自己的經驗,一旦將模塊化爲組件,您的bug會少得多,而且更容易解決,因爲您不必查看或考慮其他組件的代碼 - 除非組件使用了它,那麼當一個組件觸發另一個組件時,你有一個清晰的邊界,即當另一個組件接管時傳遞的值仍然正確嗎?如果沒有,該錯誤必須位於第一個組件中。

這是一個good introduction on component-based design。混合方法當然是一條可行的路。這裏是more resources on component based design,但我強烈建議不要偏離路徑並將FRP視爲「接受的答案的作者」所建議的 - FRP是一個有趣的概念,但在遊戲開發中尚未有真實世界的應用。

+1

可靠答案......還有很多東西要學! – DogCoffee

+5

總體回答良好。擴大關於**配料**的一點**:如果您在您的SKView上將'ignoresSiblingOrder'設置爲YES,您無需擔心兒童的順序--Sprite Kit會自動對它們進行分類以獲得高效的繪圖(例如在一次繪製調用中來自相同紋理圖集的所有精靈)。在**圖集**上:考慮到'ignoresSiblingOrder',如果一個圖集的紋理太多/很大,則可以使用節點層次結構將場景組織爲「圖層」,每個圖層可以是一個繪製調用和一個圖集(例如世界與HUD)。 – rickster

+0

很酷,我不知道這個屬性 – LearnCocos2D