Java: turn-based battle system (with gui) - java

EDIT (4/3/2017): Sorry, I was a noob back then.
I'm trying to make a turn-based battle system where the player clicks buttons on his turn. But I can't seem to find out how to code it. Below is the code on what I did.
What should happen here is that when I click the attack button(for example) the next turn will be the monster's turn but the playerTurn variable doesn't change when I click the button. playerTurn is always true. Can you help me correct this? It is a turn-based battle system.
public class BattleFrame extends JFrame implements ActionListener, Runnable {
private JButton atkButton = new JButton("Attack");
private JButton runButton = new JButton("Run");
private JButton itemButton = new JButton("Item");
private JButton magicButton = new JButton("Magic");
private JPanel panelButtons = new JPanel();
private Random rand = new Random();
private Boolean playerTurn;
private Thread t;
public BattleFrame() {
setSize(480, 390);
setLayout(null);
// I have not included the code with the setting of the JButtons
initPanel(); // initialize the panel with buttons
setResizable(false);
setVisible(true);
playerTurn = true;
t = new Thread(this);
t.start();
}
// I'm not so familiar with 'synchronized' but I tried it here but it doesn't change anything
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if(src.equals(atkButton) && playerTurn) {
System.out.println("Attack!");
playerTurn = false;
}
else if(src.equals(runButton) && playerTurn) {
System.out.println("Run!");
playerTurn = false;
}
else if(src.equals(itemButton) && playerTurn) {
System.out.println("Item");
playerTurn = false;
}
else if(src.equals(magicButton) && playerTurn) {
System.out.println("Magic");
playerTurn = false;
}
}
public void run() {
while(true) {
if(playerTurn == false) {
System.out.println("Monster's turn!"); // just printing whose turn it is
playerTurn = true;
}
else System.out.println("player's turn!");
}
}
public static void main(String[] args) {
new BattleFrame();
}
}

A Boolean is an object, so gets compared by identity, not value.
assert new Boolean (true) == new Boolean(true);
The above will fail, as the two different Boolean objects are not the same object.
For general use, use the primitive type boolean, not the standard library class Boolean. Cases where you should use Boolean are pretty rare: it's one of those things that exists more for symmetry than any real practical reason. If you do use it, you need to use a.equals(b) not a == b.
For more details, see:
http://www.java-samples.com/showtutorial.php?tutorialid=221

Related

Separating KeyListener and JFrame into 2 different classes

