0

So i have a problem with LibGDX, i am creating a game where there are spikes.

I have created a separate class which contains a run method which runs every five seconds.

I want to run a method from another class and create a new spike on the screen.

Since i have a new account i cannot post pictures.

But this is for the initializing of the timer:

@Override
public void create ()
{


    timer = new Timer();

    timer.schedule(new SpikeHandler(), 0, 5000);


}

And this is for the create a spike method:

public static void createNewSpike(int x, int y) 
{

    sb.draw(spike.spikeLeft, x, y);

}

And this is what happens every five seconds/the timer loop:

public class SpikeHandler extends TimerTask
{

public Random rand = new Random();

@Override
public void run() 
{

    if(GameStateManager.getState() == GameState.Playing && GameScreen.hasCountdowned == true)
    {
        GameScreen.sb.begin();

         GameScreen.createNewSpike(rand.nextInt(150), rand.nextInt(150));

        GameScreen.sb.end();
    }


 }
}

This is the error message I'm getting:

Exception in thread "Timer-0" java.lang.RuntimeException: No OpenGL context found in the current thread.
    at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java:124)
    at org.lwjgl.opengl.GL11.glDepthMask(GL11.java:1157)
    at com.badlogic.gdx.backends.lwjgl.LwjglGL20.glDepthMask(LwjglGL20.java:256)
    at com.badlogic.gdx.graphics.g2d.SpriteBatch.begin(SpriteBatch.java:163)
    at com.fam.dodge.SpikeHandler.run(SpikeHandler.java:17)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)
Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85
Adam Brodin
  • 63
  • 1
  • 2
  • 13

3 Answers3

4

I had the same problem using multiple threads for networking once. For everything that you want to do inside the thread that has an opengl context (Any graphics operations involving opengl) use this:

Gdx.app.postRunnable(new Runnable() {
         @Override
         public void run() {
           // do stuff here
         }
});

in your case this would include :

 GameScreen.sb.begin();  
 GameScreen.createNewSpike(rand.nextInt(150), rand.nextInt(150));
 GameScreen.sb.end();

If you want to do further reading on how to do multi threading read this from the libGDX docs: Libgdx - Threading

Bernd
  • 779
  • 5
  • 11
  • I get syntax errors while using that code you suggested. Here's my code: Gdx.app.postRunnable(new Runnable() { @Override public void run() { if(GameStateManager.getState() == GameState.Playing && GameScreen.hasCountdowned == true) { GameScreen.sb.begin(); GameScreen.createNewSpike(rand.nextInt(150), rand.nextInt(150)); GameScreen.sb.end(); } } }); } I get syntax errors with postRunnable, "=" expected and missplaced tokens – Adam Brodin Apr 06 '15 at 11:46
  • Where did you place the code? I think in your case you need to place it into the run method of your Spikehandler class. – Bernd Apr 06 '15 at 12:39
  • This is how the code is placed: Gdx.app.postRunnable(new Runnable() { @Override public void run() { if(GameStateManager.getState() == GameState.Playing && GameScreen.hasCountdowned == true) { GameScreen.sb.begin(); GameScreen.createNewSpike(rand.nextInt(150), rand.nextInt(150)); GameScreen.sb.end(); } } }); } And all i get is syntax errors.. – Adam Brodin Apr 06 '15 at 12:50
1

Ok, have a look at this: The exact same problem

Madhuchhanda Mandal
  • 917
  • 1
  • 7
  • 20
  • I don't really understand that post, im new to java/libgdx programming. But are you saying i need to type this: GLContext.createFromCurrent(); before my thread? – Adam Brodin Apr 06 '15 at 11:14
1

LibGDX uses OpenGL to draw things. In OpenGL there is only one thread permitted to use graphical resources, i.e. create textures, draw things to the screen. So the error is thrown because you are trying to draw the spike from the Timer-0 thread and not the rendering thread. You could get rid of the error by using Application.postRunnable() method. If you were to change your createNewSpike method to

public static void createNewSpike(int x, int y) 
{
    Application.postRunnable(new Runnable(){
        public void run(){
            sb.draw(spike.spikeLeft, x, y);
        }
    });

}

Your error would go away. However the spike would only be displayed on the screen for one frame, if even that. What you really need to do in the timer is add the spike to your game world. Then the next time the world is rendered it will render the spike. Unfortunately I cannot help you with that without knowing the underlying structure of your game world.

I hope this helps a bit.

Bogoth
  • 129
  • 1
  • 3
  • 1
    Another error might pop up if you use the postRunnable, because there is no active batch. Anyway the bigger issue is that you are merely trying to draw it instead of actually creating a new spike. – Bogoth Jan 09 '16 at 22:17