Questão
Quando você tem um jogo 2D que usa imagens muito grandes (maiores do que o seu hardware pode suportar), o que você faz? Talvez haja alguma solução interessante para esse problema que nunca me ocorreu antes.
Estou basicamente trabalhando em uma espécie de criador de jogos de aventura gráfica. Meu público-alvo são pessoas com pouca ou nenhuma experiência em desenvolvimento (e programação) de jogos. Se você estivesse trabalhando com esse aplicativo, não preferiria que ele resolvesse o problema internamente, em vez de pedir para "dividir suas imagens"?
Contexto
É sabido que as placas gráficas impõem um conjunto de restrições ao tamanho das texturas que podem ser usadas. Por exemplo, ao trabalhar com o XNA, você fica restrito a um tamanho máximo de textura de 2048 ou 4096 pixels, dependendo do perfil escolhido.
Normalmente, isso não representa um problema nos jogos 2D, porque a maioria deles possui níveis que podem ser construídos a partir de peças individuais menores (por exemplo, peças ou sprites transformados).
Mas pense em alguns jogos clássicos de aventura gráfica point'n'click (por exemplo, Monkey Island). As salas de jogos gráficos de aventura geralmente são projetadas como um todo, com poucas ou nenhuma seção repetível, como um pintor trabalhando na paisagem. Ou talvez um jogo como o Final Fantasy 7, que usa grandes fundos pré-renderizados.
Algumas dessas salas podem ficar bem grandes, abrangendo frequentemente três ou mais telas de largura. Agora, se considerarmos esses planos de fundo no contexto de um jogo moderno de alta definição, eles facilmente excederão o tamanho máximo de textura suportado.
Agora, a solução óbvia para isso é dividir o plano de fundo em seções menores que se encaixam nos requisitos e desenhá-las lado a lado. Mas você (ou seu artista) deve ser o único a dividir todas as suas texturas?
Se você estiver trabalhando com uma API de alto nível, talvez não deva estar preparado para lidar com essa situação e fazer a divisão e a montagem das texturas internamente (como um pré-processo, como o Content Pipeline do XNA ou em tempo de execução)?
Editar
Aqui está o que eu estava pensando, do ponto de vista da implementação do XNA.
Meu mecanismo 2D requer apenas um subconjunto muito pequeno da funcionalidade do Texture2D. Na verdade, posso reduzi-lo a essa interface:
public interface ITexture
{
int Height { get; }
int Width { get; }
void Draw(SpriteBatch spriteBatch, Vector2 position, Rectangle? source, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
}
O único método externo que eu uso que depende de Texture2D é SpriteBatch.Draw (), para que eu pudesse criar uma ponte entre eles adicionando um método de extensão:
public static void Draw(this SpriteBatch spriteBatch, ITexture texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
{
texture.Draw(spriteBatch, position, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
}
Isso me permitiria usar uma ITexture de forma intercambiável sempre que eu usasse um Texture2D antes.
Então, eu poderia criar duas implementações diferentes do ITexture, por exemplo, RegularTexture e LargeTexture, em que RegularTexture simplesmente envolvia um Texture2D comum.
Por outro lado, LargeTexture manteria uma lista de Texture2D correspondendo a cada uma das partes divididas da imagem completa. A parte mais importante é que chamar Draw () na LargeTexture deve poder aplicar todas as transformações e desenhar todas as peças como se fossem apenas uma imagem contígua.
Por fim, para tornar todo o processo transparente, eu criaria uma classe unificada de carregador de textura que atuaria como um Método de Fábrica. Ele pegaria o caminho da textura como parâmetro e retornaria uma ITexture que seria uma RegularTexture ou uma LargeTexture, dependendo do tamanho da imagem que excede ou não o limite. Mas o usuário não precisava saber qual era.
Um pouco exagerado ou soa bem?