在所有的圖形引擎中,繪制都是最基礎的部分,本文將介紹在XNA框架中與繪制相關的基礎知識。
在XNA中,我們使用SpriteBatch來進行繪制。首先,我們需要使用SpriteBatch來繪制什么了?是精靈Sprite,對。
那么Sprite通過什么來表現了?是紋理,比如2D紋理 Texture2D 。嗯,你可以把紋理想象成Sprite的外表,比如我們制作的一幅精靈圖片,就是一個紋理。
我們要如何才能把一幅圖片加載到我們的游戲中來作為一個Sprite的紋理了?這要通過素材管道 Content Pipeline 。所謂素材,包括我們游戲中要用到的圖片、模型、聲音等,比如一個紋理圖片就是素材的一種。素材管道就很容易理解了,它可以把我們需要的素材導入到我們的游戲中,以XNA能夠識別的正確的格式。而且,格式的識別與轉換是在編譯期完成的。
在新建的XNA項目中,會有一個默認的 Content 文件夾,通常,我們會把所有的素材放在這個地方,并且根據素材的種類我們會在其下創建一些子文件夾,比如Image子文件夾用來存放所有的圖片素材,Audio文件夾用來存放聲音素材等。
當一個物件別被識別為素材后,就會有一個唯一的資產名稱 AssetName 來標記它,我們可以通過素材的屬性頁來查看素材的AssetName屬性并修改它。
下面我們可以用素材管理器 ContentManager 將一個素材導入到游戲中:
texture = Content .Load < Texture2D > ( @"I mage/logo " ); // 在上文提到的LoadContent方法中調用
很多時候,我們的圖片需要是透明的,那么如何在SpriteBatch繪制的時候將圖片繪制為透明了?有兩種方法:要么圖片具有透明的背景,要么在制作圖片時將需要透明的部分設置為純正的洋紅色(255,0,255)。除此之外,還需要注意, SpriteBlendMode 模式必須為AlphaBlend(這也是默認模式,稍后會提到),才能達到我們期望的透明效果。
在進行渲染時,我們還需要注意層深度(Layer Depth)。所謂Layer Depth,指的是你需要將目標Sprite繪制在哪一個深度的層次。默認情況下,SpriteBatch會根據你調用的順序來決定Layer Depth的相對值,比如,你先調用SpriteBatch繪制Sprite A,然后調用SpriteBatch在同一位置繪制Sprite B,那么,Sprite B就會把Sprite A擋住。如果我們依靠調用SpriteBatch繪制的順序來決定Sprite的深度,那就太不靈活了,為此,調用SpriteBatch繪制方法時,你可以指定一個代表層次深度的參數(范圍0~1)來指示SpriteBatch按照我們希望的順序來繪制對象。
有了上面的這些基礎之后,我們可以詳細講解一下XNA中的渲染過程。每次渲染的過程都類似下面的模式:
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.Draw(


spriteBatch.End();
base .Draw(gameTime);
}
(1)GraphicsDevice.Clear()方法用于清除屏幕背景。
(2)SpriteBatch.Begin()方法用于通知顯卡準備繪制場景。
(3)輪流調用SpriteBatch.Draw()繪制所有組件。
(4)SpriteBatch.End()方法用于告訴顯卡繪制已經完成。
(5)最后,顯卡顯示繪制的結果。
SpriteBatch.Begin()方法有一個接受參數的重載:
SpriteBlendMode 參數決定了Sprite的顏色與背景顏色的混合模式,默認為AlphaBlend,我們剛才提到過。
SpriteSortMode參數決定了Sprite的排序模型,即與前面的Layer Depth關聯。
SaveStateMode參數用于控制是否保存圖形設備的狀態。
TransformMatrix參數用于控制旋轉、縮放等。
接下來我們看最重要的繪制Draw方法:
第一個Texture2D參數,表示要繪制Sprite的紋理。
第二個Vector2參數,表示要繪制的Sprite的左上角的位置在哪里。
第三個Rectangle參數,表示要繪制源紋理的哪一個區域,如果要繪制紋理的全部部分,則傳null。
第四個Color參數,表示繪制時所調制的顏色通道。
第五個參數rotation,表示要旋轉的角度。
第六個參數origin,表示圍繞哪個位置進行旋轉。
第七個參數scale,表示繪制時要縮放的比例。
第八個參數effects,表示是否進行翻轉。SpriteEffects.FlipHorizontally -- 水平翻轉;SpriteEffects.FlipVertically -- 垂直翻轉。
最后一個參數layerDepth,就是我們前面說過的要在哪一個深度層次繪制對象。
最后,要解釋一下,為什么需要在每次Draw調用時,都先調用GraphicsDevice.Clear()方法清除屏幕然后再重新繪制所有物件了?這樣性能不是很差嗎?而且有時候我們可能只有極小的一部分需要重新繪制。
假設我們每次只重新繪制變動的那一部分,那我們就需要一個復雜的管理器來追蹤每一個部分的變動,這樣我們才有可能知道要重繪哪一部分。你可以想象一下,這個追蹤的過程是相當復雜的。而且還存在這樣的情況,那就是當一個Sprite移動時,它后面原先被擋住的Sprite會露出來,而這個Sprite可能又會擋住另外一個Sptrite的一部分,這樣一來就更加復雜了。所以,每次重繪整個屏幕并不是一個壞的idea。
今天就講到這里,下一節我們將講述與FrameRate相關的知識。
上一篇: XNA基礎(01) —— 游戲循環
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
