2012-10-03 85 views
3

我正在開發一個XNA遊戲。這是我對架構小心的時候。直到今天,我一直以這種方式來實現我自己的繪製方法:XNA draw:在整個遊戲中使用一個spritebatch

public void Draw(SpriteBatch sb, GameTime gameTime) 
{ 
    sb.Begin(); 
    // ... to draw ... 
    sb.End(); 
} 

我挖DrawableGameComponent,看到Draw方法來這樣:

public void Draw(GameTime gameTime) 
{ 
    // ... 
} 

首先,我知道SpriteBatch可以在開始和結束之間收集許多Texture2D,以便對它們進行排序或使用相同的效果進行繪製。

我的問題是關於傳遞SpriteBatch的性能和成本。在DrawableGameComponent中,如果其spritebatch是公開的,則可以調用遊戲對象的spritebatch。

有什麼建議,xna遊戲程序員應該做什麼?

感謝您的建議。

回答

4

DrawableGameComponent的一個嚴重缺點是您被鎖定到其提供的方法簽名中。雖然沒有什麼「錯誤」,本身,與DrawableGameComponent,不要認爲它是「一個真正的架構」。你是better off認爲它可能是architecture的一個例子。

如果你發現自己需要一個SpriteBatch(或其他東西)傳遞到「遊戲組件」的繪製方法 - 最好的辦法是它作爲參數傳遞。其他任何事情都是令人費解的。

顯然這意味着你不能使用XNA提供的GameComponent系統,你必須自己選擇。但是這幾乎是微不足道的:在最基本的層面上,它只是一個具有適當虛擬方法的基本類型列表。


當然,如果你必須使用GameComponent - 或你的遊戲就是這麼簡單(例如:一臺樣機),你真的不關心架構 - 那麼你可以使用基本任何方法你喜歡得到一個SpriteBatch到你的繪製方法。它們都有缺點。

也許最下一個架構強大的方法是將您的SpriteBatch實例傳遞到每個組件的構造函數中。這可以讓你的組件與你的遊戲類脫鉤。另一方面,如果你正在向建築風向投擲,我建議你製作MyGame.spriteBatch字段public static。這是允許在任何地方訪問的最簡單的方法。實施起來很簡單,並且在需要時可以輕鬆清理。


要回答你的問題有關的性能:任何與傳遞一個SpriteBatch周圍的人也會對性能幾乎可以忽略不計的影響做(提供調用的順序Draw/Begin/End保持不變)。不要擔心。

(如果你看到在代碼SpriteBatch whatever,表示的引用。參考是一個32位的值(在32位的程序,其中所有XNA遊戲是),這是大小爲intfloat相同。它通過/訪問/等非常小,非常便宜)

1

如果DrawableGameComponent應該是父節點SpriteBatch的一部分,那麼只需通過構造函數將其傳遞並將其存儲在私有成員中(或者如果願意,則將其作爲屬性公開)。

你也可以暴露SpriteBatch爲您Game類的屬性,如果你想,像你這樣的建議,但每次提到this.Game時候,你需要將它轉換爲特定Game類類型。

((MyGame)this.Game).SpriteBatch.Draw(...) 

或者,你可以有DrawableGameComponent創建一個新的SpriteBatch。這沒有什麼不妥(據我所見)。我想這取決於你將創建多少個DrawableGameComponent以及多久。

同時瀏覽search for DrawableGameComponent的結果 - 這裏有很多好的建議。

4

如果你偶然發現這個問題,你可能正在尋找一個很好的通用解決方案。我建議你看看這個:「最好的辦法是把它作爲參數傳遞還有什麼是令人費解的。」

https://gamedev.stackexchange.com/questions/14217/several-classes-need-to-access-the-same-data-where-should-the-data-be-declared/14232#14232

我覺得有必要糾正這個問題,因爲簡直就是不正確

我個人來說,我現在做這種方式在我GameBase類:

protected override void LoadContent() 
    { 
     // Create a new SpriteBatch, which can be used to draw textures. 
     SpriteBatch = new SpriteBatch(GraphicsDevice); 
     this.Services.AddService(typeof(SpriteBatch), SpriteBatch); 
    } 

現在,因爲你將在你的遊戲類的初始化方法DrawableGameComponents你將能夠調用

this.Game.Services.GetService(typeof(SpriteBatch)) 

我會說這是解決問題的最簡潔的方法。

+0

我不同意這是最好的方法。在遊戲中使用[IoC](https://en.wikipedia.org/wiki/Inversion_of_control)可能會導致大量的性能開銷,如果沒有正確連接的話。這要求您提前註冊所有的類型,即使遊戲在其生命週期中從不使用它們,這是浪費資源。根據您的目標設備和遊戲類型,資源可能非常有限。 DI有它的位置。我只是不同意它屬於除原型之外的任何形式的視頻遊戲。 –

+0

@JohnathonSullinger您提到的限制顯然是正確的,因爲這是DI非常常見的「問題」。它應該小心使用,並進行監控以避免不良表現 - 但大多數收集DI經驗的人已經知道這一點 – Dbl