2010-05-20 14 views
5

Estoy escribiendo un programa de edición de mapas para un juego 2D usando XNA. Crear un Texture2D para todos los mosaicos que requiere un mapa lleva demasiado tiempo.¿Existe una alternativa más rápida al uso de texturas en XNA?

¿Hay alguna alternativa al uso de texturas para dibujar con XNA?

Intenté crear una sola textura por conjunto de mosaicos en lugar de una textura para cada azulejo en un conjunto de mosaicos, pero hay un límite en el tamaño de las texturas y no cabía todas las fichas de un mosaico en una textura.

Actualmente el programa contiene todas las texturas posibles en la memoria como objetos Bitmap. ¿Hay alguna forma de dibujar un objeto Bitmap a la pantalla en XNA? He buscado pero no puedo encontrar ninguna información sobre esto. Este enfoque evitaría tener que crear texturas por completo, sin embargo, cualquier tinte o efectos que tendría que hacer directamente con el mapa de bits.

Respuesta

0

Desafortunadamente, hasta donde yo sé, no hay forma de dibujar directamente un mapa de bits en la pantalla en XNA; requiere que todo esté asignado a los objetos Texture, que se guardan de forma predeterminada en la tarjeta gráfica. Aunque parece que estás hablando de muchos mosaicos, si no todos encajan en la textura máxima permitida (no recuerdo si era 1024 o 4096 cuadrados ...), ¿has intentado tener una textura sin búfer para fines de velocidad? Otra alternativa sería cargar perezosamente los tilesets en texturas para que el usuario no tenga que esperar a que todos se carguen. Para un editor, usar un color rosa brillante de retorno suele ser aceptable mientras se carga.

Además, ¿hay algo inherentemente necesario para escribir su herramienta en XNA? Como parece que está escribiendo la herramienta por separado del motor del juego, es posible que encuentre algunas soluciones muy aceptables en WPF, incluido el dibujo directamente de BitmapSources y algunas utilidades para su UI.

+0

Gracias por la respuesta, no hay nada que me obligue a usar XNA, no. En este momento, he vuelto a trabajar en una versión de C++ y DirectX de la herramienta. Mi problema es que las texturas en XNA parecen ser increíblemente lentas. Lo que toma más de 100 segundos usando XNA Texture2Ds toma 0.3 segundos usando texturas DirectX. Gracias por la franqueza, principalmente lo que quería saber es que no hay forma de dibujar directamente un mapa de bits en la pantalla. –

0

Suponiendo que todas las fichas que un mapa requieren imágenes existentes que simplemente están colocando en una pantalla para diseñar un mapa de mosaico? ¿O estás creando imágenes en este editor de mapas y quieres guardarlas?

He leído esto y tu otra publicación sobre texturas. Si están todas las imágenes definidas que quieres usar en tu juego, ¿no podrías incluirlas en la carpeta de contenido y consultarlas allí? Esto le permite a XNA compilar las texturas en el formato xnb y no debería tener los problemas que está explicando.

Sin embargo, si estamos hablando completamente dinámico, o está creando una imagen grande desde el diseño de las teselas (en lugar de hacer algo como un mapa de mosaicos), entonces no estoy seguro de cómo abordar el problema.

+0

Hola, gracias por su respuesta. El problema de simplemente agregar los archivos de imagen a la carpeta de contenido es que son imágenes de formato personalizado; mi editor de mapas es para un juego existente que usa estas imágenes.Tenía la esperanza de poder codificar el editor usando C# y XNA, sin embargo, ahora parece que tendré que volver a empezar y utilizar C++ y DirectX para lograrlo, ya que sé que las texturas de los mapas de bits son muy rápidas en DirectX. La razón principal por la que utilicé C# fue porque quería la facilidad de diseño de la interfaz de usuario, sin embargo, si no puedo usar C#, buscaré algo como Qt. –

+0

esa fue la razón por la que dudé al principio, pensé que debe haber una razón por la que no podrías usarlos en el directorio de contenido de tu juego y tu editor. ¡Lo siento, no tengo una mejor respuesta para ti! –

0

Si varias fichas usan la misma textura, será suficiente cargarla una sola vez.

Si el usuario incluye texturas en algún formato de archivo, puede convertirlo automáticamente a un formato de textura/imagen que es más rápido para sus necesidades.

+0

Gracias por su respuesta. Lamentablemente, solo cargo cada textura requerida una vez. Descubrí que simplemente agregando Texture2D tx = new Texture2D (dispositivo, ancho, alto); a mi código para cada textura requerida ¡aumenta el tiempo de carga para un mapa de 2.7 segundos a 74 segundos! Tenga en cuenta que los 2.7 segundos incluyen la creación de mapas de bits que contienen las texturas necesarias. Texture2D parece ser demasiado lento para crear texturas sobre la marcha. –

1

