Java AWT è adatto per il rendering di giochi 2D?


8

[Ripubblicando questa domanda da StackOverflow, come è stato sottolineato che qui si adatta meglio.]

Attualmente sto trasferendo il mio motore di gioco 2D su Java. Ho guardato alcune delle librerie di giochi indicate qui su StackOverflow. Tuttavia, quelli che ho visto erano piuttosto semplicistici e non affermavano nemmeno se supportavano cose come la trasparenza alfa, quindi ho deciso di eseguire il porting del mio renderer C ++ per il quale avevo già scritto la logica.

Questo renderer è un renderer software puro che utilizza la piastrellatura per evitare il rendering non necessario. Ho ottimizzato le sue prestazioni di scorrimento creando un "buffer fuori schermo" un po 'più grande del mio riquadro di output e inserendo questo buffer fuori schermo sul mio output su ogni frame. In questo modo, potrei evitare di ridisegnare le tessere inutilmente solo perché ho fatto scorrere un pixel sulla mappa.

Ho usato l'AWT di Java per implementarlo, usando un grande BufferedImage per il buffer offscreen. L'uso della CPU va bene (circa il doppio di quello che avevo in C ++), ma c'è uno strano problema con lo scorrimento continuo, in cui ogni secondo circa il renderer rimarrà in ritardo per circa 0,2 secondi.

Dal momento che non c'è nulla nel mio codice che si verificherebbe in questi periodi, e poiché i picchi scompaiono se non disegno il mio buffer offscreen nella vista principale, posso solo concludere che Java sta facendo una propria ottimizzazione interna. Tuttavia, non sono sicuro di ciò che fa, né so quale delle mie ottimizzazioni avrei dovuto rimuovere per eliminare i picchi. Inoltre, potrebbe essere che java AWT non sia stato realizzato pensando allo scrolling continuo e elevato degli FPS, ed è del tutto inutilizzabile per questo scopo.

C'è un modo per sbarazzarmi di questi picchi?


4
Potrebbe essere il bidone della spazzatura che ti colpisce?
Bummzack,

@bummzack: possibilmente. Nel profiler è simile al seguente: i.imgur.com/EMxkA.png Tuttavia, non sono sicuro di come ridurre questo effetto, soprattutto se è causato dalle mie chiamate a graphics.drawImage
cib

Risposte:


4

Anche se non posso essere sicuro senza guardare il tuo codice, sembra che il tuo problema sia il garbage collector. In Java, ci sono raccolte di rifiuti maggiori e minori che si svolgono di tanto in tanto. Il minore consuma parte della tua CPU ma non ti disturberà troppo. Le principali raccolte possono essere un vero problema per le app in tempo reale come i giochi poiché in realtà metteranno in pausa tutto mentre sono in esecuzione.

Ci sono due opzioni per risolvere questo. Innanzitutto è possibile modificare JVM per assicurarsi che vengano eseguite meno raccolte principali. In secondo luogo (e consigliato), puoi assicurarti di non lasciare troppa spazzatura. Controlla semplicemente dove nella tua app crei molti oggetti (nei miei giochi quelli di solito sono le classi vector3) e assicurati di riutilizzarli il più possibile (specialmente nei circuiti interni ecc.).


2

Sì.

Per i giochi basati su sprite 2D, AWT può essere utilizzato per gestire il rendering con grande efficacia. Può anche essere accelerato dall'hardware , a seconda dell'hardware disponibile.

Senza alcun codice o snippet di profilazione dettagliato, è difficile dire quale sia il problema. Il meglio che posso fare è offrire alcuni suggerimenti di base per lavorare con Java e AWT durante la creazione di giochi.

Lavorare con il Garbage Collector

Il GC in Java è qualcosa che dobbiamo davvero tenere a mente mentre stiamo costruendo i nostri giochi. Funzionerà periodicamente e cercherà oggetti che non hanno alcun riferimento ad essi, e li rimuoverà dalla memoria. Questo processo di rimozione è lento ed è probabilmente la causa del problema che si sta verificando.

Il mio suggerimento è di evitare di creare riferimenti a oggetti che non saranno mantenuti in circolazione per tutta la durata dell'esecuzione (o almeno, per quanto possibile). L'obiettivo ideale è assicurarsi che il GC non abbia nulla da fare ogni volta che viene eseguito.

In pratica, potresti finire con molte variabili statiche che riutilizzi durante il gioco. Ecco un esempio molto ingegnoso di come tendo a gestirlo:

public final class Resources {
    public static Map<int, String> strings;
    public static Map<int, Texture> textures;
    public static Map<int, GameObject> objects;
    public static Map<int, SoundEffect> sounds;
}

Durante il caricamento delle schermate è possibile aumentare o ridurre le Mapistanze utilizzando la newparola chiave. Ma durante il gioco, ti consigliamo di evitarlo il più possibile. Se qualcosa viene distrutto durante il gioco, imposta una bandiera sull'oggetto in modo da sapere che non è qualcosa che è attualmente attivo. Se devi generare un nuovo oggetto, passa attraverso il tuo Mapfino a quando non ne trovi uno che non è attivo, imposta le sue proprietà e contrassegnalo come attivo.

Questo è qualcosa che dovresti tenere a mente quando usi Java per applicazioni sensibili alle prestazioni, indipendentemente dal fatto che tu stia utilizzando AWT, JavaFX o OpenGL per eseguire il rendering.

Tela

Per AWT in particolare, consiglio vivamente di utilizzare la classe Canvas per eseguire il rendering di tutto per vari motivi:

  • Hai un miglior controllo di quando le cose vengono visualizzate. Ciò significa che puoi scrivere il tuo loop di gioco e fare cose come interpolazione, estrapolazione, limitazione della velocità, ecc.
  • Sembra funzionare meglio. Sono stato in grado di ottenere più cose sullo schermo contemporaneamente a un frame rate accettabile rispetto al tentativo di animare un gruppo di oggetti Label e Image.
  • È più facile da incorporare negli editor. Essere in grado di impostare un Frame con i normali controlli della GUI e puntare la logica di rendering del tuo gioco su un Canvas mi ha permesso di riutilizzare il codice di rendering del gioco negli strumenti dell'editor.
  • Ti dà un facile accesso all'API Java2D (aka, la classe Graphics2D ).
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.