Author Topic: [Java] Timer inside event-based class  (Read 3870 times)

0 Members and 1 Guest are viewing this topic.

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
[Java] Timer inside event-based class
« on: September 04, 2011, 04:03:35 pm »
Code: [Select]
import java.awt.Graphics;
import java.awt.event.*;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Game extends JPanel implements KeyListener {
  /* Game Panel class containing all functions */

  /* Global static variables */
  JFrame mainFrame = new JFrame("Falling Blocks");
  int y = 520;
  int[] locations = {0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800};

  /* Global dynamic variables */
  int a; //Horizontal acceleration
  int x;
  boolean needs_repaint;
  boolean on_title_screen, on_game, on_game_over;

  public void init_variables() {
    /* Initates the dynamic variables in order to show Title Screen */
    a = 0;
    x = 0;
    on_title_screen = true;
    on_game = false;
    on_game_over = false;
    needs_repaint = true;
  }

  public void paintComponent(Graphics g) {
    /* Draws the elements on the screen */
    super.paintComponent(g);

    if (on_title_screen) {
      g.drawString("Press SPACE to start game", 10, 10);
      g.drawString("Made by David Gomes", 10, 30);
    }

    else if (on_game) {
      //Draw the player
      g.fillRect(x, y, 50, 50);
    }

    else { //Game Over
      g.drawString("Game Over", 10, 10);
    }

    //Repainting has finished
    needs_repaint = false;
  }

  public Game() {
    /* Defines the frame and the game panel */
    this.setFocusable(true);
    this.addKeyListener(this);

    /* Fixed Layout frame */
    mainFrame.setSize(852, 600);
    mainFrame.setResizable(false);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // Add game panel to main frame
    mainFrame.getContentPane().add(this);
  }

  public void run() {
    /* Displays the frame, start the game */
    mainFrame.setVisible(true);
    this.requestFocus();
    init_variables();
  }

  @Override
  public void keyPressed(KeyEvent key) {
    /* Handles key presses */

    if (on_title_screen) {
      /* Start the game when user presses SPACE */
      switch (key.getKeyCode()) {
      case KeyEvent.VK_SPACE:
        on_title_screen = false;
        on_game = true;
        needs_repaint = true;
        break;
      }
    }

    else if (on_game) {
      switch (key.getKeyCode()) {
      case KeyEvent.VK_LEFT:  // Move x coordinate left
        if (x > 0) {
          x -= 50;
          needs_repaint = true;
        }
        break;

      case KeyEvent.VK_RIGHT: // Move x coordinate right
        if (x < 800) {
          x += 50;
          needs_repaint = true;
        }
        break;
      }
    }

    else { // Game Over
      init_variables(); //Go to title screen
      needs_repaint = true;
    }

    // Repaint only if needed
    if (needs_repaint)
      this.repaint();
  }

  /* Game Class is not abstract, and these functions are not needed */
  @Override
  public void keyReleased(KeyEvent arg0) { }
  @Override
  public void keyTyped(KeyEvent arg0) { }
}

I have that code (with syntax highlighting here), and I need to add a timer inside the Game class, associated with a function that runs every N seconds. And I need it to run at the same time as other functions run in the class (keyPressed, paint), etc.

I found a lot of information online on how to make timers in Java (javax.swing.Timer class and other ways), but I don't think it allows me to have the other functions running inside the class too. And I also don't know how to implement it in this specific context.

I appreciate any help, thanks!

Offline ben_g

  • Hey cool I can set a custom title now :)
  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +125/-4
  • Asm noob
    • View Profile
    • Our programmer's team: GameCommandoSquad
Re: [Java] Timer inside event-based class
« Reply #1 on: September 04, 2011, 04:12:29 pm »
This should work:
Code: [Select]
new Thread(new Runnable() {
          long prevTime = System.currentTimeMillis();
            public void run() {
                if(System.currentTimeMillis() >= prevTime+1000*N){
                    prevTime = System.currentTimeMillis();
                    //call the function (or embed the code here)
                }
            }
        }).start();
the N should be replaced by the secounds between two calls

Sorry, I haven't tested it yet, but i hope this code helps.

