简体   繁体   中英

Java JFrame repaint() flickering

I'm learning java from the book called "Programming Video Games for the Evil Genius" by Ian Cinnamon and there's this racing game. I understand how it works but I have a problem: it's flickering everytime it refreshes (Thread.sleep) . How can I fix it? btw I saw a post from 4 years ago but since I'm a begginer I didn't understand how to and I thought I shouldn't revive it.

Here's the code, thank you in advance:

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;

public class RadicalRacing extends JFrame {

    final int WIDTH = 900, HEIGHT = 650;
    double p1Speed = .5, p2Speed = .5;
    final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3;
    int p1Direction = UP;
    int p2Direction = UP;
    Rectangle left = new Rectangle(0, 0, WIDTH / 9, HEIGHT);
    Rectangle right = new Rectangle((WIDTH / 9) * 8, 0, WIDTH, HEIGHT);
    Rectangle top = new Rectangle(0, 0, WIDTH, HEIGHT / 9);
    Rectangle bottom = new Rectangle(0, (HEIGHT / 9) * 8, WIDTH, HEIGHT / 9);
    Rectangle center = new Rectangle((int) ((WIDTH / 9) * 2.5), (int) ((HEIGHT / 9) * 2.5), (int) ((WIDTH / 9) * 5), (HEIGHT / 9) * 4);
    Rectangle obstacle = new Rectangle(WIDTH / 2, (int) ((HEIGHT / 9) * 7), WIDTH / 10, HEIGHT);
    Rectangle obstacle2 = new Rectangle(WIDTH / 3, (int) ((HEIGHT / 9) * 5), WIDTH / 10, HEIGHT / 4);
    Rectangle obstacle3 = new Rectangle(2 * (WIDTH / 3), (int) ((HEIGHT / 9) * 5), WIDTH / 10, HEIGHT / 4);
    Rectangle obstacle4 = new Rectangle(WIDTH / 3, HEIGHT / 9, WIDTH / 10, HEIGHT / 9);
    Rectangle obstacle5 = new Rectangle(WIDTH / 2, (int) ((HEIGHT / 9) * 1.5), WIDTH / 30, HEIGHT / 4);
    Rectangle finish = new Rectangle(WIDTH / 9, (HEIGHT / 2) - HEIGHT / 9, (int) ((WIDTH / 9) * 1.5),
            HEIGHT / 70);
    Rectangle lineO = new Rectangle(WIDTH / 9, HEIGHT / 2, (int) ((WIDTH / 9) * 1.5) / 2, HEIGHT / 140);
    Rectangle lineI = new Rectangle(((WIDTH / 9) + ((int) ((WIDTH / 9) * 1.5) / 2)),
            (HEIGHT / 2) + (HEIGHT / 10), (int) ((WIDTH / 9) * 1.5) / 2, HEIGHT / 140);
    Rectangle p1 = new Rectangle(WIDTH / 9, HEIGHT / 2, WIDTH / 30, WIDTH / 30);
    Rectangle p2 = new Rectangle(((WIDTH / 9) + ((int) ((WIDTH / 9) * 1.5) / 2)), (HEIGHT / 2)
            + (HEIGHT / 10), WIDTH / 30, WIDTH / 30);

