Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java TimerTick event for game loop

I tried making a game loop in Java using the Timer from java.util.Timer. I am unable to get my game loop to execute during the timer tick. Here is an example of this issue. I am trying to move the button during the game loop, but it is not moving on the timer tick event.

import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JButton;

public class Window extends JFrame {

    private static final long serialVersionUID = -2545695383117923190L;
    private static Timer timer;
    private static JButton button;

    public Window(int x, int y, int width, int height, String title) {

        this.setSize(width, height);
        this.setLocation(x, y);
        this.setTitle(title);
        this.setLayout(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        timer = new Timer();
        timer.schedule(new TimerTick(), 35);

        button = new JButton("Button");
        button.setVisible(true);
        button.setLocation(50, 50);
        button.setSize(120, 35);
        this.add(button);
    }

    public void gameLoop() {

        // Button does not move on timer tick.
        button.setLocation( button.getLocation().x + 1, button.getLocation().y );

    }

    public class TimerTick extends TimerTask {

        @Override
        public void run() {
            gameLoop();
        }
    }
}
like image 281
Johnathan Avatar asked Dec 12 '22 13:12

Johnathan


2 Answers

Since this is a Swing application, don't use a java.util.Timer but rather a javax.swing.Timer also known as a Swing Timer.

e.g.,

private static final long serialVersionUID = 0L;
private static final int TIMER_DELAY = 35;

in the constructor

  // the timer variable must be a javax.swing.Timer
  // TIMER_DELAY is a constant int and = 35;
  new javax.swing.Timer(TIMER_DELAY, new ActionListener() {
     public void actionPerformed(ActionEvent e) {
        gameLoop();
     }
  }).start();

and

   public void gameLoop() {
      button.setLocation(button.getLocation().x + 1, button.getLocation().y);
      getContentPane().repaint(); // don't forget to repaint the container
   }
like image 144
Hovercraft Full Of Eels Avatar answered Dec 30 '22 07:12

Hovercraft Full Of Eels


First of all, Timer.schedule schedules the task for one execution, not for repeated executions. So this program can only make the button move once.

And you have a second problem : all the interactions with swing components should be done in the event dispatch thread, and not in a background thread. Read http://download.oracle.com/javase/6/docs/api/javax/swing/package-summary.html#threading for more details. Use a javax.swing.Timer to perform swing actions at repeated intervals.

like image 26
JB Nizet Avatar answered Dec 30 '22 07:12

JB Nizet