Hot questions for Using Lightweight Java Game Library in multithreading

Question:

I basically want to be able to launch a new Javafx window (stage) after (and inside) my LWJGL/GLFW thread starts. I am basically doing:

Thread thread = new Thread(()->Platform.runLater(()->{
    Stage stage = new Stage();
    //Stage setup
    stage.show();
}));
thread.start();

thread being my game thread. But it never runs and I've tried a System.out.println() inside Platform.runLater() just to check it never runs.

Why does it never run and what can I do to fix it? Thanks.

EDIT: Just to clarify that the thread has definitely started and whatnot, if I do:

Thread thread = new Thread(()->{
    System.out.println("Before Platform.runLater()");
    Platform.runLater(()->System.out.println("Inside Platform.runLater()"));
    System.out.println("After Platform.runLater()");
});

It outputs:

Before Platform.runLater()
After Platform.runLater()

Answer:

Ok, I have found the solution to this!

If you run into any situation where all of your scenes end, the thread managing all of this will just peter out. To prevent this from happening, add this line before Platform.runLater:

Platform.setImplicitExit(false);
Platform.runLater(()->System.out.println("Inside Platform.runLater()"));

So long as this runs before the last scene ends, it will keep the thread alive, and you will not run into the problem of runLater() failing!

Question:

I started working with the new Lwjgl 3 which uses GLFW for its Display/mouse/keyboard handling and I'm really liking it! However today i hit a brick. I had a simple rendering animation going but when I dragged the screen it stopped rendering until i let go again.


According to: http://www.glfw.org/faq.html The problem arises due to windows.

3.5 - Why does my application freeze when I move or resize the window? The Windows event loop is blocked by certain actions like dragging or resizing a window, or opening the window menu. This is part of the design of Windows and cannot be changed by GLFW. If you wish to keep rendering during such actions, you should render from a secondary thread.--http://www.glfw.org/faq.html


Ive done multi threaded things before in Java. But im not sure what goes in its own thread for this case. Should I have the opengl code and the GLFW code in seperate threads? I'm also having trouble thinking of a way to word my concerns.


Answer:

The only real restriction as far as I can find out is that GLFW needs to be in the application's main thread. This is where the OS event queue lives for GLFW and is why glfwPollEvents and glfwWaitEvents need to be in the main thread.

OpenGL rendering can be done from its own thread. glfwMakeContextCurrent ties the OpenGL context to the thread making that call. If your render function runs on it's own thread just make sure to update the context (as shown in the demo).

LWJGL Forum topic: [SOLVED] LWJGL3 Not threading as expected

LWJGL3 Multithreaded Demo referenced in the above link

Question:

I've been fiddling with creating a thread on which the rendering runs, and I've come across this way of implementing it:

Class Main implements Runnable {
private Thread thread;
private boolean running = false;

public void start() {
            running = true;
    thread = new Thread(this, "renderingThread")
    thread.start(); //calls run()
}

    public void run() {

    init(); //init glfw + create window

    while(running) {
        update();
        render();
    }
}

    public static void main(String[] args) {
        new Main().start()
    }

Note that only the sections of the code that are related to threads have been included.

Now, the program flow looks something like this (correct me if I'm wrong): Construct new object of type/class Main (hence, reserve a place on the heap). Then, the start() method of object of type Main is called. running boolean is set to true. Then, a new thread is created via constructor Thread (Runnable target, String name) - in my case, the first parameter is this keyword, meaning that the reference of the object of type Main is passed as the first parameter (since the method has been called by the object of type Main). Then, the next line is what fiddles me the most. The thread reference calls the method start(), but it somehow refers to the run() method. How?

I'd be very thankful for a thorough explanation of how start() method for a thread object can refer to the run() method.


Answer:

You create a new Thread with a Runnable target of this (the instance of Main class). Main implements Runnable means the method run() is overridden. The Thread class itself implements Runnable.

When you start the thread with the configuration above, the method start() causes the thread to begin execution; the Java Virtual Machine then calls the Thread object's run() method. It's said in the documentation. If you are curious, see the source code of the java.lang.Thread.

You can achieve the same effect with a simpler approach:

public class Main implements Runnable { 

    @Override
    public void run() {
        System.out.println("New thread");
    }

    public static void main(String[] args) {
        new Thread(new Main()).start();
        System.out.println("Main thread");
    }
}

Question:

I'm currently trying to make a really simple multiplayer game in java (with OpenGL (LWJGL)) and currently the program runs on two different threads.

Thread 1: Runs all the game logic and rendering

Thread 2: Handles the connection between server and client

So basically thread 2 sits and wait for incoming packets and whenever it receives a login-packet I want it to create a player-object but it seems like the new object is created on thread 2 and that causes the following error when trying to render:

Exception in thread "Thread-2" java.lang.IllegalStateException: No GLCapabilities instance has been set for the current thread.

I'm fairly new to both OpenGL and multi-threading and there is probably a pretty straightforward and easy solution to this but I'm wondering how I can create an object when receiving the packet and add it to thread 1.

Thread 2:

public void run() {
    while (running) {
        byte[] data = new byte[1024];
        DatagramPacket packet = new DatagramPacket(data, data.length);
        try {
            socket.receive(packet);
        } catch (IOException e) {
            e.printStackTrace();
        }
        parsePacket(packet.getData(), packet.getAddress(), packet.getPort());
        }
    }

parsePacket() checks the type of the packet and if it's a login-packet it will call the following method:

public void addPlayerToGame(byte[] data, InetAddress address, int port) {
    Packet00Login packet = new Packet00Login(data);

    level.addObject(new PlayerMP(packet.getUsername(), new Vector3f(0.0f, 0.0f, 0.0f), address, port));
} 

The addObject method simply adds the objects to an arraylist.

public void addObject(GameObject o) {
    this.objects.add(o);
}

All objects are then being rendered with this call on thread 1:

public void render() {
    for (GameObject o : objects) {
        o.render();
    }
    player.render();
}

Answer:

You shouldn't modify your GameObject list from the second thread since changes are extremely high you will be iterating on that list in the first thread. Which would cause a current modification exception. Or worse, creating undefined behaviors with openGL.

What you have to do is having a task list on your first thread. Every loop, you execute all tasks in the task list then clear it.

So instead of directly adding an game object to the list, add a task to add the object.

(Also, make sure to make the execution of the tasks thread safe)

Question:


Answer:

Q1: Usually you use multithreading whenever some sort of processing is going to take a while that you don’t want to hang your UI. If all your code is on the main thread then your UI becomes unresponsive in the time between the time consuming process starting and ending. If you need to do any Network Calls, you definitely need to put them on a different thread, and Android and Swift won’t even allow you to perform a Network call on the main thread.

Q2: It doesn’t matter too much as long as you do it. If you know you’re gonna use it you can implement it as you go but there’s not much stopping you from multithreading after the fact.

Q3: Many of the coding challenges have to do with timing your data and avoiding any Null Pointers since if the data you’re trying to access hasn’t arrived yet, your app can crash. Completion handlers are useful to ensure that certain functionality only happens after the data has arrived.

Q4: If you mean like consistently passing all the data between the threads it’s kinda unnecessary, you only need to pass the data across that you need at a certain point in time.