0

I have a Game Loop:

public void startGameThread() {
    gameLoop();
    gameThread = new Thread(this);
    gameThread.start();
}

public void gameLoop() {
    frame++;
    if (System.currentTimeMillis() - lastCheck >= 1000) {
        lastCheck = System.currentTimeMillis();
        System.out.println("FPS " + frame);
        frame = 0;
    }
}

@Override
public void run() {
    double timePerFrame = 1000000000.0/FPS;
    long lastFrame = System.nanoTime();
    long now = System.nanoTime();
    while (true) {
        now = System.nanoTime();
        if (System.nanoTime() - lastFrame >= timePerFrame) {
            repaint();
            update();
            gameLoop();
            lastFrame = now;
        }
    }
}

and Main Class with GUI:

package MainPackage;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MainClass implements ActionListener {
    public static boolean Clicked = false;

    public static void main(String[] args) {
        PanelClass pClass = new PanelClass();
        JButton start = new JButton("START");
        start.setSize(120, 50);
        start.setFocusable(false);
        start.setLocation(630, 200);
        start.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(e.getSource() == start) {
                    pClass.startGameThread();
                    Clicked = true;
                    start.setVisible(false);
                }
            }
        });
        start.setVisible(true);
        JFrame frame = new JFrame("Tanks");
        frame.setSize(1600, 913);
        frame.setLayout(null);
        frame.pack();
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.add(start);
        frame.add(pClass);
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }
}

After launching my application, GUI is "blinking". I think that's because of the Game loop. But how to fix it? Any help is really appreciated!

I was expecting to get the usual behavior of the GUI. Ask me to add more details; code, if needed.

Typing this, because stackoverflow need more "details". That's probably stupid, but I don't know what details to add.

Abra
  • 19,142
  • 7
  • 29
  • 41
Reyni
  • 11
  • 3

1 Answers1

0

There is nothing wrong with your game loop. The way you are creating the JFrame is wrong.

Mistake 1: Do not use JFrame.setSize() use JFrame.setPreferredSize() instead.

Mistake 2: Always call JFrame.pack() after adding all the components and before making the frame visible.

Mistake 3: Do not use null layout for JFrame.

After fixing these mistakes your game was running without any problems.

PanelClass pClass = new PanelClass();
JButton start = new JButton("START");
start.setSize(120, 50);
start.setFocusable(false);
start.setLocation(630, 200);
start.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == start) {
            pClass.startGameThread();
            Clicked = true;
            start.setVisible(false);
        }
    }
});
start.setVisible(true);
JFrame frame = new JFrame("Tanks");
frame.setPreferredSize(new Dimension(1200, 913));
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.add(start);
frame.add(pClass);
frame.setVisible(true);
frame.pack();

Complete code:

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class Game implements ActionListener {
    public static boolean Clicked = false;

    public static void main(String[] args) {
        PanelClass pClass = new PanelClass();
        JButton start = new JButton("START");
        start.setSize(120, 50);
        start.setFocusable(false);
        start.setLocation(630, 200);
        start.addActionListener(e -> {
            if(e.getSource() == start) {
                pClass.startGameThread();
                Clicked = true;
                start.setVisible(false);
            }
        });
        start.setVisible(true);
        JFrame frame = new JFrame("Tanks");
        frame.setPreferredSize(new Dimension(1200, 913));
        frame.setMinimumSize(new Dimension(300, 200));
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.add(start);
        frame.add(pClass);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.pack();
    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }
    static class PanelClass extends JPanel implements Runnable{
        int posX = 0;
        Thread gameThread;
        int frame;
        long lastCheck;
        int FPS = 60;
        public void startGameThread() {
            gameLoop();
            gameThread = new Thread(this);
            gameThread.start();
        }

        public void gameLoop() {
            frame++;
            if (System.currentTimeMillis() - lastCheck >= 1000) {
                lastCheck = System.currentTimeMillis();
                System.out.println("FPS " + frame);
                frame = 0;
            }
        }

        @Override
        public void run() {
            double timePerFrame = 1000000000.0/FPS;
            long lastFrame = System.nanoTime();
            long now = System.nanoTime();
            while (true) {
                now = System.nanoTime();
                if (System.nanoTime() - lastFrame >= timePerFrame) {
                    repaint();
                    gameLoop();
                    lastFrame = now;
                }
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            posX++;
            g.fillRect(posX,getHeight()/2,10,10);
            Toolkit.getDefaultToolkit().sync();
        }
    }

}

The game loop works and there is no blinking/flickering on ubuntu or windows 7 compiled with JDK 17.

Bonus tip: If you are overriding the paint method of your PanelClass then use Toolkit.getDefaultToolkit().sync() in the end. This method ensures that the display is up-to-date.

  • Sorry, but it doesn't work. – Reyni Dec 04 '22 at 17:39
  • @Reyni I have added the whole source code. Try compiling it with a newer JDK. It could be a JDK problem because I am seeing no flickering/blinking of any sort, neither on ubuntu nor on the windows 7. – Divyansh Singh Dec 04 '22 at 19:29
  • I forgot to change an important detail. GUI is "blinking" when the "pClass.startGameThread" is called, and GUI is shown. But you probably knew this, and im going to try and update JDK. Thanks – Reyni Dec 05 '22 at 04:03