2017-09-01 5 views
2

Ich verwende akka zusammen mit Libgdx experimentieren und ich habe folgendes ProblemVerwenden Libgdx mit Akka

ERROR] [09012017 174508.522] [WorldMap-akka.actor.default-dispatcher-3] [akkaWorldMapusergame] No OpenGL context found in the current thread. 
java.lang.RuntimeException No OpenGL context found in the current thread. 
    at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java124) 
    at org.lwjgl.opengl.GL11.glDepthMask(GL11.java1157) 
    at com.badlogic.gdx.backends.lwjgl.LwjglGL20.glDepthMask(LwjglGL20.java256) 
    at com.badlogic.gdx.graphics.g2d.SpriteBatch.begin(SpriteBatch.java170) 
    at com.badlogic.gdx.scenes.scene2d.Stage.draw(Stage.java127) 
    at org.anacletogames.modes.WorldMapScreen.renderContent(WorldMapScreen.scala90) 
    at org.anacletogames.modes.GameActor$$anonfun$receive$1.applyOrElse(GameActor.scala27) 
    at akka.actor.Actor$class.aroundReceive(Actor.scala480) 
    at org.anacletogames.modes.GameActor.aroundReceive(GameActor.scala13) 
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala525) 
    at akka.actor.ActorCell.invoke(ActorCell.scala494) 
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala257) 
    at akka.dispatch.Mailbox.run(Mailbox.scala224) 
    at akka.dispatch.Mailbox.exec(Mailbox.scala234) 
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java260) 
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java1339) 
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java1979) 
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java107) 

Dies geschieht so schnell, wie ich versuche, etwas in einem Akka Schauspieler zu machen oder versuchen, einen Bildschirm im Innern zu schaffen der Schauspieler.

Momentan befindet sich der Schauspieler könnte so

class GameActor extends Actor with WithDelta 
{ 

    val fpsLogger = new FPSLogger 
    var screenBaseScreen = null 
    override def receive = { 
    case CreateGame(s)= screen= s 


    case Render = 

     updateDelta() 
     if(isTimeToRender) { 
     ---game logic and stuff --- 
     stage.draw() 
     } 
    } 

} 

zusammengefasst werden, wenn ich .draw() es bricht rufen und das macht sehr viel Sinn ist dies ein anderer Thread. Nichts ändert sich, wenn ich den Bildschirm innerhalb des Schauspielers erzeuge, er bricht nur bei der Screen-Erstellung ab. Nun, während sich dieses Verhalten logisch anfühlt, was kann ich tun, um diese Einschränkung von LibGDX zu umgehen? Gibt es einen Weg, dies zu erreichen? Ich habe kein Problem, einen großen Spieldarsteller zu behalten, aber ich muss die Spielschleife vom Schauspieler trennen, um einige Verhaltensweisen zu erreichen würde gerne haben.

Antwort

1

Wenn Sie mit der Benutzeroberfläche arbeiten, wird im Allgemeinen erwartet, dass Sie Interaktionen mit den Benutzeroberflächenelementen aus einem einzigen Thread durchführen, der die Hauptereignisschleife enthalten würde. Dies wird für viele Zwecke benötigt; Zum Beispiel verlassen sich viele GUI-Bibliotheken auf einen globalen Zustand, auf den mehrere Threads nicht gleichzeitig zugreifen können. OpenGL ist in dieser Hinsicht ähnlich.

Die meisten GUI-Bibliotheken bieten eine Möglichkeit, einen Code im Haupt-GUI-Thread auszuführen. Swing zum Beispiel hat Swing.invokeLater Funktion und JavaFX bietet Platform.runLater. Im Fall von OpenGL-basierten Frameworks ist es sehr wahrscheinlich, dass sie zu niedrig sind, um Ihnen eine solche Methode zur Verfügung zu stellen. Sie müssen wahrscheinlich die Ereignisschleife selbst fahren. In diesem Fall müssen Sie auch sicherstellen, dass grafischer Code manuell auf dem Hauptthread ausgeführt wird.

Die Ereignisschleife sieht in der Regel wie folgt aus:

while (true) { 
    for (event <- pollEvents()) { 
    dispatch(event) 
    } 
    draw() 
    ensureFps(60) // ensures that no more than 60 iterations are executed per second 
} 

Hier ist die dispatch() Funktion jedes Ereignis analysiert, die eine Benutzereingabe sein kann, einige Timer oder was auch immer, und ändert den Zustand der Anwendung, während draw() Displays der aktualisierte Zustand Es ist wichtig, dass diese Schleife immer im Hauptthread ausgeführt wird, in dem die GUI-Bibliothek initialisiert wurde. Dies kann schwierig sein, wenn Sie diese Schleife in einen Akteur einfügen möchten.

Es sollte funktionieren, wenn Sie sicherstellen, dass der Akteur immer auf einem einzelnen Thread ausgeführt wird. Um dies zu tun, müssen Sie eine dispatcher konfigurieren, die Ihrem Akteur einen einzelnen Faden zuweist. Dann müssen Sie alle Initialisierung Ihrer GUI-Bibliothek innerhalb des Schauspielers oder zumindest mit der execute() Methode auf dem Dispatcher tun (in letzterem Fall müssen Sie sicherstellen, dass der Executor nur einen Thread enthält). Und dann müssen Sie sicherstellen, dass Sie immer mit Ihren Bibliothek-GUI-Objekten in diesem Hauptakteur arbeiten. Dann sollte es keine Probleme mit dem Threading geben.