Multithreaded LWJGL Keyboard Delay - java

In a LWJGL game I'm making I have 3 threads - one for graphics, one for processing/physics and one to provide world access and deal with multiplayer connections.
The issue I'm having is that when I call Keyboard.isKeyDown() in the physics thread I have to hold it down for sometimes half a second or so before anything happens. This isn't because the thread is running slowly - it's the only thing in the loop at the moment, and a println call shows that it's updating.
I'm wondering if this has something to do with the fact that the OpenGL context exists in the graphics thread and I'm calling keyboard calls from the physics thread? If I do the check in the graphics thread it works fine, but taking inputs there and sending them to the other thread would somewhat defy the point of having separate threads.
My keyboard check currently looks like this:
boolean escPressed = false;
private void process(){
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
if(!escPressed){
escPressed = true;
GameStateManager.pauseUnpause();
}
}
else{
escPressed = false;
}
}
My thread setup is simply this
public class Client {
public static GraphicsThread graphics;
public static PhysicsThread physics;
public static ConnectionThread server;
public static void main(String[] args) {
GameStateManager.setState(GameStateManager.EnumState.MENU);
graphics = new GraphicsThread();
physics = new PhysicsThread();
server = new ConnectionThread();
physics.start();
graphics.start();
server.start();
}
}
So can anyone tell me why there is a delay when calling the method from a different thread?
Update
I did a quick test, and it any calls to Keyboard just seem to take a very long time to complete.
while(true){
start = System.currentTimeMillis();
Keyboard.isKeyDown(Keyboard.KEY_ESCAPE);
end = System.currentTimeMillis();
System.out.println(end-start);
}
Running that test showed results as high as 1100ms, which is ridiculously high. When running in the graphics thread it completes in less than a millisecond and prints 0. Not sure what's happening here.

LWJGL 2 or 3? Shouldnt really matter..
though, as far as I know there shouldnt be a problem with calling this method on other Threads, although Calling it on the Thread where the OpenGL context is bound to is a good idea anyways.
For my setup I have one Thread dedicated to all OpenGL context related stuff. (E.g. openGL calls only). So in your case, Il would check for the keyPressed state in the graphics Thread, which passes a hint to the Physics Thread which does all the heavylifting (if there is any). Though details are up to you of course.
I hope this helps you
Edit:
I came across this post when dealing with this problem as well, basically its not possible because of choice of design by LWJGL. You can manually separate it by hinting (as described above), or keep track of the state of every input device (updated in the graphics thread) which you check on from other Threads instead of using the Keyboards class.

Related

AsyncExecutor doesn’t seem asynchronous

