2010-07-17 17 views
5

Sto programmando un grande gioco in Java e sto cercando di ottimizzare il codice ma anche di mantenere il codice pulito e ben organizzato. Ora non sono sicuro se dovrei usare il campo statico pubblico delle singole classi che hanno un paio di variabili che sono utilizzate da molte istanze.Uso del campo statico pubblico, buona pratica di programmazione/veloce?

Ad esempio, la telecamera di classe ha una posizione xey che definisce quale parte della mappa l'utente sta guardando e cosa deve essere disegnato sullo schermo. Attualmente sto facendo il benchmark con 50.000 unità e ho le seguenti opzioni per disegnarle.

1: memorizzare un riferimento all'istanza della telecamera in ciascuna unità e chiamare coordinatax() e Gety() quando deve essere disegnato:

public void paint() 
{ 
    paint(x - camera.getX(), y - camera.getY()); 
} 

2: fornitura le coordinate della telecamera come argomenti a ciascuna unità quando opportuno richiamare:

public void paint(int cameraX, int cameraY) 
{ 
    paint(x - cameraX, y - cameraY); 
} 

3: Effettuare x e Y variabili della classe telecamera fissa:

public void paint() 
{ 
    paint(x - Camera.x, y - Camera.y); 
} 

Sono interessato a ciò che è generalmente considerato come la soluzione migliore e se influisce sulle prestazioni. Forse ci sono altri modi per farlo a cui non ho ancora pensato?

Grazie!

+0

Quando ho riscritto il mio codice per utilizzare i campi statici pubblici ho notato un calo nel framerate di circa 60 fps. Rotolando ho aumentato le prestazioni ai vecchi livelli ma non ho scoperto cosa ha causato il calo. Quindi immagino che mi prenderò un po 'più di tempo in più per impostare tutti i riferimenti e dimenticare le cose sul campo statico. Grazie per le risposte! – ArmoredSandwich

risposta

3

Io suggerirei si crea una classe pittore e procedere come segue:

public void paint(Painter painter) 
{ 
    painter.draw(x, y, unit_sprite); 
} 

In questo modo le unità non devono preoccuparsi circa l'esistenza di una macchina fotografica. Non è affare di nessuno come funziona. L'unità ha solo bisogno di sapere come attingersi allo schema di coordinamento globale e il pittore capirà in che modo si riferisce alle coordinate dello schermo.

Perché questo è una buona idea?

  • Riduzione del codice, ogni unità non deve preoccuparsi della traduzione nel frame di coordinate corretto. Tutto questo codice esiste una volta in una singola posizione.
  • Facilità di cambiamento. Ad esempio, si supponga di decidere di implementare una funzione di zoom. Se ogni unità eseguisse la propria traduzione sarebbe un dolore. Tuttavia, se tutta la logica è nel pittore, è possibile modificare il pittore per prendersi cura di riscalare le immagini e determinare le correzioni corrette.
  • dipendenze diminuito, le unità non sanno cosa una macchina fotografica è, sono più semplici perché non ti preoccupare.

quanto riguarda le vostre soluzioni proposte:

  1. Memorizzazione di un riferimento alla videocamera sul vostro oggetto assume ci sarà sempre solo una telecamera. Cosa succede se si implementa qualcosa come una visualizzazione divisa? Questo può essere improbabile, ma memorizzando il riferimento ti si blocca inutilmente praticamente in una sola prospettiva.
  2. Il problema con frazionamento delle variabili è che logicamente i due pezzi sono un elemento. Questo rende un po 'più difficile capire cosa sta succedendo, causerà problemi se un giorno avremo bisogno di più parametri e forniremo anche informazioni all'unità di cui realmente non ha bisogno.
  3. Questo soffre gli stessi problemi di # 1, esso si blocca in una sola telecamera in uso in tutto il luogo. L'unità non dovrebbe essere responsabile della definizione di come viene utilizzata la fotocamera.

quanto riguarda le prestazioni:

La differenza sta per essere quasi nulla. Non sono sicuro di quale metodo vincerà in una battaglia di prestazioni, ma posso dirti se hai problemi di prestazioni che andranno da qualche altra parte (immagino che in realtà funzioni blitting). Combinando tutto il codice relativo agli offset è una singola posizione, il mio metodo proposto renderà più facile implementare un'ottimizzazione. Ad esempio, un ottimizzazione comune non è disegnare cose che sono fuori schermo. Se hai 20 funzioni tutte per calcolare gli offset e richiamare le funzioni di disegno, dovrai andare a ciascuna di queste funzioni e cambiarle. Se usi un pittore, puoi semplicemente cambiare la classe del pittore per ignorare la richiesta di disegnare al di fuori dell'area visibile e il gioco è fatto.

