Reputation: 11
I want to create a timer that counts up. Due to my game using swing components I want to use swing components for this task as well.
I also want the Timer to be repainted onto a JLabel. It should stop the timer when the player collides with the finish JLabel
when I try to print out the timer on a JLabel I get this issue: javax.swing.Timer@42cc41de
This class is the gamepane class.It is where all the components of the game are created. The walls are created here. The collisions is a for loop using an index. the walls are in an array. This is a cut down version of my game which only contains 6 walls. I usually have 49. I also cut down on some unnecessary classes such as one that is used for files and another that has my second maze in it.
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.time.Duration;
import java.time.Instant;
/**
* demonstrates basic animation using a timer, an action listener, and a key
* listener demonstrates basic collisions between rectangular objects
*
* @author 602052004
*/
public class GamePane extends JPanel implements ActionListener, KeyListener {// *change
// GamePane
// to
// GamePane
// This is were the game screen is made and the player is created.
static final long serialVersionUID = 1L;
private Duration timeOutDuration = Duration.ofSeconds(5);
private Instant startTime; // Set this when you're ready to start the timer
JLabel player = new JLabel();
JLabel finish = new JLabel();
JLabel instructions = new JLabel(
"The controls for this game will be using the WASD keys. W is going up, A is going to the left, S is going down and, D is going right.");
JFrame gameFrame;
int playerSpeed = 4;
int FPS = 40;
// This array holds my Jlabels for the walls.I used it so that i can have a
// for loop with an index for the labels.
JLabel[] walls = new JLabel[6];//this is cut down from 49-6
{
walls[0] = new JLabel();
walls[1] = new JLabel();
walls[2] = new JLabel();
walls[3] = new JLabel();
walls[4] = new JLabel();
walls[5] = new JLabel();
}
private final Set<Integer> keys = new HashSet<>();
// The keys set holds the keys being pressed
public static void main(String[] args) {
// Open the GUI window
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Create a new object and
// run its go() method
new GamePane().go();
}
});
}
GamePane() {
// Run the parent class constructor
super();
// Allow the panel to get focus
setFocusable(true);
// Don't let keys change the focus
}
protected void go() {
setLayout(new CardLayout());
// Setup the window
gameFrame = new JFrame();
// Add this panel to the window
gameFrame.setLayout(new CardLayout());
gameFrame.add(this, "main");
gameFrame.setContentPane(this);
// Set's the window properties
gameFrame.setTitle("main");
gameFrame.setSize(800, 600);
gameFrame.setLocationRelativeTo(null);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setVisible(true);
gameFrame.add(new ButtonPane(gameFrame), "buttons");
// Creates the new JPanel that will hold the game.
JPanel gamestage = new JPanel();
gamestage.setBackground(Color.darkGray);
gameFrame.add(gamestage, "game");
gamestage.setLayout(null);
// *Move the setup of the player and the timer under the walls
// Get a sample of collisions going so that i can do it over the weekend
// Setup the movable box
player.setBounds(25, 25, 20, 20);
player.setVisible(true);
player.setBackground(Color.red);
// Opaque makes the background visible
player.setOpaque(true);
// Setup the key listener
addKeyListener(this);
// Null layout allows moving objects!!!
gamestage.add(player);
// Set the timer
Timer tm = new Timer(1000 / FPS, this);
tm.start();
Timer gameTimer = new Timer(1000 / 30, this);
gameTimer.start();
System.out.println(gameTimer);
walls[0].setBounds(10, 15, 10, 480);// left height
walls[0].setVisible(true);
walls[0].setBackground(Color.white);
walls[0].setOpaque(true);
gamestage.add(walls[0]);
walls[1].setBounds(10, 10, 490, 10);// top width
walls[1].setVisible(true);
walls[1].setBackground(Color.white);
walls[1].setOpaque(true);
gamestage.add(walls[1]);
walls[39].setBounds(490, 10, 10, 480);// Right width
walls[39].setVisible(true);
walls[39].setBackground(Color.white);
walls[39].setOpaque(true);
gamestage.add(walls[39]);
// wall3.setBounds(x, y, width, height);
walls[2].setBounds(10, 100, 100, 10);
walls[2].setVisible(true);
walls[2].setBackground(Color.white);
walls[2].setOpaque(true);
gamestage.add(walls[2]);
walls[3].setBounds(100, 60, 10, 40);
walls[3].setVisible(true);
walls[3].setBackground(Color.white);
walls[3].setOpaque(true);
gamestage.add(walls[3]);
walls[4].setBounds(70, 60, 35, 10);
walls[4].setVisible(true);
walls[4].setBackground(Color.white);
walls[4].setOpaque(true);
gamestage.add(walls[4]);
finish.setBounds(30, 455, 20, 20); // *make the game change to the main
// screen when finished
// Add a timer
finish.setVisible(true);
finish.setBackground(Color.LIGHT_GRAY);
finish.setOpaque(true);
gamestage.add(finish);
instructions.setVisible(true);
instructions.setOpaque(true);
instructions.setBounds(510, 10, 265, 525);
instructions.setBackground(Color.GRAY);
instructions.setForeground(Color.white);
gamestage.add(instructions);
}
/**
* Check if two JLabel objects are touching &
*
* @param a
* The first JLabel
* @param b
* The second JLabel
* @return true if the JLabels are touching
*/
public boolean areColliding(JLabel a, JLabel b) {
return a.getBounds().intersects(b.getBounds());
}
/**
* this method makes the player move. It takes the players speed and subtracts
* or adds the player speed to the current position of the player. It also
* figures out were the player is at currently as well. This method also
* contains a for loop which is used to see if the player is colliding with the
* walls
*
* @param arg0
*/
@Override
public void actionPerformed(ActionEvent arg0) {
// Move up if W is pressed
if (keys.contains(KeyEvent.VK_W)) {
player.setLocation(player.getX(), player.getY() - playerSpeed);
}
// Move right if D is pressed
if (keys.contains(KeyEvent.VK_D)) {
player.setLocation(player.getX() + playerSpeed, player.getY());
}
// Move down if S is pressed
if (keys.contains(KeyEvent.VK_S)) {
player.setLocation(player.getX(), player.getY() + playerSpeed);
}
// Move left if A is pressed
if (keys.contains(KeyEvent.VK_A)) {
player.setLocation(player.getX() - playerSpeed, player.getY());
}
for (int i = 0; i < walls.length; i++) {
if (areColliding(walls[i], player)) { // Reposition the target
int newX = (int) (25);// This is the new location of the player in the X axis once it hits a wall
int newY = (int) (25);// this is the new location of the player in the Y axis once it hits a wall
player.setLocation(newX, newY);// Sets the location of the player once the new X and Y location is set
}
}
if (areColliding(finish, player)) {// to change the pane when you fimish the game
// Reposition the target
int newX = 25;
int newY = 25;
player.setLocation(newX, newY);
CardLayout layout = (CardLayout) gameFrame.getContentPane().getLayout();
layout.show(gameFrame.getContentPane(), "buttons");
}
if (startTime != null) {
Duration runningTime = Duration.between(startTime, Instant.now());
Duration timeRemainig = timeOutDuration.minus(runningTime);
if (timeRemainig.isNegative() || timeRemainig.isZero()) {
// Time has run out...
startTime = null; // stop the timer
System.out.println("finish");
} else {
// Update the UI
repaint();
}
}
}
@Override
public void keyPressed(KeyEvent e) {
// Add the key to the list
// of pressed keys
if (!keys.contains(e.getKeyCode())) {
keys.add(e.getKeyCode());
}
}
@Override
public void keyReleased(KeyEvent e) {
// Remove the key from the
// list of pressed keys
keys.remove((Integer) e.getKeyCode());
}
@Override
public void keyTyped(KeyEvent e) {
}
}
This is the button pane which contains the Button and the action listener. It also changes the screens for me.
/**
* This pane contains the button and sets up the button pane
*/
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonPane extends JPanel {
private JButton startBTN;// Calls the JButton
JFrame game;
public ButtonPane(JFrame g) {
game = g;
setLayout(new GridBagLayout());
setBackground(Color.gray);// Sets the menu stages color blue
startBTN = new JButton("Start");// Creates a new button
add(startBTN);// Adds the button on the startStage
startBTN.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (game.getContentPane().getLayout() instanceof CardLayout) {
CardLayout layout = (CardLayout) getParent().getLayout();
layout.show(game.getContentPane(), "game");
}
}
});
}
}
Upvotes: 0
Views: 319
Reputation: 347194
when I try to print out the timer on a JLabel I get this issue: javax.swing.Timer@42cc41de
Timer
doesn't carry any "time" information, it is simply responsible for scheduling the call back at regular intervals on the Event Dispatching Thread.
In order to print either the running or remaining time, you need to format the Duration
according to your needs.
So, in this block, you need to actually update the label with some information, calling repaint
will simply paint the state as it is.
if (startTime != null) {
Duration runningTime = Duration.between(startTime, Instant.now());
Duration timeRemainig = timeOutDuration.minus(runningTime);
if (timeRemainig.isNegative() || timeRemainig.isZero()) {
// Time has run out...
startTime = null; // stop the timer
System.out.println("finish");
} else {
// Update the UI
//repaint();
// Format the duration and update the label...
}
}
As described in How could I add a refreshing timer to a JLabel using swing components, you can generate a String
of the Duration
by using something like...
long hours = timeRemainig.toHours();
long mins = timeRemainig.minusHours(hours).toMinutes();
// Or if you're lucky enough to be using Java 9+
//String formatted = String.format("%dhrs %02dmins", duration.toHours(), duration.toMinutesPart());
String formatted = String.format("%dhrs %02dmins", hours, mins);
Then you set the text of the label accordingly
// Sorry can't identify your count down label...
countDownLabel.setText(formatted);
Also, you really, really, really, only need a single Timer
Upvotes: 2