2013-05-15 14 views
14

Ho creato un visualizzatore di immagini XNA, ma ridisegna sempre la scena, anche se non cambia, e sta facendo bruciare il mio netbook all'inferno, quindi mi piacerebbe che mandi in pausa il disegno quando non sta cambiando nulla.Come mettere in pausa il ridisegno in XNA?

Ridurre il framerate a 1 è un modo per mantenerlo freddo, ma risulta in uscita lenta.

Come si impedisce il riavvolgimento mentre non è presente alcun input?


Questo problema è stato risolto, ma è stato trovato un altro problema - il gioco consuma un sacco di CPU quando la sua finestra è a fuoco, ma quando non lo è, ci vogliono solo circa l'1% della CPU. Vedere questa domanda per i dettagli su come risolvere questo altro problema:

How to reduce XNA game CPU usage while nothing worth computing is happening?

+0

Questo è stato un rapido downvote e un voto ravvicinato. Cura di aiutare a migliorare la domanda? – user1306322

+3

Sarebbe bello se le persone lasciassero commenti per spiegare i loro downvotes. Questa sembra una domanda perfettamente legittima con una risposta definitiva. –

risposta

10

È possibile utilizzare il metodo Game.SupressDraw per questo scopo. Dalle osservazioni al collegamento:

Chiamare questo metodo durante l'aggiornamento per impedire le chiamate a Draw fino a dopo la chiamata successiva all'aggiornamento. Questo metodo può essere utilizzato su dispositivi di piccole dimensioni per conservare la durata della batteria se il display non cambia in seguito all'aggiornamento. Ad esempio, se lo schermo è statico senza animazioni di sfondo, durante l'aggiornamento è possibile esaminare l'ingresso del giocatore per determinare se il giocatore sta eseguendo un'azione. Se non viene rilevato alcun input, questo metodo consente al gioco di saltare il disegno fino al prossimo aggiornamento.

Ad esempio, il codice seguente richiamerà la funzione Draw una sola volta. Quando ho provato questo ho notato che l'utilizzo della CPU era alto (70%) senza la chiamata SuppressDraw. Quando si utilizza SupressDraw, l'utilizzo della CPU è diminuito drasticamente (a meno del 15%). I tuoi numeri possono variare.

public class Game1 : Microsoft.Xna.Framework.Game 
{ 
    ... 
    private bool _drawn = false; 
    protected override void Update(GameTime gameTime) 
    { 
     if (_drawn) 
      SuppressDraw(); 
    } 

    protected override void Draw(GameTime gameTime) 
    { 
     GraphicsDevice.Clear(Color.CornflowerBlue); 
     spriteBatch.Begin(); 
     /* draw stuff here */ 
     spriteBatch.End(); 

     _drawn = true; 
    } 
    ... 
} 

Nota che SupressDraw sopprime una sola Draw chiamata. Per evitare più chiamate a Draw, è necessario chiamare continuamente SupressDraw in Update. Spero che abbia senso.

+0

Funziona sicuramente, anche se non mi risparmia tanta CPU come speravo. L'analisi delle prestazioni dice che con ogni fotogramma disegnato soppresso, il metodo di aggiornamento principale ottiene tutta l'attenzione, ma continua a costare più CPU di prima.Immagino che la domanda posta sia una risposta, ma ho ancora bisogno di sapere come ridurre il costo della CPU di fare quasi nulla. – user1306322

+0

@ user1306322 - senza visualizzare il codice, è difficile fornire una risposta sul motivo per cui l'utilizzo della CPU non è stato ridotto. Come puoi vedere con la mia risposta sopra, ** ha ** ridotto il tempo della CPU del mio programma di esempio - dal 70% di utilizzo a circa il 15%. –

+0

Come hai detto, la percentuale varia. Immagino che la chiamata a Draw non stia effettivamente consumando una quantità significativa di risorse, mentre l'intera applicazione stava usando tutto quello che poteva ottenere (e lo fa ancora). Quindi, in pratica, questo è diventato un altro problema: determinare cosa esattamente consuma la CPU mentre in realtà non sta accadendo nulla di speciale oltre ad aspettare input e disegnare un frame 60 volte al secondo. – user1306322

0

Come dice la risposta accettata, è possibile utilizzare SuppressDraw per evitare di disegnare una cornice invariata. Il metodo di aggiornamento verrà eseguito a prescindere, tuttavia, motivo per cui utilizza ancora più CPU di quanto previsto. Per evitare di usare tanta CPU, devi in ​​qualche modo evitare di aggiornare cose che sai non sono cambiate dall'ultimo frame.

presumo si sa questo allo stesso modo di sapere quando per sopprimere pareggio, così quello che dovete fare è riorganizzare il vostro Update-metodo come questo:

private void Update(GameTime gameTime) 
{ 
    var frameHasChanges = DetectChanges(); //This method you need to figure out yourself 
    if (!frameHasChanges) 
    { 
     SuppressDraw(); 
     base.Update(gameTime); 
     return; 
    } 

    //Do the rest of normal Update 

} 

Come nota finale; Non ho mai dovuto usarlo in nessun gioco che abbia mai fatto. Ciò che ritengo suggerisca che potresti avere qualche altro problema di fondo con le prestazioni. Ho, tuttavia, usato molte tecniche per evitare il rendering del testo e così via su ogni frame (causa boxing/unboxing). Chiedi questo in commento se vuoi saperne di più.

+0

Mentre in generale questa è la strada da percorrere, in questo caso specifico, come ho detto nella domanda, il metodo di aggiornamento è molto semplice e non può occupare tutta la CPU solo per verificare se ci sono stati cambiamenti negli stati di input (e no, l'ho quadruplicato). La soluzione è stata trovata attraverso una diversa domanda al problema che è apparso dopo aver risolto la cosa non ridisegna in questa domanda. Vedi le note a piè di pagina per i dettagli. – user1306322

Problemi correlati