So erstellen Sie Update / Draw Loop passend mit android opengl?

Ich wollte ein einfaches Spiel in Android mit opengls schreiben, aber sofort lief in Schwierigkeiten mit der Hauptspielschleife. Als ich hier lese: http://developer.android.com/resources/tutorials/opengl/opengl-es10.html Die App ruft die public void onDrawFrame(GL10 gl) sie die Oberfläche neu zeichnen muss. Oder so gern Mein Problem war – wie man eine Update-Schleife erstellt, die unabhängig von Draw-Anrufen ist. Ich meine – es kann nicht so funktionieren, ich kann die Spiellogik erst dann aktualisieren, wenn das Gerät (App?) Die Oberfläche neu zeichnen möchte (oder bin ich falsch?).

Nach einigen googeln kam ich zu einer Schlussfolgerung, dass ich einen weiteren Thread für Update Loop erstellen muss. Aber dann hatte ich noch ein Problem – mit einem Thread, der sich um das Zeichnen kümmert und ein anderer, der sich um die Aktualisierung der Spiellogik kümmert, wusste ich nicht, wie man sie zusammenbringt. Zuerst waren sie zwei getrennte Klassen (zumindest in meiner Implementierung), so dass sie nicht die gleichen Spielvariablen und Objekte verwenden konnten (Sprites, Timer, verschiedene Variablen, Counter und so weiter … so ziemlich alles, was diese beiden Klassen tun mussten ihre Berufe). Jetzt denke ich, ich könnte sie irgendwie in eine Klasse packen. Aber zweitens musste ich die beiden Threads irgendwie synchronisieren.

Schließlich kam ich mit dieser allgemeinen Idee heraus:

  • 3 Klassen:
    1. public class MyRenderer implements GLSurfaceView.Renderer mit onSurfaceCreated() Methode, die sich um Zeichnung kümmert
    2. public class UpdateThread implements Runnable mit run() und update() Methoden. run() rief update() -Methode genau 60 mal pro Sekunde auf (ich wollte eine feste Step-Loop)
    3. public class SpritesHolder als Container für alle Spielobjekte / Variablen / Zeug (wie Sprites, Timer, Statusvariablen und so weiter …) mit allen Feldern öffentlich.
  • Also im Grunde genommen war die SpritesHolder Klasse eine Box, die alle benötigten Variablen an einem Ort hielt, so dass MyRenderer und UpdateThread Klassen darauf zugreifen konnten und es nutzen konnten.
  • Wie für die Synchronisation – das habe ich einfach so gemacht:

     public void update(float delta) { synchronized (spritesHolder) { // whole method code... } } 

    und:

     public void onDrawFrame(GL10 gl) { synchronized (spritesHolder) { // whole method code... } } 

    So dass beide Fäden nicht die SpritzenHolder zur gleichen Zeit verwenden. So wurden Updates 60 mal pro Sekunde durchgeführt und die Zeichnung fand statt, wenn App (Gerät?) Benötigt wurde.

Viel reden, sorry, ich habe fast fertig geschrieben diesen Beitrag. 😉 So sowieso – dies (oben beschrieben) funktioniert und ich habe sogar ein Spiel geschrieben, das auf dieser "Vorlage" basiert, aber ich denke, meine Ideen könnten verrückt sein und man kann alles besser machen. Ich wäre sehr dankbar für alle Kommentare und Ratschläge.

  • ImageView mit abgerundeten Ecken und innerem Schatten
  • Wie man eine Route zwischen zwei Geopoints auf dem Android zu zeichnen
  • Weird Problem auf Android Webview mit Leinwand
  • Android - Hinzufügen einer String über ein Drawable Image?
  • Starten eines AnimationDrawable in Android
  • Wie pausiere ich für 5 Sekunden vor dem Zeichnen der nächsten Sache auf Android?
  • Standard-Selektor-Hintergrund in Clickable Views
  • Wie zeichne eine Zeile in ImageView auf Android?
  • 2 Solutions collect form web for “So erstellen Sie Update / Draw Loop passend mit android opengl?”

    Ihre Lösung wird wahrscheinlich funktionieren, obwohl es für die Leistung suboptimal sein könnte. Wenn du darüber nachdenkst, muss der Render Thread und der Update Thread nicht wirklich 100% exklusiv sein.

    Ich habe vor kurzem eine Weile darüber nachgedacht für dieses Spiel, und das ist, was ich am Ende kommen mit (nicht unbedingt besser, aber nur etwas zu denken):

    Für jedes Renderable-Objekt habe ich ein Objekt, das dem Update-Thread gehört, und ein anderes Objekt, das dem Render-Thread gehört, der nur ein einfacher Container ist, der Anweisungen enthält, wie man ein Objekt zeichnet (Modellmatrix, einheitliche Werte, MeshID usw.). Ich laufe durch den Update-Thread, der alle endgültigen Positionen und Werte für meine gerenderten Objekte berechnet, und dann synchronisiere ich für ein kleines Fenster, wo ich irgendwelche Werte übergebe, die während dieses Frames zu den Objekten im gerenderten Thread geändert wurden. Sobald die neue Information verstrichen ist, beginnt das Frame-Rendering, während der nächste Update-Frame gleichzeitig läuft. Weil es nur ein kleines Ausschlussfenster gibt, erlaubt es das Update und zeichne Threads, um gleichzeitig die meiste Zeit zu laufen.

    Ich habe das noch nicht mit OpenGL benutzt, aber UpdateThread sollte ein TimerTask sein. In deiner Aktivität startet es mit

     new Timer().schedule(new UpdateThread(view), 0, 15); //where view is your view, and 15 is the wait time 

    In deiner TimerTask ruf die Ansicht mit einem Handler an. ZB (in deiner Ansichtsklasse)

     Handler refreshHandler = new Handler() { public void handleMessage(Message msg) { //Handle it; eg for canvas invalidate() }}; 

    In deiner UpdateThread-Laufmethode:

      view.refreshHandler.sendMessage(new Message()); 

    Jetzt ist es unabhängig von deinem Gameloop. Außerdem sollte dein Gameloop nicht in der MainActivity sein, sondern in einem Thread (unidirektional OO).

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