Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java : How to Avoid flickering on shape-made only animation (no image file)?

Hi I am reading the book "Programming Video Games for the Evil Genius" by Ian Cinnamon. In one of the projects he explains how to create some animation for a racing game. I wrote a simple code below (removing "almost" everything unnecessary). But the result is the same: the flickering.

My question is how, by using that same code (with little modifications obviously) can I make it stop flickering? My point is not to find another way around (modifying the whole code) because I am already able to create an entire game using JLabel, ImageIcon classes & spritesheets image files. My point is to solve the flickering problem without removing those shapes [Rectangle (fillRect & if possible drawImage)].

By the way if this is not possible "Why would you do that!?" or "It's impossible" are also good answers. (let's try not to use them!)

Thank You!

import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.net.*;

public class Race extends JFrame {
    public static void main(String[] args){
        new Race();
    }
        private Rectangle r1 = new Rectangle(0,0,800,100);
        private Rectangle r2 = new Rectangle(0,100,100,400);
        Image img = null;

    public Race(){
        super("Some Title");
        setVisible(true);
        setSize(800,600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try{
             URL url= this.getClass().getResource("someImage.png");
            img =Toolkit.getDefaultToolkit().getImage(url);
        }catch(Exception e){}
        Race.GameLoop gameHeart = new Race.GameLoop();
        gameHeart.run();
    }

    public void paint(Graphics g){
        super.paint(g);
        g.setColor(Color.GREEN);
        g.fillRect(r1.x, r1.y, r1.width, r1.height);
        g.setColor(Color.RED);
        g.fillRect(r2.x, r2.y, r2.width, r2.height);
        g.drawImage(img, r2.x, r2.y, r2.width, r2.height, this);
        try {
            Thread.sleep(75);
        } catch (InterruptedException ex) {}
        repaint();
    }

    public class GameLoop extends Thread {
        public void run(){
            while(true){
                //game animations and logic
                //even if I put repaint() here it still flicker
            }
        }
    }
}
like image 254
Paiku Han Avatar asked Mar 06 '26 22:03

Paiku Han


1 Answers

Don't paint onto a top level container (like JFrame), they do not support double buffering.

Instead, use something like a JPanel

Convention prefers overriding paintComponent rather then paint. This is done mostly because paint is a actually a very complex method

NEVER do this in any paint method:

try {
    Thread.sleep(75);
} catch (InterruptedException ex) {}
repaint();

Firstly, any delays should be handled by the game thread, calling Thread#sleep within the paint method will put the Event Dispatching Thread to sleep, which will prevent it from posting events (about mouse and keyboard interactions) and will make your program look non-responsive, which will cause you issues later on.

Never call repaint (or any method that might call repaint) from inside a paint method. This is simply asking the repaint manager to schedule another paint cycle, which will chew up your CPU until you program becomes unresponsive. Again, this is function of your game thread.

Remember, Swing is NOT thread save. All interactions with the UI MUST be made from within the context of the Event Dispatching Thread. Have a read through Concurrency in Swing for some more information

You can take a look at How to make line animation smoother? and Java Bouncing Ball for an examples

You might like to have a read through Performing Custom Painting and Painting in AWT and Swing

like image 86
MadProgrammer Avatar answered Mar 08 '26 12:03

MadProgrammer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!