J'ai récemment poursuivi le développement de jeux comme passe-temps et j'ai décidé que pour apprendre les avantages et les inconvénients du développement de jeux, je devais créer un jeu et tout rendre moi-même (sans utiliser de moteur de jeu). Cela s'est révélé assez compliqué, mais je fais de grands progrès. J'ai cependant rencontré un problème qui, je pense, pourrait être lié à la façon dont les téléphones Android rendent leurs graphiques et j'aurai besoin de clarifications à ce sujet.
Le problème
Mon jeu contient une série de boules dans un canon; lorsque l'utilisateur appuie sur l'écran, le canon lance les balles et le moteur (que j'implémente) gère les mises à jour des informations de localisation et la détection des collisions à partir de là. Maintenant, avant d'avoir implémenté la détection de collision, mon jeu s'est déroulé de manière très fluide et réactive, mais lorsque j'ai dit au moteur de ne tirer le cordon que s'il se trouve dans les limites et de le "rebondir" sur le mur sinon, il semblerait que le moteur la boucle prend désormais beaucoup plus de temps à s'exécuter.
Ce serait bien, si ce n'était de la latence qu'il fournit à l'expérience utilisateur. Par exemple, lorsque l'écran est touché maintenant , il faut environ 2 secondes pour que la balle s'affiche comme se déplaçant sur l'écran, et parfois elle n'apparaît pas du tout . Auparavant, la réaction était instantanée.
De plus, lorsque je commente la partie détection de collision de mon moteur physique, elle reprend son comportement réactif habituel.
Ce que je pense est à l'origine de ce comportement
Remarque: j'ai rétracté cette hypothèse (voir «Informations de débogage» ci-dessous)
Je pense que puisque je n'ai pas de limiteur d'image implémenté pour mon jeu, et qu'il rend aussi vite que le matériel le permet, qu'il dessine tant de vieilles images (dans un tampon, peut-être?) À l'écran qui il est occupé à dessiner alors qu'il devrait mettre à jour la physique. Bien que mon débogage jusqu'à présent n'ait pas indiqué que c'est le cas, je n'arrive pas à parvenir à une autre conclusion.
Du code
Notez que ce code va être assez déroutant pour comprendre ne pas savoir ce que tout fait. Je l'ai simplement inclus au cas où quelqu'un voudrait avoir du code avec lequel travailler. Les variables sont clarifiées sous l'extrait.
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());
}
}
}
}
Ici, les variables sont définies comme:
control
est une référence à mon contrôleur de jeu. Il regroupe la majorité du code du jeu.beads
est une référence au tableau 2D qui contient actuellement les billes sur la carte (à l'exception de celle qui se déplace)delta
est l'écart de temps entre les appels précédents au moteur physique et l'appel en cours
Voir les commentaires dans le code pour toute autre explication.
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;
}
La méthode outwithVerticalBounds(float, Board)
est de fonctionnalité équivalente, mais dans la direction y.
Ma question
Qu'en est-il de la détection des collisions qui empêcherait le rendu d'écran de manière si drastique? Je sais que c'est une opération très intensive, mais mon débogage a montré que les mises à jour physiques se terminent en même temps que les tirages.
Informations de débogage
Dernière mise à jour: 29 janv. 2013 16:27 EST
Voici une agrégation des informations de débogage que j'ai obtenues jusqu'à présent. Je vais mettre à jour cela au fil du temps:
La
update()
méthode au sein de mon moteur, ne prend, en moyenne, que.018 ms
pour s'exécuter. Habituellement, le délai monte jusqu'à0.020 ms
quand j'appuie sur l'écran pour libérer la perle.Après avoir comparé les heures des tirages et les mises à jour du jeu, il semblerait que j'avais raison: elles se produisent simultanément . Ainsi, cela ne pouvait pas être le problème, non?
Le
FPS
jeu est grosso modo87
, il pointe de façon aléatoire (à l'extrémité inférieure)60 FPS
, mais cette pointe n'est pas liée à la libération de la perle. Il n'y a aucunFPS
inconvénient à le faire. Cela a du sens puisque la seule partie qui augmente sa complexité après la libération du cordon est l'update()
appel, le dessin se fait toujours aussi vite que possible.Après de nouveaux tests, il est devenu évident que ce n'est pas le cas que l'écran est en retard sur la physique. J'ai testé cela avec un simple drapeau booléen dans lequel l'arrière-plan de l'écran devenait blanc lorsque je le touchais, et cela se produit immédiatement . Ainsi, il doit y avoir une autre cause pour que le cordon ne se dessine pas. Je mettrai à jour bientôt.
Information supplémentaire
Voici quelques informations supplémentaires qui devraient vous aider à comprendre ma situation:
Je teste cela sur un Google Nexus 7.
Il y a pas mal de perles sur la carte qui sont mises à jour en même temps (environ 30), mais une seule d'entre elles bouge.
Habituellement, après que le cordon commence à se déplacer (après le délai initial et s'il tire réellement), il continue à se déplacer de manière très fluide.
Il est important de noter que j'ai d'autres éléments d'interface utilisateur à l'écran qui se mettent à jour en réaction à l'événement tactile. Par exemple, la perle chargée dans le canon devient une nouvelle perle lorsque l'écran est touché (signifiant qu'elle a été libérée), mais la perle mobile n'est tout simplement pas tirée.