简体   繁体   English

Java JFrame repaint()闪烁

[英]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. 我正在从Ian Cinnamon的《为邪恶的天才编程视频游戏》一书中学习Java,并且有一款赛车游戏。 I understand how it works but I have a problem: it's flickering everytime it refreshes (Thread.sleep) . 我知道它是如何工作的,但是我有一个问题:每次刷新时它都会闪烁(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. 顺便说一句,我看到了4年前的一篇文章,但是由于我是一名初学者,所以我不知道该怎么做,所以我认为我不应该重振它。

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. 大多数Swing组件都使用setDoubleBuffered内置了此功能。

You can also use BufferStrategies or create your own class. 您也可以使用BufferStrategies或创建自己的类。

See this post for more: How to double buffer question 有关更多信息,请参见此帖子: 如何将缓冲区加倍

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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