Usando parâmetros de camada para criar contexto de sprite

Página atualizada :
Data de criação de página :

resumo

Use o valor de profundidade da camada para especificar o contexto do sprite.

レイヤーパラメータを使用してスプライトの前後関係を作る

Ambiente operacional

Pré-requisitos

Versões do XNA suportadas
  • 2.0
  • 3.0
  • 3.1
  • 4.0
Plataformas suportadas
  • Windows (XP SP2 ou posterior, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Versão do sombreador de vértice necessária para Windows 2.0
Versão do sombreador de pixel necessária para Windows 2.0

Ambiente operacional

plataforma
  • janelas 7
  • Xbox 360
  • Emulador do Windows Phone 7

substância

Normalmente, quando você desenha um sprite, ele é desenhado de forma que o que você desenhar mais tarde esteja à sua frente, mas classificando por valor de profundidade, você pode tornar o contexto claro, independentemente da ordem em que o método SpriteBatch.Draw é chamado.

Para classificar por valor de profundidade do sprite, especifique "SpriteSortMode.BackToFront" como o primeiro argumento para o método "SpriteBatch.Begin". É um método de processamento que extrai do sprite na parte de trás e substitui o sprite em primeiro plano.

// 一つでも半透明、透明要素があるスプライトの場合はこちらの引数を使用
this.spriteBatch.Begin(SpriteSortMode.BackToFront, null);

No entanto, se você quiser desenhar apenas um sprite que seja semitransparente ou não tenha nenhum elemento transparente, poderá desenhá-lo mais rapidamente especificando o seguinte.

// 深度バッファを使用して前後関係を有効にし描画するように指定
// 完全な不透明スプライトのみ描画する場合はこちらが高速
this.spriteBatch.Begin(SpriteSortMode.FrontToBack,
                       BlendState.Opaque,
                       null,
                       DepthStencilState.Default,
                       null);

O quarto argumento é "DepthStencilState.Default", que também grava informações de "profundidade" em cada pixel quando o sprite é desenhado. Quando as informações de profundidade são gravadas, é possível determinar que o objeto a ser desenhado (em pixels) após essa posição não precisa ser gravado, de modo que o custo do desenho é bastante reduzido.

Pelos motivos acima, se você desenhar o sprite em primeiro plano primeiro, o custo de desenho do sprite que se sobrepõe atrás dele diminuirá, portanto, ele é classificado para que seja desenhado da frente especificando "SpriteSortMode.FrontToBack" como o primeiro argumento a ser extraído do primeiro plano.

No entanto, isso só é útil ao desenhar um sprite opaco com um elemento de cor completamente insignificante por trás dele. No caso de sprites semitransparentes ou opacos, o valor da profundidade é gravado em cada pixel, mesmo que seja um pixel semitransparente ou transparente, portanto, se você desenhar de frente, o sprite atrás de você não será exibido. É por isso que "SpriteSortMode.BackToFront" é especificado no desenho do personagem. (Porque pixels diferentes da forma do texto são transparentes)

A propósito, como resultado de um teste de desenho de 30.000 sprites em meu ambiente, foi cerca de 3 vezes mais rápido desenhar de frente usando o valor de profundidade do que de trás. Claro, depende do número de folhas a serem desenhadas, do grau de sobreposição, do tamanho, etc., bem como do ambiente de execução, então tente você mesmo.

SpriteBatch.Begin método

Chame-o antes de desenhar o sprite. Internamente, estamos fazendo as configurações necessárias para desenhar sprites.

Modo de classificação SpriteSortMode Especifica a ordem na qual os sprites são extraídos da enumeração SpriteSortMode. Se você quiser desenhar na parte de trás, especifique SpriteSortMode.BackToFront. Se você quiser desenhar da frente, especifique SpriteSortMode.FrontToBack.
Estado de mistura Estado de mistura Como misturar a cor do sprite a ser desenhado com a cor de fundo. Por padrão, BlendState.AlphaBlend é especificado, mas, nesse caso, o sprite a ser desenhado é completamente opaco, portanto, BlendState.Opaque é especificado sem considerar a cor da tela de fundo.
samplerState Estado do Sampler Como a textura é amostrada. Se null for especificado, o SamplerState.LinearClamp padrão será especificado.
depthStencilState DepthStencilState Especifica como o buffer de estêncil de profundidade é usado. Se null for especificado, DepthStencilState.None será usado, o que não usa um buffer de estêncil de profundidade. Se você quiser usar um buffer de estêncil de profundidade, especifique DepthStencilState.Default.
rasterizerEstado Estado Rasterizer Especifica um método de rasterização, como abate de retorno. Se null for especificado, o padrão RasterizerState.CullCounterClockwise será especificado.

Para desenhar um sprite, especifique um valor de profundidade como o nono argumento para o método SpriteBatch.Draw. Os valores que podem ser definidos aqui estão na faixa de 0,0 ~ 1,0, sendo 0,0 o mais importante e 1,0 o mais recuado.

// 最背面に描画(赤)
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 método

Adiciona um sprite à lista de lotes de desenho de sprite.

textura Textura2D Especifica a textura a ser exibida como um sprite.
posição Vetor 2 A posição em que o sprite deve ser exibido. Especifique as coordenadas da tela em relação ao canto superior esquerdo da tela. A origem do sprite estará na posição superior esquerda.
sourceRectangle Anulável<Retângulo> Especifica a área de transferência para a textura. Se você quiser que toda a textura seja exibida como um sprite, você pode especificar null. Se você especificar esse parâmetro, poderá fazer com que apenas uma área arbitrária apareça como um sprite.
Cor Cor Especifica a cor para multiplicar a cor do sprite. Se você especificar Color.White, ele será exibido na cor primária do sprite. Se Color.Black for especificado, o sprite será exibido em preto total, independentemente de sua cor. A fórmula é "Resultado = cor do sprite * cor".
rotação flutuar O ângulo de rotação do sprite. As unidades são especificadas em radianos. O eixo de rotação estará no canto superior esquerdo do sprite.
origem Vetor 2 Especifica a posição do eixo de rotação ao girar o sprite. Você especifica qual posição do sprite é o eixo de rotação, mas, na realidade, a posição do eixo de rotação é fixada no canto superior esquerdo do sprite e a posição de exibição do sprite é movida por -origin.
escala flutuar Especifica a ampliação do sprite. Dimensiona vertical e horizontalmente em relação a 1,0. A origem da ampliação estará no canto superior esquerdo do sprite.
Efeitos Efeitos de sprite Especifica o efeito de inversão do sprite. Se você não fizer mais nada, especifique SpriteEffects.None.
layerDepth flutuar Especifica a profundidade na qual o sprite é exibido. É usado principalmente para exibir sprites em primeiro plano e atrás. Especifique no intervalo de 0,0 ~ 1,0, onde 0,0 é a frente e 1,0 é a parte de trás.

No programa acima, o método SpriteBatch.Draw é chamado na ordem de "vermelho", "verde" e "azul", mas cada valor de profundidade é definido como "vermelho (1,0)", "verde (0,0)" e "azul (0,5)", para que você possa ver que o vermelho é desenhado na parte de trás e o verde é desenhado em primeiro plano.

深度値を使用したスプライトの描画

Todos os códigos

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