3

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
            }
        }
    }
}
Paiku Han
  • 581
  • 2
  • 16
  • 38
  • 2
    "Swing programs should override `paintComponent()` instead of overriding `paint()`."—[*Painting in AWT and Swing: The Paint Methods*](http://www.oracle.com/technetwork/java/painting-140037.html#callbacks), for [example](http://stackoverflow.com/a/3256941/230513). – trashgod Nov 26 '12 at 20:00
  • +1 for an actual working example – MadProgrammer Nov 26 '12 at 20:12

2 Answers2

4

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

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Here is a quick answer (if you're too lazy or don't have time to read the documentations given in the answer from MadProgrammer and trashgod which by the way help me writing this one). But I highly advice you to read the documentation as soon as you have some spare time.

Here is the code from the question re-written so that there isn't flickering. I separated the code into two classes: the JFrame containing the game in the GameFrame class and the Racing game itself (part of it as in the question) in the Race class which extends JPanel.

GameFrame.java

import javax.swing.*;

public class GameFrame extends JFrame {

    public static void main(String args[]){
        new GameFrame();
    }

    public GameFrame(){
        super("Graphics with JFrame");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(800,600);
        Race game = new Race();
        this.getContentPane().add(game);
        this.setVisible(true);
        game.run();
    }

}

Race.java

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

public class Race extends JPanel implements Runnable {

    private Rectangle r1 = new Rectangle(0,0,800,100);
    private Rectangle r2 = new Rectangle(0,100,100,400);
    Image img = null;

    public Race(){
        try{
             URL url= this.getClass().getResource("someImage.png");
            img =Toolkit.getDefaultToolkit().getImage(url);
        }catch(Exception e){}
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(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);
}

    public void run() {
        while(true){
            try {
                Thread.sleep(75);
            } catch (InterruptedException ex) {}
            repaint();

            //game animations and logic
        }
    }
}

Thanks again to MadProgrammer and trashgod. I am sorry I answered to my question instead of commenting others' but I had to show explicitly the difference between Before and After. Again, if you don't understand why I did those modifications to avoid the flickering. Read MadProgrammer and trashgod comments and answers.

Paiku Han
  • 581
  • 2
  • 16
  • 38