Sorteio XNA:usando um spritebatch em todo o jogo
-
13-12-2019 - |
Pergunta
Estou desenvolvendo um jogo XNA.É hora de ter cuidado com a arquitetura.Até hoje, sempre implementei meu próprio método de desenho desta forma:
public void Draw(SpriteBatch sb, GameTime gameTime)
{
sb.Begin();
// ... to draw ...
sb.End();
}
Eu estava pesquisando o DrawableGameComponent e vi que o método Draw vem desta forma:
public void Draw(GameTime gameTime)
{
// ...
}
Primeiro de tudo, eu sei que SpriteBatch pode coletar muitos Texture2D entre Begin e End, então pode ser útil classificá-los ou desenhar com os mesmos efeitos.
Minha dúvida é sobre o desempenho e o custo de aprovação no SpriteBatch.Em DrawableGameComponent é possível chamar spritebatch do objeto do jogo se seu spritebatch for público.
O que é sugerido, o que um programador de jogos xna deve fazer?
Obrigado em conselhos.
Solução
Uma das sérias desvantagens DrawableGameComponent
é que você está bloqueado na assinatura do método fornecido.Embora não haja nada de “errado”, por si só, com DrawableGameComponent
, não pense nisso como o "uma verdadeira arquitetura".Você é melhor pensando nisso como um exemplo de uma possível arquitetura.
Se você precisar passar por um SpriteBatch
(ou qualquer outra coisa) ao método draw de um "componente do jogo" - a melhor maneira é para passá-lo como um argumento.Qualquer outra coisa é complicada.
Obviamente, isso significa que você não pode usar os recursos fornecidos pelo XNA GameComponent
sistema, e você tem que fazer sua própria alternativa.Mas isso é quase trivial:Em seu nível mais básico, é apenas uma lista de algum tipo base que possui métodos virtuais apropriados.
Claro, se você precisar usar GameComponent
- ou seu jogo é tão simples (por exemplo:um protótipo) que você realmente não se importa com a arquitetura - então você pode usar basicamente qualquer método que você gosta de obter um SpriteBatch
ao seu método de desenho.Todos eles têm desvantagens.
Provavelmente o próximo método arquitetonicamente mais robusto é passar seu SpriteBatch
instância no construtor de cada um dos seus componentes.Isso mantém seus componentes desacoplados da sua classe de jogo.
Por outro lado, se você está jogando a arquitetura ao vento, sugiro que faça o seu MyGame.spriteBatch
campo public static
.Esta é a maneira mais simples de permitir que ele seja acessado em qualquer lugar.É fácil de implementar e limpar mais tarde, quando/se necessário.
Para responder à sua pergunta sobre desempenho:Qualquer coisa que tenha a ver com passar um SpriteBatch
ao redor terá um efeito quase insignificante no desempenho (fornecendo a ordem das chamadas para Draw
/Begin
/End
continua o mesmo).Não se preocupe com isso.
(Se você ver SpriteBatch whatever
no código, isso representa uma referência.Uma referência é um valor de 32 bits (em um programa de 32 bits, como são todos os jogos XNA).É do mesmo tamanho de um int
ou um float
.É muito pequeno e muito barato para circular/acessar/etc.)
Outras dicas
Se você se deparou com essa questão, provavelmente estava procurando uma solução agradável e genérica.Eu sugiro que você dê uma olhada nisso:
Senti a necessidade de corrigir esta questão porque "a melhor maneira é passar isso como um argumento.Qualquer outra coisa é complicada." e simples incorreto.
Pessoalmente, agora estou fazendo assim na minha classe GameBase:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
SpriteBatch = new SpriteBatch(GraphicsDevice);
this.Services.AddService(typeof(SpriteBatch), SpriteBatch);
}
Agora, como você está adicionando DrawableGameComponents no método Initialize da sua classe Game, você poderá chamar
this.Game.Services.GetService(typeof(SpriteBatch))
Eu diria que essa é a abordagem mais limpa para resolver o problema.
Se o DrawableGameComponent
deveria fazer parte dos pais SpriteBatch
, basta passá-lo por meio do construtor e armazená-lo em um membro privado (ou expô-lo como uma propriedade, se desejar).
Você também pode expor o SpriteBatch
como propriedade sua Game
class se você quiser, como você sugeriu, mas toda vez que você referenciou this.Game
, você precisaria lançá-lo para seu específico Game
tipo de classe.
((MyGame)this.Game).SpriteBatch.Draw(...)
Ou você pode simplesmente ter o DrawableGameComponent
crie um novo SpriteBatch
.Não há nada de errado com isso (até onde eu já vi).Suponho que depende de quantos DrawableGameComponent
o que você criará e com que frequência.
Navegue também pelos resultados para um procurar DrawableGameComponent
- há muitos bons conselhos aí.