I'm currently programming a game in java and am using an interface to handle input/output for the game. I currently have a text interface working properly. I'm using code similar to the following:
while (moveExists())
{
String in = interface.getInput();
processInput(in);
interface.displayOutput(this.getState);
}
The text only interface works because it pauses to wait for input, but I am not sure how to accomplish a similar behaviour in a GUI implementation. How may I 'wait' for input from an actionListener?
If not, I'll probably use code less like a game loop and more like a finite state machine so that I don't need to deal with two different threads trying to co-ordinate their actions.
You could simply start a GUI (that it has its own separated thread) containing a text area and maybe a button or something like that, then you add an ActionListener to the text area or button and then you execute the code you need when the Listener is triggered (i.e. some code has been inserted or button clicked).
Another story if you have also another 'background' thread that needs to run in a loop...
Related
I wrote a simple little maze game for a terminal which repeatedly asks the user to do something (e.g. "In which direction would you like to go? [N/E/S/W]"). I have a navigate() method running in a loop that fires off these questions, stores their answers and does something depending on the answer.
public enum Dir (N, E, S, W);
public void navigate() {
Dir nextDir = utils.askDirection("Which way do you want to go?");
// Do stuff with answer, like changing position of user in maze
}
Now, I've written a simple GUI for my game. I deliberately put all the references to the terminal in a ConsoleUtils class which implements a Utils interface (this has methods like askQuestion()) - the idea being that I could create a GuiUtils class and have my game either as a terminal game or as a GUI game.
The problem is that the navigate method asks the user a question and then "waits" for the response, which the Utils class gives it by using a Scanner to read the newest line of input. However if I use Event Listeners for the new N/E/S/W buttons in my GUI, they fire off events regardless whether the navigate method has asked for one or not.
--> Image of GUI
Is there any way I can combine this or do I need to write a new navigate method for the GUI?
(To be honest, I'm also not entirely sure whether my GUI class should instantiate a game class, in which case the logic for navigate could end up in a GUI method anyway, or whether the game should have a GUI. I haven't written any code for the event listener either yet, since I'm not sure which class should be calling which. This is probably a separate question.)
Your text based game has a loop that repeatedly asks questions to gather user input. Swing provides this loop for you by continually executing Runnable blocks of code that have been posted to the EventQueue. For example, when the user presses a button labeled E, code is posted to the queue that invokes your ActionEvent implementation to handle your game's interpretation of the move east command.
For reference, a complete example of a very simple guessing game is examined here. In pseudocode, the corresponding text based game might look like this:
initialize
loop
prompt "Guess what color!"
get chosenColor
if chosenColor = actualColor
say "You win!"
reset game
else
say "Keep trying."
end loop
A more elaborate game cited there includes the original text-based source.
This question already has an answer here:
How to stop Java from running the entire code with out waiting for Gui input from The user
(1 answer)
Closed 5 years ago.
I'm a rather basic programmer who has been assigned to make a GUI program without any prior experience with creating a GUI. Using NetBeans, I managed to design what I feel the GUI should look like, and what some of the buttons should do when pressed, but the main program doesn't wait for the user's input before continuing. My question is, how do I make this program wait for input?
public class UnoMain {
public static void main(String args[]) {
UnoGUI form = new UnoGUI(); // GUI class instance
// NetBeans allowed me to design some dialog boxes alongside the main JFrame, so
form.gameSetupDialog.setVisible(true); // This is how I'm trying to use a dialog box
/* Right around here is the first part of the problem.
* I don't know how to make the program wait for the dialog to complete.
* It should wait for a submission by a button named playerCountButton.
* After the dialog is complete it's supposed to hide too but it doesn't do that either. */
Uno Game = new Uno(form.Players); // Game instance is started
form.setVisible(true); // Main GUI made visible
boolean beingPlayed = true; // Variable dictating if player still wishes to play.
form.playerCountLabel.setText("Players: " + Game.Players.size()); // A GUI label reflects the number of players input by the user in the dialog box.
while (beingPlayed) {
if (!Game.getCompleted()) // While the game runs, two general functions are repeatedly called.
{
Player activePlayer = Game.Players.get(Game.getWhoseTurn());
// There are CPU players, which do their thing automatically...
Game.Turn(activePlayer);
// And human players which require input before continuing.
/* Second part of the problem:
* if activePlayer's strategy == manual/human
* wait for GUI input from either a button named
* playButton or a button named passButton */
Game.advanceTurn();
// GUI updating code //
}
}
}
}
I've spent about three days trying to figure out how to integrate my code and GUI, so I would be grateful if someone could show me how to make this one thing work. If you need any other information to help me, please ask.
EDIT: Basically, the professor assigned us to make a game of Uno with a GUI. There can be computer and human players, the numbers of which are determined by the user at the beginning of the game. I coded the entire thing console-based at first to get the core of the game to work, and have since tried to design a GUI; currently this GUI only displays information about the game while it's running, but I'm not sure how to allow the code to wait for and receive input from the GUI without the program charging on ahead. I've investigated other StackOverflow questions like this, this, this, or this, but I cannot comprehend how to apply the answers to my own code. If possible, I'd like an answer similar to the answers in the links (an answer with code I can examine and/or use). I apologize if I sound demanding or uneducated and confusing; I've been working diligently on this project for a couple weeks and it's now due tomorrow, and I've been stressing because I can't advance until I figure this out.
TL;DR - How do I get my main program to wait and listen for a button click event? Should I use modal dialog boxes, or is there some other way to do it? In either case, what code needs to be changed to do it?
Unlike console based programming, that typically has a well defined execution path, GUI apps operate within a event driven environment. Events come in from the outside and you react to them. There are many types of events that might occur, but typically, we're interested in those generate by the user, via mouse clicks and keyboard input.
This changes the way an GUI application works.
For example, you will need to get rid of your while loop, as this is a very dangerous thing to do in a GUI environment, as it will typically "freeze" the application, making it look like your application has hung (in essence it has).
Instead, you would provide a serious of listeners on your UI controls that respond to user input and update some kind of model, that may effect other controls on your UI.
So, to try and answer your question, you kind of don't (wait for user input), the application already is, but you capture that input via listeners and act upon them as required.
I am currently making this text-based rpg game with a simple GUI. I was happy to find the good start at it but then there is something I stumbled upon that made me stop coding for a while.
If you are making this in console, you could easily use this code to pause the movements of the characters for a while, like:
System.out.println("[enemy]");
Thread.sleep(1000);
System.out.println("The local guard waves his sword and tries to stab you in the back, but you quickly parried and tried for a counterattack but you failed.");
If you are doing this on a JTextArea, you'd use the setText but
if you use Thread.sleep it doesnt work and coding setText again, would erase the old text and replace it with the new text, so the records of the fight will not be fully displayed on the game. Is there a way to fix this?
You can use append to append instead of replace. That is the easy part.
The hard part: You have to change your program flow. In Swing there exists a single thread for dispatching GUI events, the event dispatching thread. You should not set the EDT to sleep or do any other long-running operations in it. This will freeze the GUI, it can't respond to anything and will not repaint.
Instead you should either start a new thread for the logic flow and dispatch operations that have to be executed on the EDT (everything that manipulates the GUI) with SwingUtilities.invokeLater or, in this case maybe better, SwingUtilities.invokeAndWait.
Or you should embrace an event driven control flow, e.g. you could use a Timer to output the second text later.
A program flow that works well with single-threaded console programs is not the right approach for multi-threaded GUI applications (and every GUI application is automatically multi-threaded).
for the setText part, you should have a variable which will hold the text and when you want to add a string, you append it and set the text again:
String text ="[enemy]";
textfield.setText(text);
text+= "\nblablabla ..";
textfield.setText(text);
UPDATE:
Some are suggesting to use the append method which is relatively good. Sometimes in the game you would like to append and sometimes replace the whole text (a new character talks), I would recommend something like this:
textfield.setText("[enemy]\n");
textfield.append("blablabla");
//When someone else wanna talk:
thread.Sleep(1000);
textfield.setText("[me]\n");
textfield.append("moreblablabla");
You could also use append() function. See JavaDoc.
jTextField.append("Foo\n");
jTextField.append("Bar\n");
You can use append() instead of setText(). Method append() will append new text at the end of the old text.
I want to create a simple animation of a game so you can see the playout of a game. It should be an animation in which you just see the game Tic-Tac-Toe played. I have the states of the games in a description. So player 1 marks a cell = state 1; player 2 marks a cell = state 2 etc..
I currently have the game parsed in a ruby program; it will be easy to display just one state (like in the image), but how do I create an animation from it? Is there an easy way to do this? I'm open to solutions in every language but it shouldn't take to much time to implement. I want to show such an animation in a presentation.
<state1>
cell(1,1,x).
cell(1,2,o).
cell(1,3,o).
cell(2,1,o).
cell(2,2,x).
cell(2,3,x).
cell(3,1,b).
cell(3,2,b).
cell(3,3,x).
</state1>
<state2>
...
</state2>
Since you already know how to display one state, the way to animate that is to display each state one after the other in sequence.
Display the first state and set a timer, then when the timer goes off show the next state and set another delay, and so on through all the states.
Since you said you are open to all languages I don't really want to bother with any specific code beyond that high-level overview. For example, in Flash/ActionScript I would use TweenLite to display the symbols with a delay, but I don't know if that specific code would be of any use to you.
I've never programmed Ruby but it probably has a command like setDelay() or setTimer() or something. If not, the same effect can be accomplished with a main loop that will check the time each cycle and if the delay has been long enough it shows the next state.
For ruby you can have a awesome tic-tac-toe from https://github.com/grosser/tic_tac_toe
just do "gem install tic_tac_toe"
I'm using the java swing library to develop a board game called DAO.
The problem is that after the human player makes its move, by clicking on the JButton with the piece image that he wants to play, I call the computer AI routine but inside the mouse event function. By doing this only when the function returns, the computer ends its turn, do the JButtons refresh their Images (setIcon comes in).
I'd like to know how can I force the JButtons to change their image at the moment they are clicked and not only when the mouse event function ends (as I need to handle data inside it).
I've tried all of this
myButtons[i][j].setIcon(xIcon);
myButtons[i][j].revalidate();
myButtons[i][j].repaint();
myButtons[i][j].validate();
None worked.
Thx in advance
You may want to try putting the action performed upon clicking the JButton into a Swing worker. This will allow the task to go on in the background, while the user can still click other buttons, etc.
See http://java.sun.com/docs/books/tutorial/uiswing/concurrency/simple.html.
There is a single thread used for all Swing activity.
Here's the process.
One event appears on the event queue
it is pulled from the queue and executed by The AWT Thread
Any new events created while this is executing are placed on the queue to be held until the currently running AWT event returns.
The event executing returns and the next event on the queue is dequeued and executed.
This means that if you need to do anything that takes more than, say 1/100 of a second or so, you shouldn't do it any thread started from a swing event. Instead, spawn your own thread and return the swing thread to the system so the GUI can be updated.
Now, your thread MUST NOT update any GUI objects! If you need to update a GUI object, use invokeLater to place your code back on the AWT thread.
New Java programmers not conforming to this rule and executing tasks on the AWT thread is almost certainly the biggest reason people think Java is slow.