I will show you two different codes to demonstrate what i'm asking for.
The First code work fine it includes the JFrame and KeyListener in one class however what i want is to separate them.
First Code Below...
public class Fgui extends JFrame implements KeyListener{
private JPanel jp;
private Icon background = new ImageIcon(getClass().getResource("back2.png"));
private Icon monster = new ImageIcon(getClass().getResource("mol.png"));
protected JLabel mon;
private JLabel backG;
protected int monX = 300;
private int monY = 225;
protected int monDX = 0;
private int monDY = 0;
protected JLabel ct = new JLabel("Change Text");
protected int code;
public Fgui(){
super("Crazy Monster Eating Game");
this.setSize(750,400);
this.setLayout(null);
mon = new JLabel(monster);
backG = new JLabel(background);
this.addKeyListener(this);
this.add(mon);
mon.setSize(150,150);
mon.setLocation(monX, 225);
this.add(ct);
ct.setSize(750,20);
ct.setLocation(0,0);
this.add(backG);
backG.setSize(750,400);
backG.setLocation(0,0);
}
public void keyPressed(KeyEvent e) {
code = e.getKeyCode();
if(code == KeyEvent.VK_LEFT){
monDX = -40;
ct.setText("left key pressed");
monX = monDX+monX;
}
else if(code == KeyEvent.VK_RIGHT){
monDX = 40;
ct.setText("right key pressed");
monX = monDX+monX;
}else if(code == KeyEvent.VK_ESCAPE){
try{ct.setText("ESC key pressed");
this.dispose();}catch(Exception excep){System.out.println("Failed to EXIT!");}
}else{
ct.setText("Key not registred");
}
mon.setLocation(monX, 225);
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
}
Then i tried to separate them and ended up with the following code,
Second Code...
JFrame Half
public class Fgui extends JFrame {
private JPanel jp;
private Icon background = new ImageIcon(getClass().getResource("back2.png"));
private Icon monster = new ImageIcon(getClass().getResource("mol.png"));
protected JLabel mon;
private JLabel backG;
protected int monX = 300;
private int monY = 225;
protected int monDX = 0;
private int monDY = 0;
protected JLabel ct = new JLabel("Change Text");
protected int code;
public Fgui(){
super("Crazy Monster Eating Game");
this.setSize(750,400);
this.setLayout(null);
mon = new JLabel(monster);
backG = new JLabel(background);
KeyL KeyLObj = new KeyL();
this.addKeyListener(KeyLObj);
this.add(mon);
mon.setSize(150,150);
mon.setLocation(monX, 225);
this.add(ct);
ct.setSize(750,20);
ct.setLocation(0,0);
this.add(backG);
backG.setSize(750,400);
backG.setLocation(0,0);
}
}
KeyListener Half
public class KeyL extends Fgui implements KeyListener{
public void keyPressed(KeyEvent e) {
code = e.getKeyCode();
if(code == KeyEvent.VK_LEFT){
monDX = -40;
ct.setText("left key pressed");
monX = monDX+monX;
}
else if(code == KeyEvent.VK_RIGHT){
monDX = 40;
ct.setText("right key pressed");
monX = monDX+monX;
}else if(code == KeyEvent.VK_ESCAPE){
try{ct.setText("ESC key pressed");
this.dispose();}catch(Exception excep){System.out.println("Failed to EXIT!");}
}else{
ct.setText("Key not registred");
}
mon.setLocation(monX, 225);
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
}
The Second Code here has two separate classes one is JFrame class the other is for KeyListener class but when i compile it, it does not work. I assume it is the problem with me adding the addKeyListener statement in a wrong way.
KeyL KeyLObj = new KeyL();
this.addKeyListener(KeyLObj);
I tried adding it through the KeyL class but it didn't work either.
The reason i want to do this is because i don't want the code to be cramped all in one class, but separate it into 2 to make it seem more clean. And if i want to add more key events i can just do it in that one class.
The problem you're seeing is pretty simple. Because you make KeyL a subclass of Fgui, every time a new KeyL is constructed, all of the Fgui initialization code will get run.
So you get to this line:
KeyL KeyLObj = new KeyL();
That creates a new KeyL, so before that line finishes, a new KeyL object has to be created. Since a KeyL is an Fgui, the Fgui constructor gets called. And the FGui constructor eventually gets to that same line, KeyL KeyLObj = new KeyL();, so the process repeats itself. You can never get past that line, because each new KeyL needs to make another KeyL before it can be fully constructed, so the program just keeps making new objects until it runs out of space.
The answer is that there's no reason for KeyL to be a Fgui. Make it just implement KeyListener, and not extend Fgui. Then, make sure it has access to all the variables it needs to accomplish its task.
Most of your variables should not be fields in the object; they should just be local variables. Anything that doesn't need to exist outside that function, or keep it's value between calls, should be changed to a local variable. It looks like the only two that matter are mon, ct, and the Fgui which you reference with this. So make those arguments into KeyL's constructor (as two JLabels and a JFrame), and then call your methods on those.

Java, is there a better way to do key detection?

So I'm just learning java, and from my work in C++, key dectection was much easier with SDL. But when I try to do it in Java it never seems to work. Could someone please check my code and make sure all of this is alright? And yes I did import everything....
public class start extends JFrame{
JLabel label = new JLabel();
Screen circle = new Screen();
int x = 0;
int y = 0;
static boolean m = false;
boolean running = true;
public static void main(String args[]){
start gui = new start();
gui.go();
}
public void go(){
JFrame j = new JFrame();
j.setDefaultCloseOperation(EXIT_ON_CLOSE);
j.setSize(400,400);
pannel p = new pannel();
Player player = new Player();
j.add(player);
j.setVisible(true);
player.addKeyListener(new key());
//try{
// for(int i = 0; i < 300; i ++){
// player.update();
// Thread.sleep(50);
// j.repaint();
// }
//}
//catch(Exception e){}
This try block was me testing to make sure that player.update() worked.... which it did! So I know the problem isn't with the update function
while(running){
//Updates
if(m)
player.update();
System.out.println(m);
I have the program printing out the value of m to see if its ever true... which it never is...
//Rendering
player.repaint();
}
}
public class pannel extends JPanel{
public void pannel(){
JPanel p = new JPanel();
Player player = new Player();
p.add(player);
p.setVisible(true);
}
}
public class key implements KeyListener{
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_SPACE:
m = true;
break;
}
}
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_SPACE:
m = false;
break;
}
}
public void keyTyped(KeyEvent e) {
}
}
}
In C++ there was a function that you had to call in order to detect if there has been any sort of key detection. You used this function in the main loop and it was really easy... Is there a function like this for Java? Or do I really need to put a key listener on EVERY object that I want to be effected by that key?
The simplest solution, and generally the more powerful, would be to use the key bindings API
The main problem with KeyListener is that is focus contextual. That is, the component it is registered to must be focusable AND have focus before it will raise key events