this code should be called when this game start. It's also useful to set it as a deamon thread (with a thread variable, use th.setDeamon(true);) so it will stop when your game stops. Also: do NOT put this in your game loop. It will keep creating new threads eating up your CPU untill your computer crashes.
« Last Edit: September 04, 2011, 04:30:50 pm by ben_g »
My projects
 - The Lost Survivors (Unreal Engine) ACTIVE [GameCommandoSquad main project]
 - Oxo, with single-calc multiplayer and AI (axe) RELEASED (screenshot) (topic)
 - An android version of oxo (java)  ACTIVE
 - A 3D collision detection library (axe) RELEASED! (topic)(screenshot)(more recent screenshot)(screenshot of it being used in a tilemapper)
Spoiler For inactive:
- A first person shooter with a polygon-based 3d engine. (z80, will probably be recoded in axe using GLib) ON HOLD (screenshot)
 - A java MORPG. (pc) DEEP COMA(read more)(screenshot)
 - a minecraft game in axe DEAD (source code available)
 - a 3D racing game (axe) ON HOLD (outdated screenshot of asm version)

This signature was last updated on 20/04/2015 and may be outdated

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: [Java] Timer inside event-based class
« Reply #2 on: September 04, 2011, 04:56:27 pm »
Code: [Select]
import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

import java.awt.event.*;

public class Game extends JPanel {
    JFrame mainFrame = new JFrame("Game");

    String[] full_map = {"0101010101",
     "1010101010",
     "0101010101",
     "1010101010",
     "0101010101",
     "1010101010",
     "0101010101",
         "1010101010",
                         "0101010101",
              "1010101010"};

  new Thread(new Runnable() {
    long prevTime = System.currentTimeMillis();
public void run() {
      if (System.currentTimeMillis() >= prevTime+1000*2) {
    prevTime = System.currentTimeMillis();
    System.out.println("hello");
  }
    }
  }).start();

  public void paintComponent(Graphics g) {
    /* Draws the elements on the screen */
    super.paintComponent(g);

    int y, x;
    for (y = 0; y < this.full_map.length; y++) {
      for (x = 0; x < this.full_map[y].length(); x++) {
        if (this.full_map[y].charAt(x) == '1') {
          g.setColor(Color.BLACK);
          g.fillRect(50*x, 50*y, 50, 50);
        }
      }
    }
  }

  public Game() {
    /* Defines the frame and the game panel */
    this.setFocusable(true);
    mainFrame.setSize(this.full_map[0].length()*50, this.full_map.length*50);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.getContentPane().add(this);
  }

  public void start() {
    /* Displays the frame, start the game */
    mainFrame.setVisible(true);
    this.requestFocus();
  }
}

This is my whole code,

Quote
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
   Syntax error on token ";", { expected after this token
   Syntax error on token "}", delete this token

   at Game.<init>(Game.java:22)

The Java compiler returned that. I'm not sure of what's wrong, seems like not matching braces, but it all looks correct.

Offline Quigibo

  • The Executioner
  • CoT Emeritus
  • LV11 Super Veteran (Next: 3000)
  • *
  • Posts: 2031
  • Rating: +1075/-24
  • I wish real life had a "Save" and "Load" button...
    • View Profile
Re: [Java] Timer inside event-based class
« Reply #3 on: September 04, 2011, 06:03:37 pm »
You're creating a new object (a thread) inside your class and calling one of its methods.  I'm pretty sure you can't do that, you can only have code there to initialize variables.  You can instead do "Thread myThread = new Thread(..);" and then in your constructor do "myThread.start();"  Or just move it all to the constructor since you don't need the object after that.
___Axe_Parser___
Today the calculator, tomorrow the world!

Offline nemo

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1203
  • Rating: +95/-11
    • View Profile
Re: [Java] Timer inside event-based class
« Reply #4 on: September 04, 2011, 10:31:25 pm »
my approach would be to have an instance variable of javax.swing.Timer called timer in the Game class. then in the game constructor:

Code: [Select]
public Game(){
    //other stuff
    timer = new Timer([MILLISECONDS], new ActionListener(){
        public void actionPerformed(ActionEvent e){
            //run whatever functions you want.
        }});
    timer.start();
}


Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: [Java] Timer inside event-based class
« Reply #5 on: September 05, 2011, 05:28:14 am »
You're creating a new object (a thread) inside your class and calling one of its methods.  I'm pretty sure you can't do that, you can only have code there to initialize variables.  You can instead do "Thread myThread = new Thread(..);" and then in your constructor do "myThread.start();"  Or just move it all to the constructor since you don't need the object after that.

Thanks, it makes sense, but I can do the same thing, but using a Timer as nemo said.

I figured it out, and now I have a main game loop, thanks a lot!