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.
Related
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.
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.
I am creating my first game in Java. The game is Monopoly. I am struggling with how I should design the game to model its turn-based structure (managing player turns). I want to allow for both a single human-controlled and one or multiple AI-controlled players to play the game.
My specific issue is that I do not know whether to implement a game loop or not, meaning a loop which can manage the players and the variables directly related to the game of Monopoly, (think of things such as prompting each player for their turn, incrementing the turn to the next player, or getting dice rolls from each player—in turn). I am not referring to the more low-level meaning of the term “game loop” which relates more to drawing frames on the screen, updating physics, or updating AI at a specific rate of time.
My understanding is that my options for trying to implement what I need are either to:
Implement a completely event-driven program which has no such game loop, or
Implement a game loop—something that is long-running in the background and basically never-ending as long as the game is running. This would be the more procedural approach.
When I first started trying to solve this issue, I ran into problems of my UI freezing because my game loop was never-ending and was completely consuming the thread on which it was running (I just made a very simple while loop to illustrate this). So I went to the effort of creating a SwingWorker to encapsulate my game loop. That solved the issue of UI freezes, but still left me wondering if I was going down the wrong path.
As a general rule, I found that most advice on the web generally seems to favor any approach which is event-driven, and thus my current implementation utilizing a SwingWorker could be a step in the wrong direction. But I cannot fully grasp how I would implement a completely event-driven system for this specific task (meaning no game loop present). It seems to me that a loop has to exist somewhere for managing the player turns.
Here are my specific questions:
Are game loops (as I am describing them) appropriate for turn-based games such as Monopoly—specifically for queuing the player turns and prompting the appropriate player for their turn, one player at a time (and queuing the entire procedure of/sequence of steps that comprise a turn)?
If a purely event-driven system were to be created for managing player turns, how do you iterate through each player to prompt them for their turn and keep iterating until the game ends?
If a game loop were to be used to solve the specific problem described above, does it have to be run within its own thread (possibly using SwingWorker) in order to avoid freezing the UI? My situation is Java-specific, but I suppose I would be interested in answers for non-Java-specific situations as well.
Currently, I have my code organized using the MVC pattern. My controller is where my game loop (the actual SwingWorker thread) resides. It is far from complete, but it helps illustrate how I am managing player turns in what I am calling a "game loop".
SwingWorker code from controller:
swingWorker = new SwingWorker<Void, Model>() {
#Override
protected Void doInBackground() throws InterruptedException {
gameLoopRunning = true;
while (gameLoopRunning) {
//to do: use a timer instead of thread.sleep
Thread.sleep(1000);
//user turn prompt
if (model.getActivePlayer().isUserControlled()) {
boolean userRolled = false;
while(!userRolled) {
System.out.println("Roll the dice please...");
Thread.sleep(3000);
}
}
//bot turn prompt
else {
//insert code for bot rolling dice here
model.rollDice();
}
publish(model);
Thread.sleep(1000);
model.incrementPlayerTurn();
publish(model);
}
return null;
}
#Override
protected void process(List<Model> chunks) {
Model gameModel = chunks.get(chunks.size() - 1);
//hard-coded for 6 players
for (int i = 0; i < 6; i++) {
view.getPlayerPanel(i).setTurn(gameModel.getPlayers().get(i).isTurn());
}
view.getGamePanel().getDice().setDie1(model.getDie1());
view.getGamePanel().getDice().setDie2(model.getDie2());
}
};
swingWorker.execute();
The comment from SirDarius is spot on.
Though, for something as simple as advancing player turns, you don't really need to bother implementing a full fledged finite state machine.
In terms of MVC, this is what you should do for human players:
The Model: Provide methods for advancing the active player to the next player and for running through the "turn process" (i.e. rolling the dice, moving the active player's token, etc.). Because much of the turn process is event driven, these method calls will be made from event listeners in the controller.
The View: Raise an event when the active player finishes their turn, as well as raising events on various other input.
The Controller: Whenever a player finishes their turn, tell the model to advance to the next player, and start the "turn process" again. Whenever a player provides input, an event will be fired that tells the model to advance to the next stage of the turn.
For AI players, the majority of the same code can be used, but it does not make sense to have the turn progression be driven by the view. Instead, the model would need to have another "turn process" method which would be specifically for AI players. The only difference being that the code would execute in succession without waiting for input from the view, instead of being a series of event listeners.
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);
I was adding a loading bar feature to my program in Java and I was wondering if I could set a list of processes that need to be done, so that it knows how many processes it needs to complete.
For example, saving them as strings?
ArrayList<String> processes = new ArrayList<String>();
processes.add("CSVWriter.createFileOfCompany(\"Random Company\");");
processes.add("FileConverter.convertCSVToXLS(classPath +
\"/Output/Random_Company.csv\");");
for (int i = 0; i < processes.size(); i++) {
// run process
// update loading bar
}
These aren't real methods to my program, but they are pretty similar to what I want to accomplish.
I'm sure this isn't the best way, but I want to have some way to create a list like this so I know how many processes there are before I run them. I have a system set up to break down these processes even further and show their progress, so this bar is pretty precise at the moment, but I have to number each of the processes =/.
Maybe I'm just missing the point. Creating progress bars is totally new to me.
If there are any good articles on progress bar creation, feel free to send them my way as well. Keep in mind that I'm not using an actual swing-based GUI. This bar is all S.O.P text.
Many thanks,
Justian Meyer
Closures will hopefully be coming soon in the next version of Java, but until then you can use anonymous classes implementing a known interface:
List<Runnable> jobs = new ArrayList<Runnable>();
jobs.add(new Runnable() {
public void run() {
CSVWriter.createFileOfCompany("Random Company");
}
});
jobs.add(new Runnable() {
public void run() {
FileConverter.convertCSVToXLS(classPath + "/Output/Random_Company.csv");
}
});
for (Runnable job : jobs) {
job.run();
}
Here's a scheme that just came to my mind:
interface WorkProcess
void setWorkUnits(int units)
void setArguments(Object obj1,...)
void execute()
So you encapsulate all your tasks with an interface that does execute as per the classic command pattern; it's also told (see below) how much work that job will probably take. You'll probably want some mechanism to pass data into these tasks for them to work with.
class WorkProcessFactory
static WorkProcess makeWorkProcess()
static int getTotalWorkUnitsAllocated()
static synchronized int reportWorkDone(int units)
static void addProgressListener(ProgressListener xxx)
When you have a job to do, you ask the factory to churn out one of these processes for you. In doing so, it does the estimate on work units and passes that to the WorkProcess it just created. It also keeps a tally of the total of those units for setting up the top of the progress indicator. One cool side effect of this is that you don't have to wait for all your jobs to be prepared: You can increment the maximum value for your progress report every time you add a job even as jobs are being processed and newly created; your bar will always show a realistic ratio.
You can stuff your WorkProcesses into a queue of some sort. ExecutorService comes to mind if your WorkProcess also implements the Runnable interface (which is a good idea). You'll be at liberty to process those jobs sequentially single-file or concurrently - whatever your execution queue machinery supports.
The WorkProcess' execute() method basically wraps the run() method (or maybe the other way around, since ExecutorService expects a run() method but our work unit magic is in execute()); but when that's done, it conscientiously calls back to reportWorkDone with the number of units it was told its job was worth. Upon receiving these reports, the factory has an updated value for units of work done, which it can report back to the snooping ProgressListener. That, in turn, updates the bar in the GUI.
Done. (I think). Probably needs some refining.