I am only a beginner in Java and until now I just put the functionality into the addActionListener() method of the buttons, it was enough for little games and stuff.
But now I am trying to make it seriously and I am wondering how to connect those 2.
As an example I am making a Fuchimi game, so I have my classes for the actual game and then a class that builds the frame with everything needed.
But my actual problem right now is, that after the frame is created, it doesn't do the following code since the code pauses at the window, like here:
FuchimiUI ui = new FuchimiUI();
//The following is not executed
Hand playerHand = null;
while (playerHand == null) {
playerHand = ui.getPlayerHand();
}
Hand enemyHand = generateHand();
ui.changeEnemyText("Enemy picked " + enemyHand.toString());
if (enemyHand.beats(playerHand)) {
ui.changeGenText("Computer wins!");
} else
ui.changeGenText("You win!");
The buttons I have just change the hand of the player.
So how can I do that properly, having the game code being compiled while the frame is already open?
I thought about threads, but I have too little knowledge about them, thus I don't know if that would be a good way.
Edit:
The ui.getPlayerHand() method returns the chosen hand(rock, paper or scissors) that the player has chosen through the buttons.
Of course I could have written the whole code in each of the button's addActionListener()methods, but I doubt that's the proper way of doing that.
So in general, all I wanted to do is let the player choose his hand and then let the game generate a random hand, then compare those two and change the text of one of the labels, depending on wether the player won or not.
The problem you are having results from the fact that your while loop is blocking the UI thread. You need to offload it to a different thread and then enqueue the UI updates back on the UI thread. The same situation is encountered here, please have a look.
There are several ways to fix this. One of them is the SwingWorker.
The steps are:
Override doInBackground for your while loop.
In it, call publish to store intermediate results (like the messages you want to display).
Override process to display the intermediate results in your UI.
The third page of above mentioned tutorial covers this.
As much as I agree with Domi's answer, that long-running code should go into a background thread, I strongly suspect that this is not what you need in this situation, that instead you should re-think the structure of your program. Likely what you need instead of that while loop is a modal dialog.
For more and better advice, consider telling us more details of the game logic and your program set up. For instance, tell us exactly what ui.getPlayerHand() does, as a start.
What you want to do is to change the structure of your program so that it is event-driven and state based where its behavior changes depending on its state. For instance if your program is in "choose hand" mode, then those buttons or other user interfaces are all that respond to the user.
Related
I am making a programme in Java for a school project. It has the form of an interactive multiple-choice test.
I wanted it to perform it in a way that an action button creates an event in which (the order of the code is the same as listed):
1) Randomly chooses an Object that consist of several Strings from a prepared List and prints it on adequate text fields in GUI
2) Using a proper method there is a delay created that holds further code down below for 1 minute. In this time the user should be able to check proper Checkboxes so the GUI must stay active.
3)When this minute ends the checked places are read and further processed.
The thing is that I am unable to create step number 2) which is the delaying of the code below. I have tried function sleep() but when I do it with sleep() the whole GUI freezes and the user is unable to do anything on it. I have read that function swing timer would be appropriate but I dont know how to do it. I have seen examples but in them the timer along with functions that were executed after some time were written in the class ActionListener instead of the action button. I am using Netbeans 8.1
Sorry for my bad explanation of the problem, I am a total beginner in java programming and really count on your help :)
Cheers!
Your problem comes from how you structured your code. You wrote everything into a single method.
Split this up into two methods. One to set up the UI state (everything before "HERE I NEED TO DELAY..."). The second method takes everything below.
Then, at the end of the first method, create a non-repeating Timer for one Minute, add an ActionListener that just calls your second method. Then start the timer. When the timer has run its course, it will call your second method through the action listener.
Ive created a network game. I am having issues with (seemingly) unexplainable errors. Note that the cards are added by to the ArrayList upon mouse clicks, and this class is run on its own thread.
private void waitForAction(){
tb.report("Waiting for user to make a move...");
selectedCards = new ArrayList<Card>();
while(selectedCards.size() < 2){
if(selectedCards.size() == 2)//Wtf is going on here...?
tb.report("This loop is (not) broken.");
else
tb.report("Looping..");
};
tb.report("This player has selected 2 cards.");
}
When I remove the else statement, the loop never exits, which is proven to me by the print(report()) methods. I had the same issue in earlier development, but it was corrected by adding the if part of the if-else statement. I am honestly baffled, logical reasoning tells me that JVM is not checking the condition because the thread is not running, however throughout the program I only ever call Thread's start() once, otherwise its untouched by my code. Any wiser sole's opinion would be much appreciated.
Without more information it's hard to tell you exactly what is going wrong. However, I would strongly advise that you write your server in more of an event-based model. Especially given that it's a card game, so I'm guessing it's turn based and not real-time.
Instead of doing your loop based approach, try this:
The server keeps a model of the current state of the game.
The client sends a message to the server. One such message could be "play card XYZ"
The server processes the message and updates the model accordingly. If a user played a card, it might remove that card from the person's hand. It might change some other state based on the effect of the card. All the logic is handled when the message is received.
State changes are sent out to all the clients so that they are seeing a view consistent to the state of the server.
You have multithreading environment. ArrayList is not a threadSafe collection -- it does not guarantee visibility on other threads. This means your waiting thread never sees changes in the collection.
Try to use some collection of java.util.concurrency.
So I have an assignment where I have to create a "game" type application in which there are multiple moving objects (definately over 10) and some are triggered by user KeyEvents.
I seem to understand the concept but I have a question. How do I draw all objects (which animate up and down) and include KeyEvents so they all perform at once, and don't go in a linear sequence. I looked up multi-threading for this but I highly doubt it would be a good idea as I feel this can be done with only 1 thread.
Any feedback or ideas would be greatly appreciated. Thanks! :)
An example of what I mean is:
public void onPaint(Graphics g){
g.draw(apple);
g.draw(character);
moveCharacter(g);
moveApple(g);
}
So here, I have to first move the character, then the apple, how can I do both of them at the same time? Except with multiple objects.
Ideally you will want to separate your actual game logic from the rendering. Do the calculations, moving, etc on a separate thread from the draw thread. There are some subtle complications that may arise from this relating to concurrency, but it's still a good idea.
It's not clear what you mean by "do both at the same time", but the code should execute so fast that it may as well be at the same time. What you want to avoid is having having any sort of blocking in the methods (eg. user input).
My application consists of two class files, let's call them A and B. A is the main one - the one which is executed and the main class of the jar file. In A I define a JFrame, to which I add two JPanels: one of them is composed of JButtons and JLabels, and the other one is a graphical one, and is implemented in B (B extends JPanel).
In B I have a method which could take a while, so I wish to give the user information about the process going on there; namely, I'd like to tell the user how much computation is left. I want to do it by updating a JLabel in class A. However, when I try it, I get that the JLabel is updated only after the method had been completed, i.e. instead of seeing it running from 0% to 100% I only see 100%, all the time.
I don't think I have any relevant pieces of code to show you, but if there's something you'd want me to post, please do let me know.
I've checked similar questions but it appears to me that they asked something quite different.
Thank you,
Ron.
Yours is a threading problem. Your long-running process is tying up the main Swing thread, the EDT, preventing any drawing, updating of components, or user interactions. You need to do the long-running process in a background thread such as one supplied by a SwingWorker object. Do this and your GUI will become much more responsive.
Check out Concurrency in Swing for more on this important topic.
If you need more specific help, you will need to supply more information and code.
Edit: This makes alot more sense to me now that i've taken a step away from the code, thanks for the help.
Just found stack overflow the other day through Coding Horror and it looks awesome. Figure that i'd ask the community about a problem i'm currently trying to work out.
I'm developing a roguelike sortof game using j2me for midp 2.0 phones. The project is still in the basic stages of development as I figure out how it's going to work. The part i'm currently stuck on has to do with threading.
The game has a custom HaxCanvas class which extends GameCanvas and Implements runnable. It's run method calls repaint() and then sleeps for 50 ms, resulting in a frame rate of 20 FPS. This allows me to write the rest of the game without having to put repaint everywhere and should make animations and effects easier to do later on. (at least in theory).
The flow of the game is controlled by a GameManager class, which loops through all the NPC's on the map, taking their turns, until it's the player's turn. At this point I need to get input to allow the player to move around and/or attack things. I originally was calling gameManager.runUntilHeroTurn() in the keyPressed method of my HaxCanvas. However after reading up on j2me system threads I realized that putting a method with the potential to run for a while in a callback is a bad idea. However I must used keyPressed to do input handeling, since i need access to the number keys, and getKeyStates() does not support this.
Sofar my attempts to put my gameloop in it's own thread have resulted in disaster. A strange "uncaught ArrayIndexOutOfBoundsException" with no stack trace shows up after the game has run for several turns .
So i suppose my question is this:
For a "turn based" game in j2me, what's the best way to implement the game loop, allowing for input handeling only when it's the player's turn?
Although not j2me specifically you should capture user input, the general strategy is to queue the input it until its time to process the input.
input ---> queue <---> Manager(loop)
This way you can even script input for debug purposes.
So you don't need a new thread. Each time the user presses key you store them in a buffer, and then process the contents of the buffer when necessary. If the player buffer has no input, the manager should skip all gameplay, do animations and then start over (since the game is not an action game).
I would avoid threading for the game logic as J2ME threading, depending on manufacturer of course, does not do a great job of sharing the limited resources. You will often see pauses while a thread does heavy processing. I would only recommend threads for loading or network connectivity features as in this case you will just be giving the user basic "Loading..." feedback.
To handle this, I would not have sub-loops to update each of the AI in one frame. I would do something like following in the run function:
public void run() {
while(true) {
// Update the Game
if(gameManager.isUsersTurn()) {
// Collect User Input
// Process User Input
// Update User's State
}
else {
// Update the active NPC based on their current state
gameManager.updateCurrentNPC();
}
// Do your drawing
}
}
You want to avoid having everything updated in one frame as 1) the updating might be slow, resulting in no immediate visual feedback for the user 2) you can't animate each individual NPC as they make their action. With this setup you could have NPC states, NPC_DECIDE_MOVE and NPC_ANIMATING, that would allow you further control of what the NPC is doing. NPC_ANIMATING would basically put the game in a waiting state for the animation to take place, avoiding any further processing until the animation is complete. Then it could move on to the next NPC's turn.
Also, I would just have a gameManager.update() and gameManager.paint(g) (paint would be called from paint) that would handle everything and keep the run method thin.
Finally, did you look into flushGraphics()? With the GameCanvas you usually create a Graphics object, draw everything to that and then call flushGraphics(), then wait. The method you mention is the way of tackling it for the Canvas class. Just thought I would mention this and post a link:
Game Canvas Basics