2010-05-20 9 views
5

Sto scrivendo un programma di modifica delle mappe per un gioco 2D usando XNA. Per creare un Texture2D per tutte le tessere che richiede una mappa richiede troppo tempo.Esiste un'alternativa più veloce all'utilizzo delle trame in XNA?

Esistono alternative all'utilizzo di trame per il disegno con XNA?

Ho tentato di creare una sola trama per set di tessere invece di una trama per ogni piastrella in un set di tessere, ma c'è un limite alle dimensioni delle trame e non ho potuto adattare tutte le tessere di un set di tessere in una struttura.

Attualmente il programma contiene tutte le possibili trame in memoria come oggetti Bitmap. C'è un modo per disegnare semplicemente un oggetto Bitmap sullo schermo in XNA? Ho cercato ma non riesco a trovare alcuna informazione su questo. Questo approccio eviterebbe di dover creare trame del tutto, comunque qualsiasi colorazione o effetti che dovrei fare direttamente alla bitmap.

risposta

0

Sfortunatamente, per quanto ne so, non c'è modo di disegnare direttamente una bitmap sullo schermo in XNA; richiede che tutto sia mappato agli oggetti Texture, che sono di default bufferizzati sulla scheda grafica. Sembra che tu parli di molte tessere, però, se non si adattano tutte alla trama massima consentita (non riesco a ricordare se fosse 1024 o 4096 quadrati ...) - hai provato ad avere un trama senza buffer per scopi di velocità? Un'altra alternativa sarebbe quella di caricare pigro i tileset in trame in modo che l'utente non debba aspettare che tutti vengano caricati - per un editor, l'utilizzo di un colore di fallback rosa brillante è solitamente accettabile mentre viene caricato.

Inoltre, c'è qualcosa di intrinsecamente necessario per scrivere il tuo strumento in XNA? Poiché sembra che tu stia scrivendo lo strumento separatamente dal motore di gioco stesso, potresti trovare alcune soluzioni molto accettabili in WPF, incluso il disegno direttamente da BitmapSources e alcune utilità per l'interfaccia utente.

+0

Grazie per la risposta, non c'è nulla che mi richiede di usare XNA, no. In questo momento sono tornato a lavorare su una versione C++ e DirectX dello strumento. Il mio problema era che le trame in XNA sembrano essere incredibilmente lente. Ciò che richiede oltre 100 secondi con XNA Texture2D richiede 0,3 secondi utilizzando le trame DirectX. Grazie per l'immediatezza - principalmente quello che volevo sapere è che non c'è modo di disegnare direttamente una bitmap sullo schermo. –

0

Presupposto per tutte le tessere che una mappa richiede immagini esistenti che vengono semplicemente posizionate su uno schermo per disporre una mappa di tessere? O stai facendo delle immagini in questo editor di mappe e vuoi salvarle?

Ho letto questo e il tuo altro post sulle trame - Se sono tutte immagini pronte che vuoi usare nel tuo gioco, non potresti semplicemente includerle nella cartella dei contenuti e farvi riferimento lì? Ciò consente a XNA di compilare le trame nel formato xnb e non dovresti avere i problemi che stai spiegando.

Tuttavia, se stiamo parlando in modo completamente dinamico - o stai creando un'immagine grande dal layout delle tessere (invece di fare qualcosa come una mappa delle tessere), allora non sono sicuro di come affrontare il problema.

+0

Ciao, grazie per la tua risposta. Il problema con la semplice aggiunta dei file di immagine alla cartella del contenuto è che si tratta di immagini in formato personalizzato - il mio editor di mappe è per un gioco esistente che utilizza queste immagini.Speravo di poter codificare l'editor usando C# e XNA, tuttavia ora sembra probabile che dovrò ricominciare da capo e usare C++ e DirectX per realizzarlo, poiché so che le trame da bitmap sono molto veloci in DirectX. Il motivo principale per cui ho usato C# è stato perché volevo la facilità di progettazione dell'interfaccia utente, tuttavia se non posso usare C#, cercherò di utilizzare qualcosa come Qt. –

+0

questo è il motivo per cui ho esitato all'inizio, ho pensato che ci doveva essere un motivo per cui non potevi semplicemente usarli nella directory dei contenuti del tuo gioco e il tuo editore - mi dispiace non ho una risposta migliore per te! –

0

Se più riquadri utilizzano la stessa trama, sarà sufficiente caricarlo solo una volta.