Per quanto riguarda le variabili statiche in generale:

ritengo variabili statiche (e single) da variabili globali e quindi praticamente non li usano. Rendendoli statici mi lega a decisioni particolari. Non sono abbastanza intelligente per prendere tutte le giuste decisioni in anticipo e quindi ho bisogno che il mio codice sia flessibile.

Alcune linee guida:

  1. Se vi trovate a dover accedere ai dati all'interno di un oggetto, vale a dire la x, y valore di considerare se si dovrebbe invece dire che oggetto di fare qualcosa di essere richiamando un metodo. Cioè Dì non chiedere.
  2. Se un oggetto (come Painter) viene utilizzato solo per una determinata attività da un oggetto, dovrebbe essere un parametro e non una variabile membro.
+0

Wow, grazie per aver approfondito la mia domanda. Definirò sicuramente il mio approccio e implementerò una sorta di classe Painter. In realtà mi chiedo perché non mi sia venuta in mente una soluzione del genere finora. – ArmoredSandwich

2

Se si dispone di una sola telecamera in ogni momento, sceglierei la terza via. Altrimenti sceglierei la seconda strada.

Penso che dal punto di vista delle prestazioni, utilizzare un campo statico pubblico sia una buona idea. Per quanto riguarda la leggibilità del codice, se si comprende facilmente che esiste una sola telecamera in ogni momento, anche questo dovrebbe essere ok.

0

Nel complesso il secondo dovrebbe fornire un buon equilibrio; inoltre assicurerà di non tenere accidentalmente i riferimenti alla telecamera oltre a quelli previsti, o di non incorrere in conflitti con i campi statici di stato.

Ricorda che dovresti comunque profilare le prestazioni indipendentemente dalla soluzione scelta, ma non prevedere che si tratti di un collo di bottiglia fino a quando non avrai la prova che si tratta di una soluzione.

0

In tutti i linguaggi di programmazione, è sempre consigliabile utilizzare i metodi get/set per i membri statici e di istanza. Ciò consente di modificare le implementazioni interne in modo trasparente per un codice client, se necessario. Tuttavia, a volte queste regole sono infrante, se le prestazioni sono molto importanti.

+0

Non vero se la lingua supporta le proprietà. –

1

Dovrete punto di riferimento nel vostro contesto per essere sicuro, ma qui è la mia esperienza:

  • Passaggio di parametri alle funzioni è generalmente il più veloce se si dispone di un piccolo numero di parametri che verrà utilizzato molto in un anello interno. Questo perché JIT assegnerà questi ai registri
  • L'accesso alle variabili pubbliche dei membri statici è anche piuttosto veloce, solo i problemi a cui prestare attenzione sono potenziali problemi di concorrenza (ad esempio il motore potrebbe cambiare la posizione della telecamera mentre si è nel mezzo di rendering di un frame?)
  • L'accesso tramite un riferimento di istanza è più lento, ma comunque abbastanza veloce da essere utilizzabile in un gioco in tempo reale. Aiuta se la tua classe è definitiva e i metodi di accesso sono in linea, ovviamente.
0

Giusto il tempo e vedere.

long startTime = System.currentTimeMillis(); 
for(int i=0; i<1000000; i++){ 
    // Call your code 

} 
System.out.println("Total time " + (System.currentTimeMillis() - startTime) + " ms"); 

La mia ipotesi è il JIT si prenderà cura delle differenze e che saranno tutti più o meno equivalente. Non c'è sostituto per cronometrare te stesso. Inoltre, consiglierei di profilare l'app e vedere dove viene speso il tempo durante l'esecuzione dell'app prima di eseguire questi tipi di modifiche alle prestazioni micro.

1

Enumerare e calcolare in millisecondi su m.server utilizzando il vaule intero.

che è ospite senza guardare alcun libro.

0

Ho avuto la stessa domanda per lo stesso motivo (un grande gioco java).

Ho provato due modi per una variabile che rappresenta il tempo trascorso dall'ultimo fotogramma, è utilizzato in ogni istanza di ogni oggetto su ogni fotogramma.

Un modo è statico, l'altro è il passaggio di tale variabile come argomento verso il basso dal ciclo principale a ogni sottoclasse di ogni oggetto.

Qui sono i miei risultati: http://i.stack.imgur.com/WtSue.png

che ho provato ogni strada per 3 volte. Come puoi vedere i risultati sono piuttosto simili tranne che tra 130 e 210, non posso davvero spiegare il perché.

Problemi correlati