2012-12-20 34 views
13

什麼是在2D XNA遊戲中繪製精靈的有效方法?更具體地說,我把這個問題分成4個問題。最佳實踐:XNA中的高效精靈繪圖


我用來聲明的Game1的spriteBatch 靜態,並在每一個IDrawable.Draw稱爲SpriteBatch.Begin.Close。那並不好。給每個可繪製的它自己的SpriteBatch也不能很好地工作。

Q1:我認爲,最好有一個 SpriteBatch實例,只調用開始/關閉一次。它是否正確?


目前,我Game1.Draw看起來是這樣的:

spriteBatch.Begin(); 

base.Draw(gameTime); // draws elements of Game.Components 

// ... 

spriteBatch.End(); 

Q2:這樣一來,Begin只調用一次。這是要走的路嗎?你們是如何解決這個問題的?


Q3:此外,每個組件都有它自己的IGameComponent.LoadContent方法。我應該在那裏加載我的內容?或者,是否更好地加載父級的內容,如Game1.LoadContent


我知道我不應該加載相同的內容兩次,所以我給我的繪製組件同時使用靜態和非靜態Texture2D,並給了他們2層構造:

static Texture2D defaultTexture; 
public Texture2D MyTexture; 

public Enemy() 
    : this(defaultTexture) { } 

public Enemy(Texture2D texture) 
{ 
    MyTexture = texture; 
} 

protected override void LoadContent() 
{ 
    if (MyTexture == null) 
    { 
     if (defaultTexture == null) 
     { 
      defaultTexture = Content.Load<Texture2D>("enemy"); 
     } 

     MyTexture = defaultTexture; 
    } 
} 

這方式,一個類的默認紋理僅在該類第一次調用LoadContent時被加載。但是,當在構造函數中指定參數texture時,我必須事先加載該紋理。

Q4:我認爲應該有更好的方法來做到這一點。我正在考慮用他們的資產名稱作爲字符串來創建一個紋理字典。你會建議什麼?

+0

我做的同樣的方式。如果我沒有理由使用乘法精靈批處理(例如,對於分屏,不同效果等),我只在主類遊戲中調用開始和結束一次,並在該開始和結束之間繪製所有內容。 – Thaven

回答

3

我用來聲明的Game1的spriteBatch靜態

你沒有擁有它是靜態的。只是做一個單身人士。裏面Draw方法

SpriteBatch spriteBatch = ScreenManager.SpriteBatch; // singletion SpriteBatch 
spriteBatch.Begin(); 
// Draw the background 
spriteBatch.Draw(background, ... 
foreach (var enemy in enemys) 
{ 
    enemy.Draw(gameTime); 
} 
// etc. 
spriteBatch.End(); // call here end 
base.Draw(gameTime); // and then call the base class 

我認爲,最好有一個SpriteBatch實例,只調用 開始/關閉一次。它是否正確?

我建議你在一種方法中打開和結束SpriteBatch。它將幫助您避免與開始繪製的SpriteBatch衝突,但未完成。

您是否將元素添加到全局組件集合中?爲這個集合添加drawable是一個壞主意。您無法控制繪圖的順序,組件是全局的。 See this answer

在您的組件中實現IUpdatable和IDrawable,並在您需要的代碼中調用它們。擺脫靜態的東西,並使用Dependency Injection istead。

此外,每個組件都有自己的IGameComponent.LoadContent方法。我應該在那裏加載我的內容?或者,是否更好地將內容加載到父類,如Game1.LoadContent?

您應該在需要時加載資產,並對其負責。當用戶剛開始遊戲時,你不需要加載全部30個關卡,對吧?例如,當您的遊戲開始時,您將加載您的開始屏幕和主菜單所需的所有資產。如果你只是加載你需要的東西,玩家就會很高興,遊戲開始快速。然後玩家想要開始玩遊戲。在這裏,您可以將資產加載到單獨的線程以保持應用程序的響應。

我認爲應該有更好的方法來做到這一點。我正在考慮用他們的資產名稱作爲字符串來創建一個紋理字典。你會建議什麼?

Content.Load已經被緩存了,所以你不必這樣做。

+0

你似乎手動調用對敵人的「繪製」。在我的遊戲中,我添加了所有可繪製對象(比如牆壁和敵人)到'Game1.Components'列表,因此調用基類時調用Draw'。 –

+0

@RuudLenders看到我的更新 –

+0

+1,指出Content.Load處理冗餘調用本身。但是,它使用全局集合很糟糕嗎?我不必控制繪圖順序。 –

0

Q4:我認爲應該有更好的方法來做到這一點。我正在考慮用他們的資產名稱作爲字符串來創建一個紋理字典。你會建議什麼?


A4:我通常創建我的TextureLib類(在運行時處理裝載PNG圖像)內的Dictionary<string, Texture2D> NameTextureDic,這樣我就可以得到任何紋理就像這樣:

var t2d = textureLib.NameTextureDic["tree-4"];