I thread Android non riescono ad avvolgere la mia testa attorno al design


9

Sto avendo problemi ad avvolgere la testa attorno al design del gioco. Sulla piattaforma Android, ho un'attività e ho impostato la sua visualizzazione del contenuto con una visualizzazione della superficie personalizzata. La vista della superficie personalizzata funge da pannello e creo istanze di tutte le classi e faccio tutti i disegni e i calcoli.

Domanda: Devo invece creare le istanze di altre classi nella mia attività?

Ora creo una classe di thread personalizzata che gestisce il loop del gioco.

Domanda: Come posso usare questa classe in tutte le mie attività? O devo creare ogni volta un'istanza separata della classe thread estesa?

Nel mio gioco precedente, avevo più livelli che dovevano creare un'istanza della classe thread e nella classe thread dovevo impostare i metodi di costruzione per ciascun livello separato e nel ciclo usare un'istruzione switch per verificare quale livello deve rendere e aggiorna. Scusa se sembra confuso.

Voglio solo sapere se il metodo che sto usando è inefficiente (cosa che probabilmente lo è) e come progettare nel modo giusto. Ho letto molti tutorial là fuori e ho ancora molti problemi con questo particolare argomento. Forse un link ad alcuni tutorial che spiegano questo? Grazie.

Risposte:


13

Consiglio vivamente di avere un thread di rendering (usando Canvas/ OpenGL ES, Canvasprobabilmente è un po 'più facile da configurare) e un thread di gioco in cui metti la tua logica di gioco.

Per "caricare" effettivamente il gioco è possibile creare una classe GameEngine e renderlo il punto centrale dell'applicazione. Quando il tuo renderer è pronto, puoi creare un callback all'istanza GameEngine che creerà e avvierà due thread usando a Runnableper il rendering e un altro Runnableper la logica di gioco.

Codice di esempio:

Avvio dell'applicazione

private GameEngine engine;
private CanvasRenderer renderer;

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   // Create instances of your two Runnable classes and pass that into
   // the GameEngine constructor.
   // Create an instance of the game engine.
   engine = new GameEngine(canvasRunnable, gamelogicRunnable);
   renderer = new CanvasRenderer(this, engine); 
   setContentView(renderer); 
}

CanvasRenderer

private GameEngine engine;    

// Save your instance from the GameEngine reference in your constrcutor and make
// a global initializion for your GameEngine instance.  

@Override
public void surfaceCreated(SurfaceHolder holder) {  
   // One time setup here.
   // When your view is ready, make this callback to the 
   // GameEngine.
   engine.surfaceIsReady();
}

GameEngine

private Thread canvasThread;
private CanvasRunnable canvasRunnable;
// You should be able to figure out how to create a second thread
// where you should put your game logic. :)

// Constructor stuff like creating instances of your threads
// and passing references as you wish to those.
// Don't start the threads here.
// Remember to set references from your Runnable's into your Thread's 
// instances here!

/**
 * Callback. Now your renderer is ready and you
 * can start your threads.
 */
public void surfaceIsReady() {
   thread.setName("Canvas");
   thread.start();
   // Same for game logic.
}

Wow grazie. Mi è piaciuto come l'hai spiegato. Quell'unica spiegazione mi illumina l'intero concetto.
Semajhan,

@semajhan: chiedi solo se hai più problemi. :)

Questo è ciò che ho in testa: la classe GameEngine che funge da "collegamento" o "riferimento" a tutte le altre classi con il pannello. Attività> Pannello> GameEngine> tutte le altre classi.
Semajhan,

@semajhan: Esatto. Solo per tua conoscenza: se decidi di andare con OpenGL ESte dovresti sapere che il renderer ha OpenGL ESgià il suo thread e in quel caso non devi creare e avviare manualmente un nuovo Threade Runnableper quel sistema.

Ignora questo commento.
semajhan

3

In genere, il tuo loop di gioco è autonomo all'interno di una singola attività.

quando cambi Attività, metti in pausa / uccidi il tuo loop di gioco. Le attività separate dovrebbero corrispondere comunque alla messa in pausa del gioco (ad es. Perché sei passato a un'attività "invia e-mail agli amici" o "menu principale")

Per livelli extra, non dovresti creare o destituire alcun nuovo thread ... a meno che tu non sia passato a un "livello completo, caricando il livello successivo, attendi" Attività e dovrai riavviare il "gioco principale "Attività comunque. Ma anche in quel caso, non stai davvero realizzando thread "extra", stai solo creando un thread in quell'attività e uccidendo / riavviando / uccidendo / riavviando in sequenza ... quell'attività. ogni volta che viene completato un livello.


3

Se capisci il tedesco, questo tutorial è molto carino.

Per la lingua inglese posso consigliare questo tutorial

Per quanto riguarda la classe thread: non so se sia davvero necessario che tu possa fare riferimento a tutte le classi della tua applicazione. Nel mio gioco, l'ho risolto in questo modo:

La classe che è responsabile per disegnare la GUI principale ha un metodo di rendering overriden. In questo metodo viene chiamata una classe thread che aggiorna tutti gli elementi della GUI ed elabora gli input dell'utente.

Il thread è anche responsabile di mantenere un framerate costante. A seconda del gioco che stai sviluppando, questo potrebbe essere importante.


Quel tutorial tedesco è carino ma è stato tradotto approssimativamente vai google quindi è un po 'difficile da capire.
Semajhan,
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.