    public RadicalRacing() {
        super("Radical Racing");
        setSize(WIDTH, HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        Move1 m1 = new Move1();
        Move2 m2 = new Move2();
        m1.start();
        m2.start();
    }

    public void paint(Graphics g) {
        super.paint(g);
        //draw the background
        g.setColor(Color.DARK_GRAY);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        //green border
        g.setColor(Color.GREEN);
        //now, using rectangles, draw it
        g.fillRect(left.x, left.y, left.width, left.height);
        g.fillRect(right.x, left.y, left.width, left.height);
        g.fillRect(top.x, top.y, top.width, top.height);
        g.fillRect(bottom.x, bottom.y, bottom.width, bottom.height);
        g.fillRect(center.x, center.y, center.width, center.height);
        g.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
        g.fillRect(obstacle2.x, obstacle2.y, obstacle2.width, obstacle2.height);
        g.fillRect(obstacle3.x, obstacle3.y, obstacle3.width, obstacle3.height);
        g.fillRect(obstacle4.x, obstacle4.y, obstacle4.width, obstacle4.height);
        g.fillRect(obstacle5.x, obstacle5.y, obstacle5.width, obstacle5.height);
        g.setColor(Color.WHITE);
        g.fillRect(lineO.x, lineO.y, lineO.width, lineO.height);
        g.fillRect(lineI.x, lineI.y, lineI.width, lineI.height);
        g.setColor(Color.YELLOW);
        g.fillRect(finish.x, finish.y, finish.width, finish.height);

        g.setColor(Color.BLUE);
        g.fillRect(p1.x, p1.y, p1.width, p1.height);
        g.setColor(Color.RED);
        g.fillRect(p2.x, p2.y, p2.width, p2.height);
    }

    private class Move1 extends Thread implements KeyListener {

        public void run() {
            addKeyListener(this);
            while (true) {
                try {
                    repaint();
                    if (p1.intersects(right) || p1.intersects(left)
                            || p1.intersects(top) || p1.intersects(bottom)
                            || p1.intersects(obstacle) || p1.intersects(obstacle2)
                            || p1.intersects(obstacle3) || p1.intersects(obstacle4)
                            || p1.intersects(obstacle5) || p1.intersects(p2)) {
                        p1Speed = -4;
                    }
                    if (p1.intersects(center)) {
                        p1Speed = -2.5;
                    }
                    if (p1Speed <= 5) {
                        p1Speed += .2;
                    }
                    if (p1Direction == UP) {
                        p1.y -= (int) (p1Speed);
                    }
                    if (p1Direction == DOWN) {
                        p1.y += (int) (p1Speed);
                    }
                    if (p1Direction == LEFT) {
                        p1.x -= (int) (p1Speed);
                    }
                    if (p1Direction == RIGHT) {
                        p1.x += (int) (p1Speed);
                    }

                    Thread.sleep(75);
                } catch (Exception e) {
                    break;
                }
            }
        }

        public void keyPressed(KeyEvent event) {
        }

        public void keyReleased(KeyEvent event) {
        }

        public void keyTyped(KeyEvent event) {
            if (event.getKeyChar() == 'a') {
                p1Direction = LEFT;
            }
            if (event.getKeyChar() == 'd') {
                p1Direction = RIGHT;
            }
            if (event.getKeyChar() == 's') {
                p1Direction = DOWN;
            }
            if (event.getKeyChar() == 'w') {
                p1Direction = UP;
            }
        }
    }

    private class Move2 extends Thread implements KeyListener {

        public void run() {
            addKeyListener(this);
            while (true) {
                try {
                    repaint();
                    if (p2.intersects(right) || p2.intersects(left)
                            || p2.intersects(top) || p2.intersects(bottom)
                            || p2.intersects(obstacle) || p2.intersects(obstacle2)
                            || p2.intersects(obstacle3) || p2.intersects(obstacle4)
                            || p2.intersects(obstacle5) || p2.intersects(p1)) {
                        p2Speed = -4;
                    }
                    if (p2.intersects(center)) {
                        p2Speed = -2.5;
                    }
                    if (p2Speed <= 5) {
                        p2Speed += .2;
                    }
                    if (p2Direction == UP) {
                        p2.y -= (int) (p2Speed);
                    }
                    if (p2Direction == DOWN) {
                        p2.y += (int) (p2Speed);
                    }
                    if (p2Direction == LEFT) {
                        p2.x -= (int) (p2Speed);
                    }
                    if (p2Direction == RIGHT) {
                        p2.x += (int) (p2Speed);
                    }

                    Thread.sleep(75);
                } catch (Exception e) {
                    break;
                }
            }
        }

        public void keyPressed(KeyEvent event) {
        }

        public void keyReleased(KeyEvent event) {
        }

        public void keyTyped(KeyEvent event) {
            if (event.getKeyChar() == 'h') {
                p2Direction = LEFT;
            }
            if (event.getKeyChar() == 'k') {
                p2Direction = RIGHT;
            }
            if (event.getKeyChar() == 'j') {
                p2Direction = DOWN;
            }
            if (event.getKeyChar() == 'u') {
                p2Direction = UP;
            }
        }
    }

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

What you need is double buffering. What is happening is the program draws one screen creating a flickering effect. Double buffering is the concept where you draw to an on-screen canvas and then when it is ready place it on top of the previous.

Most Swing components have this functionality built in by using setDoubleBuffered.

You can also use BufferStrategies or create your own class.

See this post for more: How to double buffer question

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM