Reputation: 45
I've been working on what should be a relatively simple game, Mormon Sim. The goal is to hold a successful conversation while going door to door. It's pretty simple, on the click of a button, it changes a JLabel's text according to the button and method called. For example, using the Knock button will activate the method knockResponse, which will calculate if someone will come to the door or not. Based on the result of the calculation, someone will answer the door or you will be turned away. The problem is, after a few clicks, usually once the player gets past the knock check, the JLabel begins to revert itself back to other text, and back and forth between a few different things, sometimes completely disregarding the swing timers on them. I really have no idea what is going on here, and I can't really find a reason that this would happen. A whole week of thorough googling has yielded no similar problems or solutions. TL;DR Java has become self aware
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
//To do: ASCII art in JLabels
public class mainMenu implements ActionListener{
static JButton start = new JButton("Start!"), knock = new JButton("Knock"), talk = new JButton("Talk"), stats = new JButton("Stats");
static int level = 1, stamina = 100, knocking = 1, speech = 1, points = 0;
static JFrame frame = new JFrame("Mormon Sim");
static mainMenu game = new mainMenu();
static JLabel text = new JLabel(), knockSkill, speechSkill, staminaBar;
static JPanel DoorMenu = new JPanel();
JTextField name = new JTextField("Enter your name here", 25);
static String playerName;
public JPanel createStartMenu(){//JPanel for the start menu. Replaced on start click
JPanel startMenu = new JPanel();
JLabel instructions = new JLabel("<html>Welcome to Mormon Adventure, the first text-based mormon sim. Your goal is to <br>hold as many successful door to door<br>conversations as possible. Every successful conversation earns you a<br>skill point and a level. Level 15 is a win!<br>A conversation requires stamina as it goes on, find Orange Crush to replenish your stamina<html>");
startMenu.setLayout(null);
startMenu.setLocation(0, 0);
startMenu.setSize(500, 500);
start.setLocation(200, 300);
start.setSize(100, 50);
start.addActionListener(this);
startMenu.add(start);
instructions.setLocation(100, 100);
instructions.setSize(300, 200);
startMenu.add(instructions);
name.setSize(150, 25);
name.setLocation(100, 50);
name.addActionListener(this);
startMenu.add(name);
startMenu.setOpaque(true);
return startMenu;
}
public JPanel createDoorMenu(){//used for knocking, speaking, and going to the stat page. The problem is here
talk.setEnabled(false);
String knockText = "<html>You walk up the driveway of the next house on your<br>list. As you approach the door, you adjust your<br>tie, and smooth your hair. Your mouth is dry, and<br>you could really go for a bottle of orange crush.<br>You decide you should get one after this house.<br>Time to knock, someone is clearly home.<html>";
DoorMenu.setLayout(null);
DoorMenu.setLocation(0, 0);
DoorMenu.setSize(500, 500);
text = new JLabel(knockText);
text.setLocation(100, 150);
text.setSize(300, 200);
DoorMenu.add(text);
knock.setLocation(100, 400);
knock.setSize(100, 50);
knock.addActionListener(this);
DoorMenu.add(knock);
talk.setLocation(200, 400);
talk.setSize(100, 50);
talk.addActionListener(this);
DoorMenu.add(talk);
stats.setLocation(300, 400);
stats.setSize(100, 50);
stats.addActionListener(this);
DoorMenu.add(stats);
knockSkill = new JLabel("Knocking: " +knocking+ " Speech: " +speech+ " Level: " +level+ " Skill Points: " +points);
knockSkill.setLocation(100, 25);
knockSkill.setSize(500, 50);
DoorMenu.add(knockSkill);
DoorMenu.setOpaque(true);
return DoorMenu;
}
public JPanel createStatMenu(){//still doesn't do anything
JPanel statMenu = new JPanel();
return statMenu;
}
public static void knockResponse(){//generates a response from a knock based on knock level (1 <= x <= 10). Random number (1 <= y <= 10) is generated, level determines how many are successful
//max knock level will shatter the door. 50/50 chance of conversation or police. max speech + police will talk them into letting you go
knock.setEnabled(false);
Random rand = new Random();
int n = rand.nextInt(10) + 1;
if(n > knocking){//knock check loss
text.setText("<html>All you hear is someone yelling to go away...<br>Oh well. You chipper up and go to<br>the next house on your list. That orange Crush<br>will have to wait!<html>");
ActionListener taskPerformer = new ActionListener(){//delay the label reset
public void actionPerformed(ActionEvent evt){
text.setText("<html>You walk up the driveway of the next house on your<br>list. As you approach the door, you adjust your<br>tie, and smooth your hair. Your mouth is dry, and<br>you could really go for a bottle of orange crush.<br>You decide you should get one after this house.<br>Time to knock, someone is clearly home.<html>");
knock.setEnabled(true);
}
};
new Timer(1000, taskPerformer).start();
}
if(n <= knocking && knocking != 10){//successful knock check
knock.setEnabled(false);
stats.setEnabled(false);
text.setText("<html>Someone's coming to the door!<br>You straighten your hair and adjust your tie.<html>");
ActionListener taskPerformer = new ActionListener(){//delay the label reset
public void actionPerformed(ActionEvent evt){
text.setText("<html>The door opens, and you introduce yourself;<br>\"Hi! my name is " +playerName+ ". Have you accepted my homeboy JC as your lord and savior?\"<html>");//I couldn't really think of anything to make him say other than that
talk.setEnabled(true);
}
};
new Timer(1000, taskPerformer).start();
}
if(knocking == 10){//door breaks
text.setText("<html>You managed to shatter the door thanks to<br>your orange crush powered knocking skeelz.<html>");
n = rand.nextInt(1) + 1;
if(n == 0){//response check. Both are empty for now
text.setText("0");
}else if(n == 1){
text.setText("1");
}
}
}
public static void successCalc(){//calculate the success in talking to someone by
talk.setEnabled(false);
Random rand = new Random();
int n = rand.nextInt(10) + 1;
if(n <= speech && speech != 10){
level++;
points++;
text.setText("<html>After some time, your conversation is over.<br>That went well. Better than you thought.<br>As you leave, you feel a rumbling in your gut.<br>It soon becomes painful. You fall to<br>the ground, and a gleaming light comes from<br>your stomach, as a skill point bursts out.<br>You hear a faint \"dunananaaa...\"<html>");
talk.setEnabled(false);
knockSkill.setText("Knocking: " +knocking+ " Speech: " +speech+ " Level: " +level+ " Skill Points: " +points);
}else if(n > speech){
talk.setEnabled(false);
text.setText("<html>After a moment of you speaking, all they do<br>is start blaring death metal.<br>You decide it's time to leave!<html>");
}else if(speech == 10){
text.setText("<html>Your golden, heavenly voice convinces them<br>to convert immediately.<br>You run down to the nearest convenience store<br>and grab yourself an orange Crush. Bottled, of course.<html>");
}
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == start){
frame.getContentPane().removeAll();
frame.setContentPane(createDoorMenu());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setResizable(false);
frame.setVisible(true);
}else if(e.getSource() == knock){
knock.setEnabled(false);
knockResponse();
}else if(e.getSource() == talk){
talk.setEnabled(false);
successCalc();
}
playerName = name.getText();
}
public static void createAndShowGUI(){
JFrame.setDefaultLookAndFeelDecorated(false);
frame.setContentPane(game.createStartMenu());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setResizable(false);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
createAndShowGUI();
}
});
}
}
Thanks for any help, I'm terrible at asking questions.
Upvotes: 1
Views: 175
Reputation: 16364
A Timer
starts out repeating, by default. So, your timers are all firing every second, forever.
You ought to call setRepeats(false)
:
void doLater(ActionListener action, int delay) {
Timer timer = new Timer(delay, action);
timer.setRepeats(false);
timer.start();
}
Upvotes: 4