2012-10-21 5 views
0

J'essaie actuellement de faire un petit jeu pour Android.
J'essaie de mesurer le temps entre deux actions du jeu mais l'heure de début reste 0 quand j'essaye d'appeler la méthode currentTimeMillis() après avoir appelé la méthode gameThread.run() (gameThread est un runnable). Lorsque je le place avant l'appel run(), il fournit la bonne valeur.System.currentTimeMillis() renvoie 0 (zéro)

Classe Gameview:

@Override 
public void surfaceCreated(SurfaceHolder holder) 
{ 
    // at this point the surface is created and we start the gameloop 
    gameThread.setRunning(true); 
    gameThread.run(); 
    begin=System.currentTimeMillis(); 
} 

/** 
* This is the game update method. It iterates through all the objects and 
* calls their update method 
*/ 
public void update() 
{ 
    for (GuiElement element : guiElements) 
    { 
     element.update(); 
    } 
    count++; 
    if (ball.getPosY() >= Statics.DISPLAY_HEIGTH - ball.getRadius()) 
    { 
     Log.d(TAG, "Displayhoehe : " + Statics.DISPLAY_HEIGTH); 
     Log.d(TAG, "DisplayfactorHeight : " + Statics.DISPLAY_FACTOR_HEIGHT); 
     Log.d(TAG, "speedvalue : " + ball.getSpeedY()); 
     Log.d(TAG, "ballradius : " + ball.getRadius()); 
     Log.d(TAG, "am boden mit " + count + " schritten"); 
     gameThread.setRunning(false); 
     end = System.currentTimeMillis(); 
     Log.d(TAG, "begin, end " + begin + " " + end); 
     Log.d(TAG, "time " + (end - begin)); 
    } 
} 

classe GameThread (implémente runnable)

public void run() 
{ 
    Canvas canvas; 
    Log.d(TAG, "Starting game loop"); 

    long beginTime; // the time when the cycle begun 
    long timeDiff; // the time it took for the cycle to execute 
    int sleepTime; // ms to sleep (<0 if we're behind) 
    int framesSkipped; // number of frames being skipped 

    while (running) 
    { 
     canvas = null; 
     // try locking the canvas for exclusive pixel editing in the surface 
     try 
     { 
      canvas = surfaceHolder.lockCanvas(); 

      synchronized (surfaceHolder) 
      { 
       beginTime = System.currentTimeMillis(); 
       framesSkipped = 0; // resetting the frames skipped 
       // update game state 
       gameView.update(); 
       // draw state to the screen 
       gameView.draw(canvas); 
       // calculate how long did the cycle take 
       timeDiff = System.currentTimeMillis() - beginTime; 
       // calculate sleep time 
       sleepTime = (int) (FRAME_PERIOD - timeDiff); 

       if (sleepTime > 0) 
       { 
        // if sleepTime > 0 we're OK 
        try 
        { 
         // send the thread to sleep for a short period very 
         // (useful for battery saving) 
         Thread.sleep(sleepTime); 
        } 
        catch (InterruptedException e) 
        { 
        } 
       } 

       while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) 
       { 
        // we need to catch up (skip some draw() calls) 
        this.gameView.update(); // update without rendering 
        sleepTime += FRAME_PERIOD; // add frame period to check 
               // if we catched up 
        framesSkipped++; 
       } 
      } 
     } 
     finally 
     { 
      // in case of an exception the surface is not left in an inconsistent state 
      if (canvas != null) 
      { 
       surfaceHolder.unlockCanvasAndPost(canvas); 
      } 
     } 
    } 
} 

EDIT: j'ai essayé de connecter la valeur de retour de currentMillis() au point de départ et il semble que la méthode est appelée après que la méthode run() a terminé. Ne devrait-il pas fonctionner de manière synchrone?

@Override 
public void surfaceCreated(SurfaceHolder holder) 
{ 
    // at this point the surface is created and we start the gameloop 
    gameThread.setRunning(true); 
    gameThread.run(); 
    begin=System.currentTimeMillis(); 
    Log.d(TAG, "currentMillis at beginning " + System.currentTimeMillis()); 
} 

Log:

10-21 19:43:17.480: D/GameView(19767): Displayhoehe : 480 
10-21 19:43:17.480: D/GameView(19767): DisplayfactorHeight : 1.0 
10-21 19:43:17.480: D/GameView(19767): speedvalue : 1.6666666666666667 
10-21 19:43:17.480: D/GameView(19767): ballradius : 20 
10-21 19:43:17.480: D/GameView(19767): am boden mit 133 schritten 
10-21 19:43:17.480: D/GameView(19767): begin, end 0 1350841397483 
10-21 19:43:17.480: D/GameView(19767): time 1350841397483 
10-21 19:43:17.480: D/GameView(19767): currentMillis at beginning 1350841397484 

Solution: J'ai commencé le Runnable mal. C'est la bonne façon de commencer la Runnable:

gameThread.setRunning(true); 
Thread t = new Thread(gameThread); 
t.start(); 
begin=System.currentTimeMillis(); 
+0

Il est impossible que System.currentTimeMillis() renvoie 0 (sauf si vous avez défini l'horloge système au 1er janvier 1970). Où notez-vous la valeur? – asenovm

+0

Quel est le problème de le placer avant 'run()'? – Eric

+0

Ce n'est pas vraiment faux, mais je veux comprendre pourquoi cela arrive. – Refrigerator

Répondre

3

C'est parce que vous appelez la méthode run() directement au lieu d'appeler la méthode start() du fil.

+1

Il a noté que gameThread est en fait un runnable (malgré un mauvais nom). Et encore qu'est-ce que cela a à voir avec System.currentTimeMillis() retournant 0 (si c'est possible du tout). – asenovm

+0

Merci, c'est embarrassant que j'ai démarré le Runnable de manière incorrecte ... – Refrigerator

+0

Si c'est le cas - quelques autres choses à mentionner: * Posez vos questions correctement - System.currentTimeMillis n'a jamais retourné 0 * nommez vos variables correctement - ie gamerThread n'est pas un thread, mais un runnable * Utilisez System.nanoTime() au lieu de System.currentTimeMillis() car ce dernier dépend de la plus petite quantité de temps pouvant être mesurée (spécifique au système d'exploitation) * ne jamais simplement avaler un Interrupted exception - la bonne façon de gérer cela est d'arrêter quelque chose/d'arrêter l'exécution du thread, ou de réinitialiser le drapeau interrompu (en appelant 'Thread.currentThread() .interrupt()'. – asenovm