使用 Layer 參數創建 Sprite 上下文
總結
使用圖層的 depth 值來指定 Sprite 的上下文。
經營環境
先決條件
支援的 XNA 版本 |
|
支援的平臺 |
|
Windows 所需的頂點著色器版本 | 2.0 |
Windows 所需的像素著色器版本 | 2.0 |
經營環境
平臺 |
|
物質
通常,在繪製 sprite 時,會繪製該 sprite,以便稍後繪製的內容位於您面前,但通過按深度值排序,無論調用 SpriteBatch.Draw 方法的順序如何,都可以使上下文清晰。
若要按sprite depth值排序,請將“SpriteSortMode.BackToFront”指定為“SpriteBatch.Begin”方法的第一個參數。 這是一種從後面的sprite中提取並覆蓋前臺的sprite的處理方法。
// 一つでも半透明、透明要素があるスプライトの場合はこちらの引数を使用
this.spriteBatch.Begin(SpriteSortMode.BackToFront, null);
但是,如果您只想繪製半透明或根本沒有透明元素的sprite,則可以通過指定以下內容來更快地繪製它。
// 深度バッファを使用して前後関係を有効にし描画するように指定
// 完全な不透明スプライトのみ描画する場合はこちらが高速
this.spriteBatch.Begin(SpriteSortMode.FrontToBack,
BlendState.Opaque,
null,
DepthStencilState.Default,
null);
第四個參數是「DepthStencilState.Default」,它還會在繪製子畫面時將“深度”資訊寫入每個圖元。 寫入深度資訊時,可以確定該位置之後的要繪製的物件(以像素為單位)不需要寫入,因此繪製成本大大降低。
由於上述原因,如果先在前臺繪製 sprite,則重疊在其後面的 sprite 的繪製成本將降低,因此通過指定 “SpriteSortMode.FrontToBack” 作為從前臺繪製的第一個參數,對其進行排序,以便從前面繪製。
但是,這僅在繪製不透明 sprite 且其後面的顏色元素完全可以忽略不計時才有用。 對於半透明或不透明的 Sprite,即使它是半透明或透明圖元,深度值也會寫入每個圖元,因此如果您從前面繪製,則不會顯示您後面的 Sprite。 這就是在角色繪製中指定 「SpriteSortMode.BackToFront」 的原因。 (因為文字形狀以外的像素是透明的)
順便說一句,在我的環境中繪製 30,000 個 sprite 的測試結果顯示,使用深度值從前面繪製的速度大約比從後面繪製快 3 倍。 當然,這取決於要繪製的圖紙數量、重疊程度、大小等,以及執行環境,所以請自己嘗試一下。
SpriteBatch.Begin
方法
在繪製sprite之前調用它。 在內部,我們正在為繪製sprite進行必要的設置。
sortMode | SpriteSortMode (精靈排序模式) | 指定從SpriteSortMode枚舉中繪製sprite的順序。 如果要從背面繪製,請指定 SpriteSortMode.BackToFront。 如果要從前面繪製,請指定 SpriteSortMode.FrontToBack。 |
混合狀態 | BlendState (混合狀態) | 如何將要繪製的sprite的顏色與背景色混合。 默認情況下,指定了 BlendState.AlphaBlend,但在這種情況下,要繪製的 sprite 是完全不透明的,因此指定了 BlendState.Opaque,而不考慮背景色。 |
samplerState | SamplerState (采樣狀態) | 紋理的採樣方式。 如果指定了 null,則指定預設的 SamplerState.LinearClamp。 |
depthStencilState | DepthStencilState | 指定如何使用深度模具緩衝區。 如果指定了 null,則使用 DepthStencilState.None,它不使用深度模具緩衝區。 如果要使用深度模具緩衝區,請指定 DepthStencilState.Default。 |
rasterizerState | RasterizerState | 指定柵格化方法,如反向剔除。 如果指定了 null,則指定預設的 RasterizerState.CullCounterClockwise。 |
若要繪製 sprite,請將深度值指定為 SpriteBatch.Draw 方法的第九個參數。 此處可設置的值在0.0~1.0的範圍內,其中0.0是最前面的,1.0是最後面的。
// 最背面に描画(赤)
this.spriteBatch.Draw(this.texture, new Vector2(150.0f, 50.0f), null,
Color.Red, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);
// 最前面に描画(緑)
this.spriteBatch.Draw(this.texture, new Vector2(110.0f, 90.0f), null,
Color.Green, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
// 2つのスプライトの間に描画(青)
this.spriteBatch.Draw(this.texture, new Vector2(190.0f, 130.0f), null,
Color.Blue, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
SpriteBatch.Draw
方法
將 Sprite 新增到 Sprite 繪製批處理清單中。
質地 | 紋理2D | 指定要顯示為 Sprite 的紋理。 |
位置 | 向量 2 | sprite 應顯示的位置。 在螢幕座標中指定相對於螢幕左上角的座標。 精靈的原點將位於左上角位置。 |
sourceRectangle 的 | Nullable<Rectangle 的 Nullable> | 指定紋理的傳輸區域。 如果希望將整個紋理顯示為sprite,則可以指定 null。 如果指定此參數,則只能將任意區域顯示為Sprite。 |
顏色 | 顏色 | 指定顏色以乘以 Sprite 的顏色。 如果指定 Color.White,它將以 Sprite 的原色顯示。 如果指定了 Color.Black,則 sprite 將以全黑顯示,而不管其顏色如何。 公式為“結果 = sprite 顏色 * 顏色”。 |
旋轉 | 浮 | Sprite 的旋轉角度。 單位以弧度指定。 旋轉軸將位於sprite的左上角。 |
起源 | 向量 2 | 指定旋轉 Sprite 時旋轉軸的位置。 您可以指定Sprite的哪個位置是旋轉軸,但實際上,旋轉軸的位置固定在Sprite的左上角,並且Sprite的顯示位置由 -origin 移動。 |
規模 | 浮 | 指定 Sprite 的放大倍數。 相對於 1.0 垂直和水平縮放。 放大的原點將位於Sprite的左上角。 |
影響 | SpriteEffects (精靈效果) | 指定 Sprite 的翻轉效果。 如果不執行任何其他操作,請指定SpriteEffects.None。 |
layerDepth 層深度 | 浮 | 指定 Sprite 的顯示深度。 主要用於在前臺和後台顯示sprite。 在 0.0~1.0 的範圍內指定,其中 0.0 是前部,1.0 是後部。 |
在上面的程式中,SpriteBatch.Draw 方法是按照 “red”、“green” 和 “blue” 的順序調用的,但每個深度值都設置為“red (1.0)”、“green (0.0)”和“blue (0.5)”,所以你可以看到紅色在後面畫,綠色在前台畫。
所有代碼
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
namespace LayerDepthSprite
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
テクスチャー
</summary>
private Texture2D texture = null;
<summary>
GameMain コンストラクタ
</summary>
public GameMain()
{
// グラフィックデバイス管理クラスの作成
this.graphics = new GraphicsDeviceManager(this);
// ゲームコンテンツのルートディレクトリを設定
this.Content.RootDirectory = "Content";
#if WINDOWS_PHONE
// Windows Phone のデフォルトのフレームレートは 30 FPS
this.TargetElapsedTime = TimeSpan.FromTicks(333333);
// バックバッファサイズの設定
this.graphics.PreferredBackBufferWidth = 480;
this.graphics.PreferredBackBufferHeight = 800;
// フルスクリーン表示
this.graphics.IsFullScreen = true;
#endif
}
<summary>
ゲームが始まる前の初期化処理を行うメソッド
グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
</summary>
protected override void Initialize()
{
// TODO: ここに初期化ロジックを書いてください
// コンポーネントの初期化などを行います
base.Initialize();
}
<summary>
ゲームが始まるときに一回だけ呼ばれ
すべてのゲームコンテンツを読み込みます
</summary>
protected override void LoadContent()
{
// テクスチャーを描画するためのスプライトバッチクラスを作成します
this.spriteBatch = new SpriteBatch(this.GraphicsDevice);
// テクスチャーをコンテンツパイプラインから読み込む
this.texture = this.Content.Load<Texture2D>("Texture");
}
<summary>
ゲームが終了するときに一回だけ呼ばれ
すべてのゲームコンテンツをアンロードします
</summary>
protected override void UnloadContent()
{
// TODO: ContentManager で管理されていないコンテンツを
// ここでアンロードしてください
}
<summary>
描画以外のデータ更新等の処理を行うメソッド
主に入力処理、衝突判定などの物理計算、オーディオの再生など
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Update(GameTime gameTime)
{
// Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
// ゲームを終了させます
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
// TODO: ここに更新処理を記述してください
// 登録された GameComponent を更新する
base.Update(gameTime);
}
<summary>
描画処理を行うメソッド
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Draw(GameTime gameTime)
{
// 画面を指定した色でクリアします
this.GraphicsDevice.Clear(Color.CornflowerBlue);
// 深度バッファを使用して前後関係を有効にし描画するように指定
// 完全な不透明スプライトのみ描画する場合はこちらが高速
this.spriteBatch.Begin(SpriteSortMode.FrontToBack,
BlendState.Opaque,
null,
DepthStencilState.Default,
null);
// 一つでも半透明、透明要素があるスプライトの場合はこちらの引数を使用
//this.spriteBatch.Begin(SpriteSortMode.BackToFront, null);
// 最背面に描画(赤)
this.spriteBatch.Draw(this.texture, new Vector2(150.0f, 50.0f), null,
Color.Red, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);
// 最前面に描画(緑)
this.spriteBatch.Draw(this.texture, new Vector2(110.0f, 90.0f), null,
Color.Green, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
// 2つのスプライトの間に描画(青)
this.spriteBatch.Draw(this.texture, new Vector2(190.0f, 130.0f), null,
Color.Blue, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
// スプライトの一括描画
this.spriteBatch.End();
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}