Recentemente ho perseguito lo sviluppo del gioco come un hobby e ho deciso che, per imparare lo sviluppo del gioco, avrei dovuto creare un gioco e renderizzare tutto da solo (senza l'uso di un motore di gioco). Ciò si è rivelato piuttosto complicato, tuttavia sto facendo grandi progressi. Tuttavia, ho riscontrato un problema che penso possa essere correlato al modo in cui i telefoni Android visualizzano la loro grafica e avrò bisogno di alcuni chiarimenti su questo problema.
Il problema
Il mio gioco contiene una serie di palline in un cannone; quando l'utente preme lo schermo, il cannone lancia le palline e il motore (che sto implementando) gestisce gli aggiornamenti delle informazioni sulla posizione e il rilevamento delle collisioni da lì. Ora, prima che avessi implementato il rilevamento delle collisioni, il mio gioco funzionava in modo molto fluido e reattivo, tuttavia quando ho detto al motore di disegnare il tallone solo se è entro i limiti e "rimbalzarlo" dal muro, sembrerebbe che il motore il ciclo ora richiede molto più tempo per essere eseguito.
Questo andrebbe bene, se non fosse per la latenza che sta fornendo all'utente l'esperienza. Ad esempio, quando lo schermo viene toccato ora , occorrono ~ 2 secondi per visualizzare la palla mentre si muove attorno allo schermo, e talvolta non appare affatto . In precedenza, la reazione era istantanea.
Inoltre, quando commento la parte di rilevamento delle collisioni del mio motore fisico, riprende il suo solito comportamento reattivo.
Quello che penso sta causando questo comportamento
Nota: ho ripreso questo presupposto (vedere "Informazioni sul debug" di seguito)
Penso che dal momento che non ho implementato un limitatore di frame per il mio gioco e che il rendering è veloce quanto l'hardware lo consentirà, che sta disegnando sullo schermo così tanti vecchi frame (in qualche buffer, forse?) Che è impegnato a disegnare mentre dovrebbe aggiornare la fisica. Sebbene il mio debug finora non abbia indicato che sia così, non riesco a giungere ad alcuna altra conclusione.
Qualche codice
Nota che questo codice sarà piuttosto confuso per capire non sapere cosa fa tutto. L'ho semplicemente incluso nel caso in cui qualcuno fosse particolarmente interessato ad avere del codice con cui lavorare. Le variabili sono chiarite sotto l'estratto.
PhysicsEngine.updateBeadPositions (float) :
private void updateBeadPositions(float delta){
//Update all of the beads currently on the board.
beads = control.getBoard().getValues();
temp_x = 0.0f;
temp_y = 0.0f;
//For each row...
for(Bead[] row : beads){
//For each bead...
for(Bead bead : row){
//If this bead exists...
if(bead != null){
temp_y = (float) (bead.getYCoordinate() * bead.getYVelocity() * delta);
//If the coordinates are within the bounds of the game
if(outwithVerticalBounds(temp_y, control.getBoard())){
//Set the X coordinate equal to the distance * the time differential (delta).
bead.setXCoordinate(temp_x);
//Set the X coordinate equal to the distance * the time differential (delta).
bead.setYCoordinate(temp_y);
}
}
}
}
//If the cannon Bead has been set...
if(control.getCannon().getReleased() != null){
//Update the cannon bead
if(control.getCannon().getReleased().getXVelocity() == PhysicsEngine.VELOCITY_STATIC && control.getCannon().getReleased().getYVelocity() == PhysicsEngine.VELOCITY_STATIC){
control.getCannon().getReleased().setXCoordinate(control.getCannon().getX());
control.getCannon().getReleased().setYCoordinate(control.getCannon().getY() - Cannon.PIVOT_Y_OFFSET);
}
else{
temp_x = control.getCannon().getReleased().getXCoordinate() + (control.getCannon().getReleased().getXVelocity() * delta);
temp_y = control.getCannon().getReleased().getYCoordinate() + (control.getCannon().getReleased().getYVelocity() * delta);
//TODO: Commented out collision checkers!
//If the horizontal coordinates are within the bounds of the game
if(!outwithHorizontalBounds(temp_x, control.getBoard())){
//If the vertical coordinates are within the bounds of game
if(!outwithVerticalBounds(temp_y, control.getBoard())){
//Set the X coordinate equal to the distance * the time differential (delta).
control.getCannon().getReleased().setXCoordinate(temp_x);
//Set the X coordinate equal to the distance * the time differential (delta).
control.getCannon().getReleased().setYCoordinate(temp_y);
}
//Otherwise...
else{
//Bounds off the wall in the y direction
control.getCannon().getReleased().setYVelocity(-1.0f * control.getCannon().getReleased().getYVelocity());
}
}
//Otherwise...
else{
//Bounce off the wall in the x direction (flip the x velocity)
control.getCannon().getReleased().setXVelocity(-1.0f * control.getCannon().getReleased().getXVelocity());
}
}
}
}
Qui, le variabili sono definite come:
control
è un riferimento al mio controller di gioco. Confeziona la maggior parte del codice di gioco.beads
è un riferimento all'array 2D che contiene attualmente le perline sulla scheda (escluso quello che si sta muovendo)delta
è la differenza di tempo tra le chiamate precedenti al motore fisico e la chiamata corrente
Vedi i commenti all'interno del codice per qualsiasi altra spiegazione.
PhysicsEngine.outwithHorizontalBounds (float, Board) :
private boolean outwithHorizontalBounds(float x, Board board){
//If the horizontal values are within the bounds...
if(x > (board.getRight() - bead_radius)){
return true;
}
if(x < (board.getLeft() + bead_radius)){
return true;
}
//Otherwise, it is not.
return false;
}
Il metodo ha outwithVerticalBounds(float, Board)
funzionalità equivalenti, ma nella direzione y.
La mia domanda
Che dire del rilevamento delle collisioni causerebbe l'inibizione così drastica del rendering dello schermo? So che è un'operazione molto intensa, ma il mio debug ha dimostrato che gli aggiornamenti della fisica si stanno completando contemporaneamente ai sorteggi.
Informazioni sul debug
Ultimo aggiornamento: 29 gen 2013 16:27 EST
Ecco un'aggregazione delle informazioni di debug che ho ottenuto finora. Aggiornerò questo col passare del tempo:
Il
update()
metodo all'interno del mio motore richiede in media solo.018 ms
l'esecuzione. Di solito, il ritardo passa a0.020 ms
quando tocco lo schermo per rilasciare il tallone.Dopo aver confrontato i tempi dei sorteggi e gli aggiornamenti del gioco, sembrerebbe che io avessi ragione: si stanno verificando contemporaneamente . Quindi, questo non potrebbe essere il problema, giusto?
Il
FPS
gioco è approssimativamente87
, spike casualmente a (nella fascia bassa)60 FPS
, tuttavia questo spike non è correlato al rilascio del tallone. Non ci sonoFPS
svantaggi nel fare questo. Ciò ha senso poiché l'unica parte che aumenta la sua complessità dopo il rilascio del cordone è laupdate()
chiamata, il disegno avviene comunque il più velocemente possibile.Dopo ulteriori test, è diventato evidente che non è così che lo schermo è in ritardo rispetto alla fisica. Ho provato questo con una semplice bandiera booleana in cui lo sfondo dello schermo diventava bianco quando lo toccavo, e questo accade immediatamente . Quindi, ci deve essere qualche altra causa per il tallone che non si disegna. Aggiornerò presto.
Informazioni supplementari
Ecco alcune informazioni supplementari che dovrebbero aiutarti a capire le mie circostanze:
Sto testando questo su un Google Nexus 7.
Ci sono alcune perline sulla mappa che vengono aggiornate contemporaneamente (circa 30), ma solo una di esse si sta muovendo.
Di solito, dopo che il tallone inizia a muoversi (dopo il ritardo iniziale e se effettivamente disegna), continua a muoversi in modo molto regolare.
È importante notare che sullo schermo sono presenti altri elementi dell'interfaccia utente che si aggiornano in risposta all'evento touch. Ad esempio, il tallone caricato nel cannone diventa un nuovo tallone quando viene toccato lo schermo (a indicare che è stato rilasciato), ma il tallone mobile non viene semplicemente disegnato.