This question has been edited to provide as much information about the problem as possible, as someone suggested I should do. Now that there’s bounty on it—that only seems like the right thing to do. Good luck, people!
Don’t forget you can always ask additional questions if you feel there’s something I didn’t include!
Introduction
I’m working on a system for procedurally generating terrain as a character walks around using various different noises—mostly perlin- and simplex-noise. The world itself has three dimensions, althought it’s viewed as top-down in two dimensions inside the game.
For those of you used to procedurally generating terrain, you’ll be aware of the fact that it’s necessary to use multithreading in order for it not to cause lag spikes within the renderer thread. That’s exactly what I’ve been trying to do, with a little help from LibGDX’s AsyncExecutor, as well as the same library’s AsyncTask, which is a task running on the thread offered by the AsyncExecutor.
Problem
My problem is that the AsyncExecutor doesn’t seem asynchronous at all. It causes lag spikes within my renderer thread, which in theory could be from it using a resource that also is used by the renderer thread. The thing is, however, that the renderer thread generates in new “chunks”—I call them regions—that the AsyncExecutor then work on. The renderer thread isn’t allowed to render that resource until it has been fully generated by the AsyncExecutor.
RegionHandler
I have a class called RegionHandler which places new regions in the direction the player is moving and removes regions from the opposite directions—in order for the program not having to be aware of more than 13 x 9 regions at one time.
Here’s a brief piece of code explaining how it works—the comments are there to simplify discussing different pieces of the code:
// These ‘if’s are triggered when the player moves
// to a certain position
if(addLeft)
{
// Adds new regions to the left and removes to the right
// ...
// Submit ‘RegionLoader’ task to ‘asyncExecutor’
// with regions that needs be generated as well as ‘toSends’ which is
// also part of that generation
asyncExecutor.submit(new RegionLoader(toGenRegions, toSends));
}
else if(addRight)
{
// Adds new regions to the right and removes to the left
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toGenRegions, toSends));
}
if(addBottom)
{
// Adds new regions to the bottom and removes to the top
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toSend, toSends));
}
else if(addTop)
{
// Adds new regions to the top and removes from the bottom
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toSend, toSends));
}
The asyncExecutor is in fact and AsyncExecutor and the RegionLoader implements the AsyncTask interface. I’ve tested to see how long this piece of code takes to run through—this piece of code never takes over a single millisecond to run through.
The Regions are handled inside a list:
List<List<Region>> regions;
RegionLoader
This class is a task with the capability of being run by an AsyncExecutor.
private class RegionLoader implements AsyncTask<Object>
{
private List<Region> regions;
private List<ToSendInner> toSends;
public RegionLoader(
List<Region> regions,
List<ToSendInner> toSends)
{
this.regions = regions;
this.toSends = toSends;
}
#Override
public Object call() throws Exception
{
// Generates the ‘Region’s it has been given inside the constructor
// ...
return null;
}
}
Once call() has finished it’ll set a boolean to true that allows for the rendering of that specific Region.
Furthermore
Although the AsyncExecutor is meant to be asynchronous, it causes lag spikes every once in a while inside the renderer thread. As mentioned earlier, this could be caused by the AsyncExecutor using the same resources as the renderer thread, but the renderer thread merely renders the Regions when it’s allowed to—for that reason I can’t see why that’d be what’s causing the lag spikes.
What I’ve tried so far
I’ve tried using regular Java threads, but I read somewhere that these might not work due to LibGDX supporting Android development and Android doesn’t have the same capabilities when it comes to multithreading—but I could truly be wrong!
Furthermore
Perhaps someone has experienced a similar problem over their game development careers? If so, maybe someone can point me in the right direction?
I'd take a look into the effects of your garbage collection, as you seem to be passing new Region objects to the tasks. Try reusing/repopulating existing Regions instead.
I don't remember any problems about Android and Threads and searched but didn't find anything. You should test it.
I will assume that generating regions is not anything related to openGL. So you don't have to run it on main thread.
Try this: Thread + Gdx.app.postRunnable()
new Thread(new Runnable() {
Variables...
public Runnable set(Variables... ) {
// set variables
return this;
}
#Override
public void run() {
// do stuff
Gdx.app.postRunnable(() -> {
// commit that stuff.
});
}
}.set(regions,whateverelse)).start();
If you look at the source code of AsyncExecutor you will see that it exactly does the same. But only it doesn't let a second runnable run at the same time.
https://github.com/libgdx/libgdx/blob/9b8f20b2d0e96e53f0f2b98dc8f6131c810aae71/gdx/src/com/badlogic/gdx/utils/async/AsyncExecutor.java
Note: The implementation of the AsyncExecutor is changed to instantly execution in the gwt backend. Because of the limitations I'd guess. You probably shouldn't target gwt.
Try it, and let me know. If main thread still hangs, it is because what you are doing in the //commit that stuff part. Post more of your code, there is not enough to understand the source of the problem.
EDIT : Also use Gdx.graphics.getDeltaTime() to see if there is really a hang. It might be caused by something else, so eliminate other possibilities and find out if the real reason is this task.

How to terminate a Java process from a different one?

I am making a CSP solver that calculates all the combinatory solutions of a specific problem like this (briefly put):
// Say we are in a Solver class
public void solve() {
// find solution...
}
// This would be in a Problem class
problem.getSolver().solve();
There is a good chance that the resolution process takes a long time to finish, like more than a couple of minutes. So far, when it has been taking so long I have just stopped the process via console.
But eventually I am going to post my application as a web application in a host that allows Java apps (side-question: I have seen I can do it in Google Cloud and I have been told also about AWS; are they good options?). This means I, or the user, cannot terminate the process anymore if it takes too long.
I want to add the funcionality of having the option of cancelling the resolution process at will.
So I would declare a new method in the Solver class that would terminate the process, which would effectively stop the resolution process:
public void stopResolutionProcess() {
// kill the process, therefore, stop the resolution process
}
I cannot just call problem.getSolver().stopResolutionProcess() after the resolution process has already started, because the thread is already running and until that process ends, that method call will never be executed.
So how could I do this? How could a client signal the service hosted in the cloud to terminate a running process?
Put the long running process in a different thread. You can stop it from the main thread if necessary. See:
How to stop a thread by another thread?
Since you haven't chosen a cloud host yet this question is really difficult to answer. Generally speaking you need a synchronization object. Something like
volatile boolean keepRunning = true;
and your method would do
public void stopResolutionProcess(){
keepRunning = false;
}
then in your solve you have to regularly check for that variable
public void solve(){
while(keepRunning){
// doSomething();
Thread.sleep(500);
}
}
Now i use a variable here but that may not be sufficient. In App Engine your application could run in different instances where static variables are not synchronized. You would need a sync object that is accessible to all your solve threads. In App Engine that would be a datastore object that is also cached in the memcache. But you could use Pub/Sub or other mechanisms to propagate the completion of the task. The specifics are tightly coupled to the environment you'll choose to run this on.
Requests for product recommendations are generally off-topic on Stackoverflow. Choose a product for hosting and if you run into trouble return with a more concrete question.

