Android glatte Spielschleife

Ich habe Probleme mit einem reibungslosen Scrollen in OpenGL (Test auf SGS2 und ACE)
Ich habe einfache Anwendungen – nur feste Geschwindigkeit horizontale Bildlauf von Bildern, oder nur ein Bild (Spieler) bewegen mit Beschleuniger, aber es ist Bewegung ist nicht glatt 🙁
Ich habe viele verschiedene Code ausgesucht, aber keine Zufriedenheit …

Zuerst habe ich versucht, mit GLSurfaceView.RENDERMODE_CONTINUOUSLY zu arbeiten und ich stelle alle Code auf onDrawFrame:

  • Wie kann ich ein Fragment eines FragmentPagerAdapter aktualisieren?
  • TextView ClickableSpan Styling für gedrückten Zustand
  • Erkennung aller Berührungsereignisse ohne Überlagerung dispatchTouchEvent ()?
  • So verschieben Sie die Tasten Text, wenn der Zustand gedrückt wird
  • Wie überschreibst du ein Modul / eine Abhängigkeit in einem Unit-Test mit Dagger 2.0?
  • Fügen Sie ein Kontrollkästchen "Remember me" hinzu
  • public void onDrawFrame(GL10 gl) { updateGame(gl, 0.017f); drawGame(gl); } 

    Das ist das einfachste und absolut glatt !! – aber es ist abhängig von Hardware-Geschwindigkeit (= nutzlos)

      public void onDrawFrame(GL10 gl) { frameTime = SystemClock.elapsedRealtime(); elapsedTime = (frameTime - lastTime) / 1000; updateGame(gl, elapsedTime); drawGame(gl); lastTime = frameTime; } 

    Das ist das beste von allen, aber es ist nicht so glatt wie die vorherigen, manchmal flick

    Zweitens habe ich versucht GLSurfaceView.RENDERMODE_WHEN_DIRTY , in onDrawFrame Ich habe nur Zeichnung Objekte und diesen Code in separaten Thread:

      while (true) { updateGame(renderer, 0.017f); mGLSurfaceView.requestRender(); next_game_tick += SKIP_TICKS; sleep_time = next_game_tick - System.currentTimeMillis(); if (sleep_time >= 0) { try { Thread.sleep(sleep_time); } catch (Exception e) {} } else { Log.d("running behind: ", String.valueOf(sleep_time)); } } 

    Das ist nicht glatt und es ist kein Problem mit "hinterlaufen"

    Mein Ziel ist glatte Bildbewegung wie im ersten Codebeispiel oben.

    Mögliche Fehler ist irgendwo anders dann schaue ich Bitte, Kann mir jemand helfen?
    Ist besser Gebrauch RENDERMODE_WHEN_DIRTY oder RENDERMODE_CONTINUOUSLY?

    Vielen Dank.

  • So öffnen Sie das Untermenü nach dem Klicken auf Menüpunkt in der Navigationsschublade?
  • Android Studio mit 100% CPU auf einem i7 Prozessor für Projekt Rebuild
  • LinearLayout vs RelativeLayout
  • java.lang.SecurityException: Permission Denial: Eröffnungsanbieter com.google.android.apps.photos.content.GooglePhotosImageProvider
  • Duplizieren von Dateien während der Verpackung eines APK
  • Android: Kann keine vertikale Lücke zwischen Bildern in LinearLayout entfernen
  • One Solution collect form web for “Android glatte Spielschleife”

    Ich kämpfte mit dem exakt gleichen Thema für mehrere Tage. Die Schleife sieht glatt aus ohne Android-Zeitreferenz, aber sobald es jede Art von "Zeit-Synchronisierung" enthält, führen externe Faktoren aus der Android-Entwicklungssteuerung ernsthafte Diskontinuitäten zum Endergebnis ein.

    Grundsätzlich sind diese Faktoren:

    • EglSwapInterval ist nicht in Android implementiert, so ist es schwierig zu wissen, den Moment, wenn die Hardware die endgültige Zeichnung im Bildschirm (Hardware-Bildschirm synchronisieren)
    • Thread.sleep ist nicht genau. Das Thread kann mehr oder weniger als gewünscht schlafen.
    • SystemClock.uptimeMillis () System.nanoTime (), System.currentTimeMillis () und andere zeitbezogene Messungen sind nicht genau (genau).

    Das Problem ist unabhängig von der Zeichnungstechnik (Zeichnung, openGL 1.0 / 1.1 und 2.0) und der Spielschleifenmethode (fester Zeitschritt, Interpolation, variabler Zeitschritt). Wie Sie, ich habe versucht Thread.sleep, verrückte Interpolationen, Timer, etc. Egal, was Sie tun werden, haben wir keine Kontrolle über diese Faktoren.

    Nach vielen Fragen und Antworten auf dieser Seite sind die Grundregeln, um reibungslose, kontinuierliche Animationen zu erzeugen:

    • Reduzieren Sie auf dem Minimum das GC, indem Sie alle dynamischen Speicheranforderungen entfernen.
    • Render Frames so schnell die Hardware kann sie verarbeiten (40 bis 60fps ist in den meisten Android-Geräte in Ordnung).
    • Verwenden Sie feste Zeitschritte mit Interpolation oder variablen Zeitschritten.
    • Optimieren Sie die Aktualisierungsphysik und zeichnen Sie die Routine, die in relativer konstanter Zeit ohne hohe Peak-Varianz ausgeführt werden soll.

    Sicherlich haben Sie eine Menge vorherige Arbeit gemacht, bevor Sie diese Frage stellen, indem Sie Ihre updateGame () und drawGame () (ohne nennenswerte GC und relative konstante Ausführungszeit) optimieren, um eine glatte Animation in Ihrer Hauptschleife zu erhalten, wie Sie erwähnen: " Einfach und absolut glatt ".

    Ihr besonderer Fall mit variablen stepTime und keine besonderen Anforderungen in perfekter Synchronisierung mit realTime Events (wie Musik), die Lösung ist einfach: "reib den Schritt Zeitvariable".
    Die Lösung arbeitet mit anderen Spielschleifenschemata (fester Zeitschritt mit variablem Rendering) und ist einfach, das Konzept zu portieren (glatt die Menge an Verschiebung, die durch das UpdateGame und die Echtzeituhr über mehrere Frames erzeugt wird.)

      // avoid GC in your threads. declare nonprimitive variables out of onDraw float smoothedDeltaRealTime_ms=17.5f; // initial value, Optionally you can save the new computed value (will change with each hardware) in Preferences to optimize the first drawing frames float movAverageDeltaTime_ms=smoothedDeltaRealTime_ms; // mov Average start with default value long lastRealTimeMeasurement_ms; // temporal storage for last time measurement // smooth constant elements to play with static final float movAveragePeriod=40; // #frames involved in average calc (suggested values 5-100) static final float smoothFactor=0.1f; // adjusting ratio (suggested values 0.01-0.5) // sample with opengl. Works with canvas drawing: public void OnDraw(Canvas c) public void onDrawFrame(GL10 gl){ updateGame(gl, smoothedDeltaRealTime_ms); // divide 1000 if your UpdateGame routine is waiting seconds instead mili-seconds. drawGame(gl); // Moving average calc long currTimePick_ms=SystemClock.uptimeMillis(); float realTimeElapsed_ms; if (lastRealTimeMeasurement_ms>0){ realTimeElapsed_ms=(currTimePick_ms - lastRealTimeMeasurement_ms); } else { realTimeElapsed_ms=smoothedDeltaRealTime_ms; // just the first time } movAverageDeltaTime_ms=(realTimeElapsed_ms + movAverageDeltaTime_ms*(movAveragePeriod-1))/movAveragePeriod; // Calc a better aproximation for smooth stepTime smoothedDeltaRealTime_ms=smoothedDeltaRealTime_ms +(movAverageDeltaTime_ms - smoothedDeltaRealTime_ms)* smoothFactor; lastRealTimeMeasurement_ms=currTimePick_ms; } // Optional: check if the smoothedDeltaRealTIme_ms is too different from original and save it in Permanent preferences for further use. 

    Für ein festes Zeitschritt-Schema kann ein intermetiate updateGame implementiert werden, um die Ergebnisse zu verbessern:

     float totalVirtualRealTime_ms=0; float speedAdjustments_ms=0; // to introduce a virtual Time for the animation (reduce or increase animation speed) float totalAnimationTime_ms=0; float fixedStepAnimation_ms=20; // 20ms for a 50FPS descriptive animation int currVirtualAnimationFrame=0; // useful if the updateGameFixedStep routine ask for a frame number private void updateGame(){ totalVirtualRealTime_ms+=smoothedDeltaRealTime_ms + speedAdjustments_ms; while (totalVirtualRealTime_ms> totalAnimationTime_ms){ totalAnimationTime_ms+=fixedStepAnimation_ms; currVirtualAnimationFrame++; // original updateGame with fixed step updateGameFixedStep(currVirtualAnimationFrame); } float interpolationRatio=(totalAnimationTime_ms-totalVirtualRealTime_ms)/fixedStepAnimation_ms; Interpolation(interpolationRatio); } 

    Geprüft mit Leinwand und openGlES10 Zeichnung mit folgenden Geräten: SG SII (57 FPS), SG Note (57 FPS), SG Tab (60 FPS), unbranded Android 2.3 (43 FPS) langsamer Emulator läuft unter Windows XP (8 FPS). Die Testplattform zieht um 45 Objekte + 1 riesigen Hintergrund (Textur aus dem 70MP-Quellbild), die sich entlang eines Pfades bewegt, der in realen physikalischen Parametern (km / h und Gs) angegeben ist, ohne Spikes oder Flick zwischen mehreren Geräten (gut, 8 FPS auf dem Emulator Sieht nicht gut aus, aber seine Strömung bei konstanter Geschwindigkeit wie erwartet)

    Überprüfen Sie die Graphen, wie android die Zeit berichten. Manchmal berichtet Android eine große Delta-Zeit und nur die nächste Schleife ist es klein als der Durchschnitt, was bedeutet, ein Offset auf das Lesen von realTime Wert.

    Bildbeschreibung hier eingeben

    Mit mehr Details: Bildbeschreibung hier eingeben

    Wie Begrenzung der Framerate bei der Verwendung von Android GLSurfaceView.RENDERMODE_CONTINUOUSLY?

    System.currentTimeMillis vs System.nanoTime

    Hat die Methode System.currentTimeMillis () wirklich die aktuelle Zeit zurück?

    Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.