first off apologies for the question title I wasn't to sure what to name this.
anyway I'm working on a game, where there can be a number of players who can each have a number of pets. I have developed the main structure to the game, e.g. player class, pet class and a main class .. From there I have been working on the GUI, where I ask how many players, and how many pets each player would like.. Where I am getting stuck is how to to create the pets for each player.
I have created a pretty basic form that asks for the player to choose a pet type, give it a name and then create the pet..
public void createPets( final Player player){
//various buttons,comboBox and labels go here
//layout managers
//add it all to a frame
JButton jbCreatePet = new JButton("Create Pet");
jbCreatePet.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String name = jtfName.toString();
if (cbSpecies.getSelectedIndex() == 0){
Alien alien = new Alien();
alien.setName(name);
player.getAllPets.add(alien);
}
else if(cbSpecies.getSelectedIndex() == 1){
create other pet2
}
else{
create other pet3
}
}
});
player is a Player object passed into the method using a for loop..
for (Player player: allPlayers){
createPets(player);
}
Now I know that its NOT correct to use the for loop e.g. the form will simply skip to the last player and none of the other players will get to create a pet..
So I have a couple of questions:
When I assigned the created pet to the players list of all pets, eclipse told me I had to create it final. I somewhat understand why but what I am wondering is by making the player parameter final does that mean i wont be able to create pets for other plays, only the first player..
How can I show my form to each player e.g. 2 players in the game both with 2 pets, player 1 chooses a pet and gives it a name then creates it, he will then be told he needs to create another pet (form shows again) so he creates another pet, then its player 2s turn to choose and create 2 pets... I guess I am trying to figure out how to pass the right player argument into the createPet method at the right time...
Please let me know if you would like me to clarify anything else...
Big thanks to whoever can help me with this!!!!
When I assigned the created pet to the players list of all pets, eclipse told me I had to create it final. I somewhat understand why but what I am wondering is by making the player parameter final does that mean i wont be able to create pets for other plays, only the first player..
Eclipse isn't requiring this -- Java is because you're using the Player parameter within an anonymous inner class and so it must be final. This will not prevent you using this same method for other players.
How can I show my form to each player e.g. 2 players in the game both with 2 pets, player 1 chooses a pet and gives it a name then creates it, he will then be told he needs to create another pet (form shows again) so he creates another pet, then its player 2s turn to choose and create 2 pets... I guess I am trying to figure out how to pass the right player argument into the createPet method at the right time...
The main Game object will control all of the above, correct? I suppose you could use a for loop, one that say displays a modal dialog such as a JOptionPane inside of the loop.
Another option is to create JPanel view that allows all players to enter their pets. It's all up to you, and I recommend that you experiment with different approaches.
One main thing that you'll want to be sure to do early on is to strongly separate your program's logic from the GUI. For instance your Player and Pet classes should have no knowledge about the GUI, should have no Swing code whatsoever, so that the code to logically add Pets is non-GUI (but can and will be used by the GUI).
Edit
Consider giving your Game class a registerPlayer(Player player) or editPlayer(Player player) method that any Player can call to register their name, their Pets, and any other property that may be needed to play the game. Then have this method called once when a JButton is pressed. Don't allow the game to progress unless all Players have been properly registered.
Related
I've read through a dozen or so actionlistener/loop related questions here, but I'm not sure I've found my answer. I started on my first large Java project, a text RPG that's spiraled into around 5K lines of logic and game features which was functioning as intended using just the console - when I decided I'd try to build a Java swing GUI for it instead. Here's my problem:
I use a Room object which handles the description of where the player is at and also has an array of options for the player to choose next which it creates dynamically based on what cell the room's id is in on a csv file and what is beside it. I stopped outputting this to the console and instead started creating JButtons based on the options array like so:
public void showNarrate(){
add(dd,gridConstraints);
optionCopy.clear();
int i = 0;
for(JButton j : optionButtons){
//adding and formatting buttons to gridBagConstraint I also set actionCommand for each button to the triggerValue (ID of the next room which the button should take the player to)
}
//I tried using a copy of my JButton array here so I could have something to iterate over in actionListener after clearing out the original
//(Since it needs to be cleared so the next Room's buttons can be built after the player chooses an option)
for(JButton j : optionButtons){
optionCopy.add(j);
}
optionButtons.clear();
//dd is a seperate drawingComponent I used for outputting room descriptions which may be totally unnecessary at this point :/
dd.repaint();
setVisible(true);
}
Over in actionlistener (Same class) this is how I tried to swing it:
for(JButton j : optionCopy){
if(e.getActionCommand().equals(j.getActionCommand())){
Main.saveRoom = Main.currentRoom;
Main.currentRoom = j.getActionCommand();
System.out.println(Main.currentRoom);
}
}}
Then in my main class I call:
narrator.narrate(currentRoom, saveRoom); which takes care of some other logic concerning locked doors, encounters, etc.
Also in Main loop are some other methods related to autosave and tracking which rooms the player has visited. I know from other q/a i'v read on here that this is all pretty bad design, and I'm sttarting to understand that now, but my issue is this:
The first room of the game loads up fine, when I click a button it outputs to console(Just for testing) the correct trigger value of the room the button should be calling, so I'm getting that far, but how can I call the same method over again now?
-If I call narrate from actionListener it will wind up calling itself again and complain about ConcurrentModification.
-If I try to keep a loop going in my Main class it will keep looping and won't allow for the player to actually choose a button.
I've never used threads before, which I wonder might be the answer,and the closest thing to a related answer I've found is this:
Java: Method wait for ActionListener in another class
but I don't think moving actionListener to Main class would resolve my problem which is actionListener winding up calling itself recursively. And as for the observer-observable pattern... I just can't understand it :(
I appreciate any and all help, I've learned a LOT trying to make this thing work without seeking help as much as possible but this has stumped me.
Your loop in actionPerformed only checks whether a JButton exists in your optionList with the given actionCommand. However this can be done before actually doing something:
boolean contained = false;
for (JButton j : optionButtons)
if (j.getActionCommand().equals(e.getActionCommand()))
contained = true;
if (contained) {
// change room
}
now you can call narrate because you have finished iterating over the collection beforehand and will not get a ConcurrentModificationException
I am currently building a game where I would need to do the following:
New currentControls(defualt);
User selects an object on the board
If (selectedObj instanceof typeOfObj) { currentControls.setControls(typeOfObjControls); }
Is there a good structure I could use to implement this? I've looked at a few tutorials but haven't found a good modular way to do it.
Any ideas?
I figured out the answer on my own.
When creating my Controls Class I needed to over write the constructor to contain the object the Player had selected and update in the main game loop which object is currently selected. On instantiation of Controls the Keyboard, mouse, and game controller would be set the same way via the passed selectedObj The Keyboard class would then in turn would only do methods appropriate to the Obj:
if Dog is selected { A: left, D: right}
if bird is selected {A: fly left, D: fly right}
I'm trying to build a text based D&D type game, and I'm stuck on how to let the user call a method at any time during the game.
The game will run its course, and if the user decides at any time they want to take a peak at his/her stats, the user will type "character sheet" and all his stats etc. will show.
My only idea to go about my problem is to to use:
if( variable.equals("character sheet"))
callMethod();
but this only works once.
Now even if I put it in a loop, yes, it would let me do it as many times as I want, but it won't execute the rest of the program...
Without the loop it will let me do it once, and execute the rest of the program but will never let the user type Character Sheet and open the method ever again.
/////////////////
import java.util.Scanner;
public class MainGame
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String characterSheet;
CharacterCreation create = new CharacterCreation();
System.out.println("Choose a race:");
System.out.println("Race List:\nDwarf\nDark Elf\nHalfling\nHuman");
create.stats();
System.out.println("If you want to see your character sheet in the future type 'character sheet'");
characterSheet = input.nextLine();
characterSheet.toLowerCase();
if(characterSheet.equals("Character Sheet"))
create.getStats();
}
}
Well, the big question is: is your game running whatever the user does, or does it run in step with each user action? In the second case, you need a simple loop:
while (isRunning){
getUserInput();
updateGameWorld();
}
If the game runs independently of the user's action, you'll need 2 threads: one that will update the world regularly, and one that will listen to the user inputs and adapt the world to them.
I'd suggest you read about "game loops", but be warned that they usually about drawing graphics in frame, which may dilute their general purpose. But basically you have one game loop that renders the world, and another thread that handles user actions.
I am making some sort of turn-based battle system in a JFrame where the player clicks a button when it's his turn. The problem is: how can the program wait for a mouse click on the button? It goes like this:
while it is the player's turn {
wait for mouse input
if input == attack (for example)
-> attack
else if input == item
-> use item
and so on
You don't wait for a click; you let Swing do that for you. Instead, you put whatever you want to do into an ActionListener and attach it to the button, so it gets executed when the button is clicked.
As far as the turns go, you just need a member variable someplace that keeps track of whose turn it is; the button handler then has to look at that variable to know what to do.
One good way to structure things, by the way, might be to have a Player class, and a Game class, and a member in Game called currentPlayer. Then the ActionListener (which keeps the Game object as a member variable of its own) could look at currentPlayer in the Game and simply invoke makeMove() on the appropriate Player object.
So suppose I'm developing a chess-like program using Java's Swing. I added a MouseListener to handle user input. To make a move the user must click a valid piece and then click a valid place. What's the best way to track the 2 mouse clicks in a turn? I'm thinking in use some kind of variable to record if is the turn's first click or second.
You have to distinguish the two game states, using a variable is fine.. you can also think something as suggested by NomeN comment and use two different listeners by swapping them.
Your case is quite simple but in general the formalism you use to handle these things is a sort of finite state machine that describes the states of your game and how to pass from one to another.
In this case you can have some states like:
player 1 turn
player 2 turn
main screen
pause screen
option screen
and you decide how and when to pass from a state to another, for example
after player1 moved you pass to player2 turn
after player2 moves you go back to player1 turn
when game starts you go in main screen
if you start a new game then you go to player1 turn
if you press pause key while in game you go from turn to pause screen and when closed you go back to the turn that was going before pause
This is just to give you an idea, so for example your MouseListener could care about states:
enum State { TURN_P1, TURN_P2, MAIN, PAUSE, ... }
public State gameState
...
public void mouseClicked(MouseEvent e)
{
if (gameState == TURN_P1)
{
...
if (move_is_legal and so on)
gameState = TURN_P2;
}
else if (gameState == TURN_P2)
{
...
if (move_is_legal and so on)
gameState = TURN_P1;
}
}
Oops, I answered too quickly. Yes, a structure that encodes a click location, looks for intervening motion events and then records the second click. There should be an initiated state, an accept state, and it should probably record a abort state (maybe a press of ESC).