使用 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);
}
}
}