Displaying correct information in JPanel

I'm having trouble updating JPanels with new data. I'm working on a game, the basic concept of what I'm trying to do is load a player and display the items he holds in a JPanel (set out in a box layout) I am using a thread and loop to update the player items. This works fine for one player but my game allows for additional players which the user can switch between. When I switch to the next player I want their details to be loaded and updated. This doesn't work.
This is just a snippet of the code but I'm hoping someone will be able to see my problem.
private JFrame frame;
private JPanel mainPanel;
private Box Item1 Item2, Item3;
static private JPanel centerPanel;
private boolean playerLoaded;
private Player currentPlayer;
private Thread gameThread;
public void run(){
while (running){
for (Player player:allPlayers){
playerLoaded = false;
currentPlayer = player;
player.setCurrentTurn(true);
while (player.isCurrentTurn()){
if (playerLoaded != true){
loadPlayer(player);
loadItems(player);
playerLoaded = true;
}
if ((playerLoaded == true){
updateItems(player);
try {
Thread.sleep(999);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
public void loadPlayer(Player player){
jlCurrentPlayer.setText("Player: " + player.getName());
}
public void loadItems(Player player){
int count = 1;
centerPanel = new JPanel(new GridLayout(1,3));
for (Item Item : player.getAllItems()){
if (count == 1) {
Item1 = Box.createVerticalBox();
Item1.setBorder(BorderFactory.createLineBorder(Color.BLACK));
JLabel jlItem = new JLabel(item.getName());
Item1.add(jlItem);
centerPanel.add(Item1);
}
else if (count ==2){
Item2 = Box.createVerticalBox();
Item2.setBorder(BorderFactory.createLineBorder(Color.BLACK));
JLabel jlItem = new JLabel(item.getName());
Item2.add(jlItem);
centerPanel.add(Item2);
}
else if (count ==3){
Item3 = Box.createVerticalBox();
Item3.setBorder(BorderFactory.createLineBorder(Color.BLACK));
JLabel jlItem = new JLabel(item.getName());
Item3.add(jlItem);
centerPanel.add(Item3);
}
mainPanel.add(centerPanel,BorderLayout.CENTER);
count++;
}
}
public void updateItemstats(Player player){
int count = 1;
if (player.isCurrentTurn()){
for (Item item : player.getAllItems()){
if ((count == 1) && (player.isCurrentTurn())) {
Item1.add(Box.createVerticalGlue());
Item1.add(new JLabel("Value: " + item.getstats().getValue()));
Item1.add(new JLabel("Quality: " + item.getStats().getQuality()));
}
else if (count ==2){
Item2.add(Box.createVerticalGlue());
Item2.add(new JLabel("Value: " + item.getstats().getValue()));
Item2.add(new JLabel("Quality: " + item.getStats().getQuality()));
}
else if (count ==3){
Item3.add(Box.createVerticalGlue());
Item3.add(new JLabel("Value: " + item.getstats().getValue()));
Item3.add(new JLabel("Quality: " + item.getStats().getQuality()));
}
count++;
}
}
}
JButton jbNext = new JButton("Next Player");
jbNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
currentPlayer.setCurrentTurn(false);
}
});
For my main frame I am using a Border Layout. Whats happening when I switch players is basically the updated information is sometimes a mix of player 1 and 2. e.g.
value 25
Quality 60
value 50
Quality 20.
In addition if player 1 has 1 Item and player 2 has 3 Items and I switch from player 2 to 1 sometimes player 1 will have all of player 2 items instead of his own.
I thought it might be an issue with the Item1 2 and 3 panels so I tried to remove them on next player btn click but this just caused an exception. This may well be the problem still and I may not be removing them correctly.
Can anyone out there help me out with this?
You should call setCurrentTurn(true) for the next Player in the next player action Listener.
Have you set the currentPlayer variable in Player to volatile? Important: Both the private Player currentPlayer and the private boolean currentPlayer in the Player.java must be volatile. (Have a look at http://javamex.com/tutorials/synchronization_volatile.shtml)
Also, use a Monitor and wait() instead of Thread.sleep that way you can use notify() to wake up the waiting Thread.
Here are some suggestions for your code, but be aware that you will have to do more (e.G. in the Player.java class that you did not show).
volatile List<Player> players = ...; // load your list of Player
volatile int currentPlayerIndex = 0;
volatile Player currentPlayer = null;
private final Object WAIT_MONITOR = new Object(); // yes, 'new Object()' !
[...]
public void run() throws InterruptedException {
playerLoop:
while(programRunning) { // maybe while(true)
synchronized (WAIT_MONITOR) {
loadPlayer(currentPlayer);
loadItems(currentPlayer);
updateItems(currentPlayer);
WAIT_MONITOR.wait(1000);
}
}
}
[...]
JButton jbNext = new JButton("Next Player");
jbNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
synchronized(WAIT_MONITOR) { // this causes that the contents of run() and this method do not run at the same time.
currentPlayer.setCurrentTurn(false);
if(players.size() > currentPlayerIndex + 1) // don't use >=
currentPlayerIndex++;
else
currentPlayerIndex = 0; // reset at the end of the list
currentPlayer = players.get(currentPlayerIndex);
currentPlayer.setCurrentTurn(true);
WAIT_MONITOR.notifyAll(); // that causes the wait() method above to be continued.
}
}
});

Combination Lock (Java)

I have a school assignment that i need to create. Below is the info:
Create a frame with ten buttons, labeled 0 through 9. To exit the program, the user must click on the correct three buttons in order, something like 7-3-5. If the wrong combination is used, the frame turns red.
I already finish the frame and the buttons with online research helps, but i just cant make the functionality to work. Please take a look at my codes and thanks in advance.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ComboNumber extends JFrame implements ActionListener{
//variable declaration
int ans1 = 3;
int ans2 = 7;
int ans3 = 1;
int one, two, three;
String inData1, inData2, inData3;
JButton[] button;
//constructs the combolock object
public ComboNumber()
{
//sets flowlayout
getContentPane().setLayout(new FlowLayout());
Container c = getContentPane();
//creates buttons
button = new JButton[10];
for(int i = 0; i < button.length; ++i) {
button[i] = new JButton("" + i);
//adds buttons to the frame
c.add(button[i]);
//registers listeners with buttons
button[i].addActionListener(this);
}
//sets commands for the buttons (useless)
//sets title for frame
setTitle("ComboLock");
}
//end combolock object
//listener object
public void actionPerformed(ActionEvent evt)
{
Object o = evt.getSource();
for(int i = 0; i < button.length; ++i) {
if(button[i] == o) {
// it is button[i] that was cliked
// act accordingly
return;
}
}
}
//end listener object
//main method
public static void main (String[] args)
{
//calls object to format window
ComboNumber frm = new ComboNumber();
//WindowQuitter class to listen for window closing
WindowQuitter wQuit = new WindowQuitter();
frm.addWindowListener(wQuit);
//sets window size and visibility
frm.setSize(500, 500);
frm.setVisible(true);
}
//end main method
}
//end main class
//window quitter class
class WindowQuitter extends WindowAdapter
{
//method to close the window
public void windowClosing(WindowEvent e)
{
//exits the program when the window is closed
System.exit(0);
}
//end method
}
//end class
The basic idea is simple.
You need two things.
What the combination actually is
What the user has guessed
So. You need to add two variables. One contains the combination/secret, the other contains the guesses.
private String secret = "123";
private String guess = "";
This allows you to make the combination as long as you like ;)
Then in your actionPerformed method, you need to add the most recent button click to the guess, check it against the secret and see if they've made a good guess. If the length of the guess passes the number of characters in the secret, you need to reset the guess.
public void actionPerformed(ActionEvent evt) {
Object o = evt.getSource();
if (o instanceof JButton) {
JButton btn = (JButton) o;
guess += btn.getText();
if (guess.equals(secret)) {
JOptionPane.showMessageDialog(this, "Welcome Overloard Master");
dispose();
} else if (guess.length() >= 3) {
JOptionPane.showMessageDialog(this, "WRONG", "Wrong", JOptionPane.ERROR_MESSAGE);
guess = "";
}
}
}

Trouble with RadioButtons and booleans connection

Well its weird. I am not good with radiobuttons by the way. But I made a JPanel program in netbeans which includes a RadioButton. You enter all this information with JTextFields(no problem) and then lastly I had a JButton which you click the choice you want. Then I have a JButton that takes all the information and outputs this. For the RadioButton, I first entered the usual:
family = new JRadioButton("Family", true);
friend = new JRadioButton("Friend");
relative = new JRadioButton("Relative");
friendFriend = new JRadioButton("Friend of Friend");
ButtonGroup group = new ButtonGroup();
group.add (friend);
group.add (family);
group.add (relative);
group.add (friendFriend);
(I'm not sure if I needed a listner for the RadioButtons or not but my program still seems to "crash" no matter what).
then I had one action listner for the JButton which included all the textfields and radio buttons. But the RadioButton is the issue.
In the action listner I had:
Object source = event.getSource();
if (source == family)
relation1 = true;
else
if (source == friend)
relation2 = true;
else
if(source == relative)
relation3 = true;
else
if(source == friendFriend)
relation4 = true;
Then I made a relation class:
public class Relation {
private boolean arrayFamily, arrayFriend, arrayRelative, arrayFriendFriend;
public Relation(boolean relation1, boolean relation2, boolean relation3,
boolean relation4)
{
this.arrayFamily = relation1;
this.arrayFriend = relation2;
this.arrayRelative = relation3;
this.arrayFriendFriend = relation4;
}
public String relations ()
{
String relationship = null;
if(arrayFamily && !arrayFriend && !arrayRelative && !arrayFriendFriend == true)
{
relationship = "Family";
}
else
if(arrayFriend && !arrayFamily && !arrayRelative &&
!arrayFriendFriend == true)
{
relationship = "Friend";
}
else
if(arrayRelative && !arrayFamily && !arrayFriend &&
!arrayFriendFriend == true)
{
relationship = "Relative";
}
else
if(arrayFriendFriend && !arrayFamily && !arrayFriend &&
!arrayRelative == true)
{
relationship = "Friend of a Friend";
}
return relationship;
}
}
LASTLY back in the action listner, I implementer this class:
Relation relationship = new Relation(relation1, relation2, relation3
, relation4);
String arrayRelation = relationship.relations();
I lastly included arrayRelation in an array but the array worked fine.
My problem is that the output of the array for my RadioButtons keeps reading "null" (most likey because this code: String relationship = null;). I assume this means that none of my if else statements were satisfied and I really dont know why.
Also important to point out is that if I click submit without clicking any radio button (the button stays on "family"), it reads null. If I click a button once it works perfectly reading the string I intended. But if I click another button afterwards and click submit again, the string goes back to "null".
I know its lengthy but I would really appreciate any help because I am lost.
P.S. some parts of my code are repetitive because I was playing around trying to fix the problem.
I suggest you handle your action events separately, for example:
family.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
familyActionPerformed(evt);
}
});
Then implement familyActionPerformed(evt):
private void familyActionPerformed(java.awt.event.ActionEvent evt) {
// every click on family radio button causes the code here to be executed
relation1 = true;
}
Also write an event handler for the button you click, like this:
submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
// Here test the state of each radio button
relation1 = family.isSelected();
relation2 = friend.isSelected();
relation3 = relative.isSelected();
relation4 = friendFriend.isSelected();
}
MORE EDIT:
Doing what you're doing with NetBeans should be very easy. Here are tutorials that will clear it all up for you:
Tutorial 1
Tutorial 2
I explain the solution again:
Using 'family' button as an example, in your constructor where you have created and initialised your GUI components do this:
JRadioButton family = new JRadioButton();
// do any other thing you want to do to this button and finally..
family.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
familyActionPerformed(evt);
}
});
JButton submit = new JButton("Submit");
submit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
submitActionPerformed(evt);
}
});
Then somewhere create these methods:
private void familyActionPerformed(java.awt.event.ActionEvent evt){
// each time family is selected, you code processes the lines below:
...
}
private void submiteActionPerformed(java.awt.event.ActionEvent evt){
relation1 = family.isSelected();
relation2 = friend.isSelected();
relation3 = relative.isSelected();
relation4 = friendFriend.isSelected();
}
Do something similar for the rest of the RadioButtons.
I think that you're making things way too complex for yourself. If all you want is the String of the JRadioButton pressed, then use the ButtonGroup to get it for you. It can return the ButtonModel of the selected JRadioButton (if any one was selected), and from that you can extract the actionCommand String, although you'll have to remember to set this when you create your JRadioButton.
For example:
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class JRadioExample extends JPanel {
private static final String[] RADIO_TITLES = { "Family", "Friend",
"Relative", "Friend or Relative" };
private ButtonGroup btnGrp = new ButtonGroup();
public JRadioExample() {
for (int i = 0; i < RADIO_TITLES.length; i++) {
JRadioButton rBtn = new JRadioButton(RADIO_TITLES[i]);
rBtn.setActionCommand(RADIO_TITLES[i]); // ***** this is what needs to
// be set
btnGrp.add(rBtn);
add(rBtn);
}
add(new JButton(new BtnAction("Get Chosen Selection")));
}
private class BtnAction extends AbstractAction {
public BtnAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent evt) {
ButtonModel model = btnGrp.getSelection();
if (model != null) {
String actionCommand = model.getActionCommand();
System.out.println("Selected Button: " + actionCommand);
} else {
System.out.println("No Button Selected");
}
}
}
private static void createAndShowGui() {
JRadioExample mainPanel = new JRadioExample();
JFrame frame = new JFrame("JRadioExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Categories

Resources