Making code that runs automatically within a given interval

I have a few questions about having code that runs automatically within a given interval. I'm programming a kind of game mode where it checks if the players have killed all the monsters in the map (I have my methods for these). I was wondering what's the best way to program this check? I've looked up ways where a person made a ScheduledExecutorService during a class constructor....
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
But I saw online where people used
static void main(String[] args) {
And a run method to do the checks. Which would be better? I'm simply wanting to have a check that runs every few or so seconds that sees if the player has cleared the map, and if he or she has, then to progress to the next stage.
I think you can check this every time the player kills a monster. Maybe you want to listen to a KillMonster event. You can create interfaces and implement that in your other class.
public interface KillMonsterEventListener {
void onKillMonster ();
}
And then in the player class you can call a method to call onKillMonster() of all the event listeners. I think you know how to do that. Just create a list of KillMonsterEventListeners and have a method like:
public void addKillMonsterEventListener (KillMonsterEventListener listener) {
listeners.add (listener); //listeners is the list of KillMonsterEventListeners.
}
Overall, it is somewhat costly to use Executor for just that, because you can easily have a counter for number of monsters and modify it whenever a monster is killed in the update tick. When it reaches 0, the player has cleared the level. Generally Executor is fine for larger operations like autosave to the file, it's also worth noting that the code will be executed on a background thread. Since you are just going to query the number of monsters left in the game and not alter UI, it should be fine.
Regards static void main(String[] args) { I don't see how that fits in the question.

SecondaryLoop in JavaFX, like Swing?

I have a Java Swing app which I'm investigating if it is even possible to port to JavaFX. The app is a development environment and simulator for an internally used scripting language. The interesting thing about it is you can set breakpoints for this scripting language and step through it, like any programmer would expect for a language.
Now because the language in the simulator is interpreted, deep within the execution of the interpreter, when it hits a breakpoint, it can pop back to the gui with a Java Swing SecondaryLoop class. So when the breakpoint is hit, it calls secondaryLoop.enter(). The gui is then active for the user to inspect variables and gui components are active. When the user hits "Continue" in the program, it calls secondaryLoop.exit() to continue execution of the interpreter. It wouldn't really be feasible for the interpreter to unwind it's entire state to go back to the primary loop, and then take up where it left off at exactly the same point. That's why the SecondaryLoop is invaluable in making it work.
Is this possible in JavaFX?
Yes, it's possible. You need to use the enterNestedEventLoop and exitNestedEventLoop methods (they are inside the com.sun.javafx.tk.Toolkit class). See this usage example:
// Make sure to import the FX Toolkit first
import com.sun.javafx.tk.Toolkit;
// This object will be used as a unique identifier to the nested loop (to
// block the execution of the thread until exitNestedEventLoop is called)
final Object loopLock = new Object();
// Simulate a long process thread (DB call, download, etc)
Thread longProcess = new Thread(new Runnable()
{
#Override
public void run()
{
// Sleep for 12 seconds to simulate a long process
try
{
Thread.sleep(12000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
// Setup a result to pass back to the enterNestedLoop() caller
String result = "Result of this long process";
// We are now done. Call exitNestedEventLoop() to unblock
// the enterNestedLoop() caller. This needs to run from
// the FX Thread so use Platform.runLater()
Runnable fxRunner = new Runnable()
{
public void run()
{
try
{
Toolkit.getToolkit().exitNestedEventLoop(loopLock,
result);
} catch (Throwable t)
{
t.printStackTrace();
}
}
};
Platform.runLater(fxRunner);
}
});
// Start that long process from the FX Thread
longProcess.start();
// The next call will block until exitNestedEventLoop is called, however
// the FX Thread will continue processing UI requests
Object result = Toolkit.getToolkit().enterNestedEventLoop(loopLock);
// Next statement will print: "Result of this long process"
System.out.println("Result is: " + result);
Now, before you use this be warned of two important things:
The com.sun.javafx.tk.Toolkit class is not part of the public API, so Oracle reserves the right of removing it without notice. I've been using it just fine from Java 7 to 8u51 so they could stay there forever, change package/names or disappear completely (unlikely).
Nested loops (and Swing's secondary loops) are great for flexibility and small applications but overusing them often comes with a price. Nesting to many loops (huge stack trace) will often cause "strange" behaviour in your applications since initial parts of your code might end up waiting four or five things ahead completely unrelated to them. I've seen FX nested loops causing "empty" exceptions in FX WebEngine executeScript() calls and duplicating keyboard preprocessing (when pairing FX+Swing) among other problems.
That said I would recommend using the javafx.concurrent.Task instead (if it makes sense). Using the Task class will require a bit more effort but I think it's the correct way of doing things and will probably save you lots of maintenance time.
For extra reference about the FX Task class see this great article: http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm
UPDATE: enterNestedEventLoop and exitNestedEventLoop will be part of the Java 9 public API (Platform class), more info in JDK-8090865
Hope this helps!

UI updates as expected in debug mode, but does nothing when run normally

I'm creating a simple game turn based game in NetBeans. After the initialization of the GUI it calls the function herosTurn() to which waits for the users choice and and creates the outcome of that choice from a separate class Hero. When I step through the code in Debug mode, I get correct outcomes, but if I just run the code nothing is ever appended to the Text Area unless I have the wait function constantly appending text while it waits for input. I've seen other questions similar to this but they all involved multi-threading, and I don't believe that is what I am doing. Any help would be greatly appreciated.
This is the main class:
package Flow;
import Forms.Battleinterface;
/**
*
* #author Steemo
*/
public class battle {
public static int hAct;
public static int gLife = 200;
public static void herosTurn() {
hAct = 0;
Forms.Battleinterface.biText.append("What will you do?");
while (hAct == 0){
// adding the line below makes code work but is ugly.
//Forms.Battleinterface.biText.append(".");
continue;
}
if (hAct == 1){
Entities.Hero.attack();
}
}
public static void main(String args[]) {
Battleinterface battleinterface = new Forms.Battleinterface();
Battleinterface.Start();
while (gLife > 0) {
herosTurn();
}
}
}
And this is the Hero() class that is in a separate package:
package Entities;
import java.util.Random;
/**
*
* #author Steemo
*/
public class Hero {
static Random hGen = new Random(54154454);
public static void attack() {
int hAtt = 0;
hAtt = hGen.nextInt(6) + 15;
Forms.Battleinterface.biText.append("\nYou swing your axe and do " + hAtt
+ " Damage!!!");
}
}
I am not attaching the class I use to generate the GUI (Battleinterface) because the GUI generates fine and the only other thing happening there is the passing of the input hAct.
If it is needed I can attach it.
Replace this code...
while (hAct == 0){
continue;
}
...with this instead:
while (hAct == 0){
try {
Thread.yield();
} catch (InterruptedException interruptedEx) {
// Log the interruption somewhere.
}
}
Assuming you're using AWT/Swing on some level? This is an infinite loop, preventing other threads from ever running. By doing this you never let the UI thread actually do any updating, which means it appears to hang. You may not be doing any threading on your own, but AWT/Swing comes with Threads built in to do various functions, and they need to periodically get CPU time to do their work.
The reason this works in debugging is because the debugger is pausing the herosTurn method as you're stepping through it, allowing the UI thread to do its updates (including getting input from the user), but when simply running your game, the herosTurn method never pauses, and that method is occupying 100% of the available CPU time for your app.
Finally, as Mike Clark mentions, you typically shouldn't write UI with infinite loops. Instead you define components, which trigger events. Your code is notified of those events and reacts appropriately. This is what is known as the UI's event model. If you're using Swing, the introductory info on working within the event model is covered here.
I also wouldn't typically use AWT/Swing for games, because of the complications of UI coding, rendering performance, and several other reasons relating to the reality that AWT/Swing were not built to be good tools for games. That being said, a turn-based game can work fine this way (because the rendering performance requirements are often much lower) if you're willing to delve into the UI code to get it done, in addition to a few other reasons which I've outlined in a previous answer.
Hmm, there might be an issue with flushing your text buffer to the text area. Try explicitly flushing your text buffer after every print to see if that makes a difference.
It seems to me that your program is stuck in a while loop in the method herosTurn() As long as that function has not returned, nothing is going to update if you program this game as a single thread application.
It works when you uncomment the Forms.Battleinterface.biText.append("."); line cos then you send a signal to the GUI every iteration which causes it to update.
Games usually have a main game loop from which all elements of the program are controlled. Maybe a change of your implementation strategy will help?
I'm not a games programmer, so this might not be the best approach, but why don't you try setting up a javax.swing.Timer that runs every, say, 100 milliseconds. In inside the timer action, you can write all the code which checks and advances the game state and generates output to the user.
I'd suggest collecting the user's input in a JTextField that is separate from the place where the game output is printed. If you want to know when the user presses enter to send what they've typed, you can register an ActionListener on the JTextField.
textField.addActionListener(yourListener);

Categories

Resources