Dado que necesita utilizar un formato de imagen personalizado, si desea (por velocidad) puede intentar escribir importadores y procesadores de canalización de contenido personalizado para XNA (http://msdn.microsoft.com/en-us/library/bb447754.aspx), pero esto puede ser excesivo para lo que necesita hacer.

Veo que desea diseñar la GUI lo más fácilmente posible, incluso si estos problemas le obligan a usar un lenguaje como C++ para que pueda usar DirectX. En Visual C++ aún debería poder aprovechar visual Windows Forms layout si está usando Visual Studio.

0

¿Está tratando de dibujarlos todos con un único hilo de ejecución?

Pruebe multi-threading su juego. Enhebrar en C# es bastante fácil y es compatible con XNA.

En lugar de mirar su pantalla como un todo, intente dividirla en dos (o más) porciones. Es posible que necesite volver a escribir la función que está utilizando para dibujar (¡espero que no haya tirado todo directamente en su método Draw() !!) para tomar las coordenadas que establecen los límites de las regiones de dibujo.

+0

Mi programa ya tiene varios subprocesos. Un hilo se encarga de manejar los mensajes de la ventana mientras que un hilo secundario intenta cargar los mosaicos y crear texturas de ellos. Al momento de escribir esta pregunta aún no había agregado un método Draw porque primero necesitaba tener un método para cargar las texturas en un marco de tiempo razonable. –

1

¿Hay alguna razón por la que no haya considerado cargar la imagen una vez y luego pasar las coordenadas de desplazamiento xey al sombreador de píxeles?

Es, básicamente, establecer el C# así:

myGraphicsDevice.Textures[0] = whateverYourGiantMapTextureIs; 

foreach(MapChunk chunk in mapChunks) { 
    myShader.Effect.Parameters["xOffset"] = chunk.XOffset; 
    myShader.Effect.Parameters["yOffset"] = chunk.YOffset; 

    myGraphicsDevice.DrawIndexedPrimitives(your chunk drawing code here); 
} 

y luego el código de sombreado de la siguiente manera:

float4x4 World; 
float4x4 View; 
float4x4 Projection; 

float xOffset; 
float yOffset; 

sampler TextureSampler; 

struct VS_INPUT { 
    float4 Position : POSITION0; 
    float4 Color : COLOR0; 
}; 

VS_INPUT Transform(VS_INPUT Input) { 
    VS_INPUT Output; 

    float4 worldPosition = mul(Input.Position, World); 
    float4 viewPosition = mul(worldPosition, View); 
    Output.Position = mul(viewPosition, Projection); 
    Output.Color = Input.Color; 

    return Output; 
} 

float4 ColorTexture(VS_INPUT Input) : COLOR0{ 
    return Input.Color.rgba * tex2D(TextureSampler, float2(xOffset, yOffset)); 
} 

technique TransformColorTexture { 
    pass P0 { 
     VertexShader = compile vs_2_0 Transform(); 
     PixelShader = compile ps_2_0 ColorTexture(); 
    } 
} 

El código shader podría necesitar algún ajuste en el código existente, pero de lo contrario, debería hacer el truco.

1

Usar una textura por baldosa no es muy eficiente. Especialmente porque significa que no puedes hacer lotes (en ningún sentido real).

Si NECESITA tenerlos como texturas separadas en su proyecto de contenido por algún motivo (más fácil de editar un mosaico, etc.), puede compilarlos fácilmente en mosaico después de la carga. La forma de hacerlo es básicamente:

1: Cargar una serie de azulejos (digamos 40 32 * 32 tejas por ahora)

2: encontrar una textura agradable de tamaño para el tilemap: raíz cuadrada de 40 es 6. algo, por lo que redondeamos a 7. 7 * 32 es 224, lo cual es bueno, pero 256 es mejor, así que hagamos que la textura sea 256x256. (Puede crear un código que lo descubra sobre la marcha)

3: Cree un Rendertarget2D que sea del tamaño deseado.

4: Activar rendertarget.

5: Render azulejos en rendertarget:

int x, y = 0; 
foreach (var tile in allTiles) 
{ 
    RenderTile(tile, x*32, y*32); 
    x++; 

    if (x >= 8) 
    { 
     x = 0; 
     y++; 
    } 
} 

Para betch-render que tiene un vértice tampón con 4 x 40 vértices. cada conjunto de 4 tiene un valor que indica el índice del cuadrante al que pertenece (0,1,2, etc ...). En su sombreador tiene una matriz de matrices [40] para la posición de las teselas, así como una matriz de tileIndex (int [40]) para saber qué teselas representar desde el mosaico.

Lo siento, pero no tengo tiempo para escribir todo el shader de código en este momento: s

Un otro truco que he utilizado en nuestros juegos es pre-renderizado el nivel en grandes baldosas (640x360), lo que reduce mucho el número de llamadas, especialmente cuando se trata de más de 5 capas de fichas de diferentes tilesets. Lo único es que no funciona con mosaicos dinámicos (mosaicos animados, etc.), pero puede marcarlos y renderizarlos normalmente si lo desea ...

Cuestiones relacionadas