Se l'utente include trame in qualche formato di file, è possibile convertirlo automaticamente in un formato di trama/immagine che è più veloce per le proprie esigenze.

+0

Grazie per la risposta. Sfortunatamente, carico una sola volta ogni texture richiesta. Ho scoperto che è sufficiente aggiungere Texture2D tx = new Texture2D (dispositivo, larghezza, altezza); al mio codice per ogni trama richiesta aumenta il tempo di caricamento di una mappa da 2,7 secondi a 74 secondi! Si noti che il 2,7 secondi include la creazione di Bitmap contenenti le texture necessarie. Texture2D sembra essere troppo lento per creare texture al volo. –

1

Poiché è necessario utilizzare un formato immagine personalizzato, se si desidera (per velocità) è possibile tentare di importare importatori e processori di pipeline di contenuti personalizzati per XNA (http://msdn.microsoft.com/en-us/library/bb447754.aspx), ma ciò potrebbe essere eccessivo per ciò che è necessario fare.

Vedo che si desidera progettare la GUI il più facilmente possibile, anche se questi problemi ti costringono a utilizzare un linguaggio come C++ in modo da poter utilizzare DirectX. In Visual C++ si dovrebbe comunque essere in grado di sfruttare visual Windows Forms layout se si utilizza Visual Studio.

0

Stai provando a disegnarli tutti utilizzando un singolo thread di esecuzione?

Prova il multi-threading del gioco. Il threading in C# è abbastanza semplice ed è supportato da XNA.

Invece di guardare lo schermo nel suo insieme, provare a dividerlo in due (o più) porzioni. Potrebbe essere necessario riscrivere la funzione che si sta utilizzando per disegnare (spero che non abbiate semplicemente scaricato tutto direttamente nel metodo Draw() !!) per prendere le coordinate che definiscono i confini delle regioni di disegno.

+0

Il mio programma è già multi-thread. Un thread si occupa di gestire i messaggi della finestra mentre un thread secondario tenta di caricare le tessere e di creare trame da esse. Al momento della stesura di questa domanda non avevo ancora aggiunto un metodo Draw in quanto prima avevo bisogno di un metodo per caricare le trame in un arco di tempo ragionevole. –

1

C'è qualche motivo per cui non si è considerato di caricare l'immagine una volta e quindi di passare in coordinate x e y allo pixel shader?

Si sarebbe fondamentalmente impostare il C# in questo modo:

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

E poi il codice dello shader in questo modo:

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

Il codice dello shader potrebbe essere necessario un po 'di raccordo nel codice esistente, ma in caso contrario dovrebbe fare il trucco

1

L'utilizzo di una trama per tessera non è molto efficiente. Soprattutto perché significa che non è possibile eseguire il batching (in senso reale).

Se è necessario averli come trame separate nel progetto di contenuto per qualche motivo (più facile modificare un riquadro, ecc.), È possibile compilarli facilmente in tilemaps dopo il caricamento. Come si esegue questa operazione è fondamentalmente:

1: Caricare un numero di tessere (diciamo 40 32 * 32 piastrelle per ora)

2: Capire una texture piacevole-size per l'tilemap: radice quadrata di 40 è 6.qualcosa, quindi andiamo fino a 7. 7 * 32 è 224, che è bello, ma 256 è più bello, quindi lasciamo la texture 256x256. (puoi creare il codice che lo capisca al volo)

3: Crea un Rendertarget2D che è la dimensione desiderata.

4: Attiva il rendering.

5: rendering piastrelle su renderTarget:

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

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

Per betch-renderizzare si dispone di un vertice-buffer con 4 * 40 vertici. ogni set di 4 ha un valore che indica l'indice del quad di appartenenza (0,1,2, ecc ...). Nel tuo shader hai una matrice di matrici [40] per la posizione delle tessere, così come una matrice di tileIndex (int [40]) per sapere quale tessera deve essere visualizzata dalla tilemap.

Mi dispiace, ma io non ho tempo per scrivere tutto shader-code in questo momento: s

Un altro trucco che ho usato nei nostri giochi è pre-rendering del livello su grandi formati (640x360), che riduce di molto il numero di sorteggi, specialmente quando si ha a che fare con più di 5 strati di tessere da diversi tileset. L'unica cosa è che non funziona con le tessere dinamiche (piastrelle animate, ecc.), Ma puoi contrassegnarle e renderle normalmente se vuoi ...

Problemi correlati