Używanie parametrów warstwy do tworzenia kontekstu sprite'ów
streszczenie
Użyj wartości głębokości warstwy, aby określić kontekst ikonki.
Środowisko pracy
Warunki wstępne
Obsługiwane wersje XNA |
|
Obsługiwane platformy |
|
Wymagana wersja cieniowania wierzchołków systemu Windows | 2.0 |
Wymagana wersja Pixel Shader w systemie Windows | 2.0 |
Środowisko pracy
podest |
|
substancja
Zwykle, gdy rysujesz duszka, jest ona rysowana tak, że to, co narysujesz później, jest przed tobą, ale sortując według wartości głębokości, możesz sprawić, że kontekst będzie jasny niezależnie od kolejności, w jakiej wywoływana jest metoda SpriteBatch.Draw.
Aby posortować według wartości głębokości sprite, określ "SpriteSortMode.BackToFront" jako pierwszy argument metody "SpriteBatch.Begin". Jest to metoda przetwarzania, która czerpie z duszka z tyłu i nadpisuje duszka na pierwszym planie.
// 一つでも半透明、透明要素があるスプライトの場合はこちらの引数を使用
this.spriteBatch.Begin(SpriteSortMode.BackToFront, null);
Jeśli jednak chcesz narysować tylko duszka, który jest półprzezroczysty lub nie ma żadnych przezroczystych elementów, możesz narysować go szybciej, określając następujące elementy.
// 深度バッファを使用して前後関係を有効にし描画するように指定
// 完全な不透明スプライトのみ描画する場合はこちらが高速
this.spriteBatch.Begin(SpriteSortMode.FrontToBack,
BlendState.Opaque,
null,
DepthStencilState.Default,
null);
Czwartym argumentem jest "DepthStencilState.Default", który również zapisuje informacje o "głębokości" do każdego piksela podczas rysowania ikonki. Po zapisaniu informacji o głębokości można określić, że obiekt, który ma zostać narysowany (w pikselach) po tej pozycji, nie musi być zapisany, więc koszt rysowania jest znacznie zmniejszony.
Z powyższych powodów, jeśli najpierw narysujesz duszka na pierwszym planie, koszt rysowania duszka, który nakłada się za nim, zmniejszy się, więc jest on sortowany tak, aby był rysowany od przodu, określając "SpriteSortMode.FrontToBack" jako pierwszy argument do rysowania z pierwszego planu.
Jest to jednak przydatne tylko podczas rysowania nieprzezroczystego duszka z całkowicie znikomym elementem koloru za nim. W przypadku sprite'ów półprzezroczystych lub nieprzezroczystych wartość głębi jest zapisywana do każdego piksela, nawet jeśli jest to piksel półprzezroczysty lub przezroczysty, więc jeśli rysujesz od przodu, duszek za tobą nie zostanie wyświetlony. Z tego powodu na rysunku postaci określono "SpriteSortMode.BackToFront". (Ponieważ piksele inne niż kształt tekstu są przezroczyste)
Nawiasem mówiąc, w wyniku testu rysowania 30 000 sprite'ów w moim otoczeniu, rysowanie z przodu przy użyciu wartości głębokości było około 3 razy szybsze niż z tyłu. Oczywiście zależy to od liczby arkuszy do narysowania, stopnia nałożenia się, rozmiaru itp., a także środowiska wykonawczego, więc spróbuj sam.
SpriteBatch.Begin
metoda
Zadzwoń do niego przed narysowaniem duszka. Wewnętrznie wprowadzamy niezbędne ustawienia do rysowania sprite'ów.
sortMode (tryb sortowania) | Tryb sortowania SpriteSortMode | Określa kolejność, w jakiej sprite'y są rysowane z wyliczenia SpriteSortMode. Jeśli chcesz rysować od tyłu, określ SpriteSortMode.BackToFront. Jeśli chcesz rysować od przodu, określ SpriteSortMode.FrontToBack. |
blendState (stan mieszania) | Stan mieszania | Jak połączyć kolor duszka, który ma zostać narysowany, z kolorem tła. Domyślnie określono BlendState.AlphaBlend, ale w tym przypadku ikonka do narysowania jest całkowicie nieprzezroczysta, więc BlendState.Opaque jest określana bez uwzględnienia koloru tła. |
samplerState (Państwo) | Stan próbki | Sposób próbkowania tekstury. Jeśli null zostanie określona, zostanie określona wartość domyślna SamplerState.LinearClamp . |
głębokośćStan szablonu | GłębokośćStencilState (GłębokośćStan wzornika) | Określa sposób użycia bufora głębokości-szablonu. Jeśli wartość null jest określona, używany jest DepthStencilState.None, który nie używa buforu głębokości-szablonu. Jeśli chcesz użyć buforu depth-stencil, określ DepthStencilState.Default. |
RasterizerState (stan rasteryzatora) | Stan rasterizera | Określa metodę rasteryzacji, taką jak usuwanie wsteczne. Jeśli wartość null zostanie określona, zostanie określona wartość domyślna RasterizerState.CullCounterClockwise. |
Aby narysować ikonkę, określ wartość głębokości jako dziewiąty argument metody SpriteBatch.Draw. Wartości, które można tutaj ustawić, mieszczą się w zakresie 0,0 ~ 1,0, przy czym 0,0 jest najsurowszy, a 1,0 jest najbardziej wysunięty.
// 最背面に描画(赤)
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
metoda
Dodaje ikonkę do listy wsadu rysowania ikonki.
tekstura | Tekstura2D | Określa teksturę, która ma być wyświetlana jako ikonka. |
pozycja | Wektor2 | Pozycja, w której ma być wyświetlany duszek. Określ współrzędne ekranu względem lewego górnego rogu ekranu. Początek duszka będzie znajdował się w lewym górnym rogu. |
sourceRectangle (Prostokąt) | Dopuszczanie wartości null<Rectangle> | Określa obszar transferu tekstury. Jeśli chcesz, aby cała tekstura była wyświetlana jako ikonka, możesz określić wartość null. Jeśli określisz ten parametr, możesz sprawić, że tylko dowolny obszar będzie wyświetlany jako duszek. |
Kolor | Kolor | Określa kolor, który ma zostać zwielokrotniony przez kolor ikonka. Jeśli określisz Color.White, będzie on wyświetlany w podstawowym kolorze ikonki. Jeśli zostanie określona wartość Color.Black, ikonka będzie wyświetlana w pełnej czerni, niezależnie od jej koloru. Formuła to "Wynik = kolor duszka * kolor". |
obrót | spławik | Kąt obrotu duszka. Jednostki są określone w radianach. Oś obrotu będzie znajdować się w lewym górnym rogu duszka. |
pochodzenie | Wektor2 | Określa położenie osi obrotu podczas obracania duszka. Można określić, która pozycja ikonki jest osią obrotu, ale w rzeczywistości pozycja osi obrotu jest ustalona w lewym górnym rogu ikonki, a pozycja wyświetlania ikonki jest przesuwana przez -origin. |
skala | spławik | Określa powiększenie duszka. Skaluje się w pionie i poziomie względem wersji 1,0. Początek powiększenia będzie znajdował się w lewym górnym rogu duszka. |
Efekty | Efekty Sprite'a | Określa efekt odwrócenia ikonki. Jeśli nie robisz nic innego, określ SpriteEffects.None. |
layerDepth (głębokość warstwy) | spławik | Określa głębokość, na której ikonka jest wyświetlana. Służy głównie do wyświetlania sprite'ów na pierwszym i tylnym planie. Określ w zakresie 0,0 ~ 1,0, gdzie 0,0 to przód, a 1,0 to tył. |
W powyższym programie metoda SpriteBatch.Draw jest wywoływana w kolejności "czerwony", "zielony" i "niebieski", ale każda wartość głębokości jest ustawiona na "czerwony (1.0)", "zielony (0.0)" i "niebieski (0.5)", więc widać, że czerwony jest rysowany z tyłu, a zielony jest rysowany na pierwszym planie.
Wszystkie kody
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);
}
}
}