Java JPanel中的闪烁图像

Java JPanel中的闪烁图像,java,swing,flicker,graphics2d,Java,Swing,Flicker,Graphics2d,我已经创建了一个游戏,它向JPanel绘制图像。这与JTimer一起运行,JTimer每14毫秒执行一次以移动背景、移动障碍物和移动玩家(直升机)。我偶尔会看到背景和障碍物的闪烁,而且运行起来并不特别平稳。 有什么办法可以让我绕过这件事吗?我需要在不同的类中使用线程和动画吗? 我还使用了双缓冲,但后来我发现JPanel是双缓冲的,所以我删除了它 下面是Panel类中的代码 class ImagePanel extends JPanel implements KeyListener, MouseL

我已经创建了一个游戏,它向JPanel绘制图像。这与JTimer一起运行,JTimer每14毫秒执行一次以移动背景、移动障碍物和移动玩家(直升机)。我偶尔会看到背景和障碍物的闪烁,而且运行起来并不特别平稳。 有什么办法可以让我绕过这件事吗?我需要在不同的类中使用线程和动画吗? 我还使用了双缓冲,但后来我发现JPanel是双缓冲的,所以我删除了它

下面是Panel类中的代码

class ImagePanel extends JPanel implements KeyListener, MouseListener,
        MouseMotionListener {

    /**
     * 
     */
    private static final long serialVersionUID = -6096603231469523786L;
    Plane o1 = new Plane();
    Tank o2 = new Tank();

    ArrayList<Plane> planeArray;
    ArrayList<Tank> tankArray;
    ArrayList<Missile> missileArray;

    int bgx;
    int bgxTwo;
    int time;
    int y;
    int score;
    int obsNum;
    int obsNum2;
    int planeSpeed;
    int missileSpeed;
    int count;

    boolean holding;
    boolean gameOver;
    boolean startscreen;
    boolean shooting;
    boolean obsOne = false;
    boolean obsTwo = false;

    Color colorone = Color.WHITE;
    Color colortwo = Color.WHITE;
    Color restartColor = Color.white;
    Color menuColor = Color.white;
    Color bulletColor = Color.white;

    Font f1;
    Font f2;
    Font f3;

    String version = "Get To The Chopper Beta 1.2";

    int level = 1;

    java.util.Timer movementtimer;
    TimerTask task;

    java.util.Timer obstacletimer;
    TimerTask taskTwo;

    private Image image;
    private Image imageTwo;
    private Image chopper;
    private Image chopper2;
    private Image tank;
    private Image plane;
    private Image missile;
    private Image explosion;

    BufferedImage bufferedImage;
    Graphics buffer;

    java.net.URL bgurl;
    java.net.URL curl;
    java.net.URL c2url;
    java.net.URL turl;
    java.net.URL purl;
    java.net.URL murl;
    java.net.URL eurl;

    // ///////// CONSTRUCTOR SETS NON-CHANGABLE VARIABLES ////////////////

    public ImagePanel() {

        setFocusable(true);
        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);

        f1 = new Font("Helvetica", Font.BOLD, 10);
        f2 = new Font("Helvetica", Font.PLAIN, 30);
        f3 = new Font("Helvetica", Font.PLAIN, 25);

        startscreen = true;

        getImages();

        planeArray = new ArrayList<Plane>();
        tankArray = new ArrayList<Tank>();
        missileArray = new ArrayList<Missile>();

        repaint();
    }

    public void getImages() {

        bgurl = getClass().getResource("images/background.png");
        switch (level) {
        case (1):
            bgurl = getClass().getResource("images/grassbackground.png");
            bulletColor = Color.black;
            break;
        case (2):
            bgurl = getClass().getResource("images/snowbackground.png");
            bulletColor = Color.red;
            break;
        }
        curl = getClass().getResource("images/heli.png");
        c2url = getClass().getResource("images/heli2.png");
        turl = getClass().getResource("images/tank.png");
        purl = getClass().getResource("images/plane.png");
        murl = getClass().getResource("images/missile.png");
        eurl = getClass().getResource("images/explosion.png");

        try {

            image = Toolkit.getDefaultToolkit().getImage(bgurl);
            imageTwo = Toolkit.getDefaultToolkit().getImage(bgurl);
            chopper = Toolkit.getDefaultToolkit().getImage(curl);
            chopper2 = Toolkit.getDefaultToolkit().getImage(c2url);
            tank = Toolkit.getDefaultToolkit().getImage(turl);
            plane = Toolkit.getDefaultToolkit().getImage(purl);
            missile = Toolkit.getDefaultToolkit().getImage(murl);
            explosion = Toolkit.getDefaultToolkit().getImage(eurl);

        } catch (Exception ex) {
            System.out.println("File Not Found");
        }

    }

    // //////// SETS VARIABLES WHEN GAME IS STARTED OR RESTARTED
    // //////////////////

    public void startGame() {
        bgx = 0;
        bgxTwo = 800;
        y = 50;
        score = 0;
        holding = false;
        gameOver = false;
        time = (int) (Math.random() * 500 + 500);
        obsNum2 = 0;
        shooting = false;

        count = 1;

        planeSpeed = -6;
        missileSpeed = -7;

        planeArray.clear();
        tankArray.clear();
        missileArray.clear();

        colorone = Color.WHITE;
        colortwo = Color.WHITE;
        restartColor = Color.white;
        menuColor = Color.white;

        movementtimer = new java.util.Timer();
        task = new TimerTask() {
            public void run() {
                moveImage();repaint();
            }
        };
        movementtimer.schedule(task, 0, 13);

        obstacletimer = new java.util.Timer();
        taskTwo = new TimerTask() {
            public void run() {
                generateObstacle();
            }
        };
        obstacletimer.schedule(taskTwo, 2000, time);

    }

    // ////////// COLLISION DETECTION //////////////////

    public void moveImage() {

        moveBackground();

        addToScore();

        if (holding) {
            y += -3;
        } else {
            y += 3;
        }

        for (int i = 0; i < planeArray.size(); i++) {
            Plane plane = planeArray.get(i);
            if (y + 30 >= plane.yPos && y + 30 <= plane.yPos + 30
                    && plane.xPos >= 200 && plane.xPos <= 250
                    || y >= plane.yPos && y <= plane.yPos + 30
                    && plane.xPos >= 200 && plane.xPos + 50 <= 250) {
                gameOver = true;
                System.out.println("Crash with plane!");
            }
        }

        for (int i = 0; i < tankArray.size(); i++) {
            Tank tank = tankArray.get(i);
            if (y + 30 >= tank.yPos && y + 30 <= tank.yPos + 30
                    && tank.xPos >= 200 && tank.xPos <= 250
                    || y >= tank.yPos && y <= tank.yPos + 30
                    && tank.xPos >= 200 && tank.xPos + 50 <= 250) {
                gameOver = true;
                System.out.println("Crash with a tank");
            }
            if (shooting) {
                if (y + 30 >= tank.bulletYPos && y <= tank.bulletYPos
                        && tank.bulletXPos >= 200 && tank.bulletXPos <= 250) {
                    gameOver = true;
                    System.out.println("Shot down");

                }
            }
        }

        for (int i = 0; i < missileArray.size(); i++) {
            Missile missile = missileArray.get(i);
            if (y + 30 >= missile.yPos && y + 30 <= missile.yPos + 30
                    && missile.xPos >= 200 && missile.xPos <= 250
                    || y >= missile.yPos && y <= missile.yPos + 30
                    && missile.xPos >= 200 && missile.xPos + 50 <= 250) {
                gameOver = true;
                System.out.println("Crash with a missile");
            }
        }

        if (y >= 300) {
            gameOver = true;
        } else if (y <= -15) {
            gameOver = true;
        }


    }

    // //////// MOVES BACKGROUND //////////////

    public void moveBackground() {

        bgx += -5;

        if (bgx == -800) {
            bgx = 800;
        }

        bgxTwo += -5;

        if (bgxTwo == -800) {
            bgxTwo = 800;
        }

        for (int i = 0; i < planeArray.size(); i++) {

            Plane obs = planeArray.get(i);
            obs.xPos = obs.xPos - 6;
        }

        for (int i = 0; i < tankArray.size(); i++) {

            Tank obs = tankArray.get(i);

            obs.xPos = obs.xPos - 5;
            if (shooting) {
                obs.bulletYPos = obs.bulletYPos - 2;
                obs.bulletXPos = obs.bulletXPos - obs.angle;
            }
        }

        for (int i = 0; i < missileArray.size(); i++) {

            Missile obs = missileArray.get(i);
            obs.xPos = obs.xPos - 7;
        }

    }

    public void addToScore() {

        score += 5;

        increaseDiff();

    }

    public void increaseDiff() {

        if (score == 10000) {
            shooting = true;
            for (int i = 0; i < tankArray.size(); i++) {
                Tank tank = tankArray.get(i);
                tank.bulletXPos = tank.xPos;
            }
        }
        if (score > 5000 && score < 9999) {
            time = (int) (Math.random() * 400 + 250);
            planeSpeed = -7;
            missileSpeed = -8;

        } else if (score > 10000 && score < 14999) {
            time = (int) (Math.random() * 400 + 150);
            planeSpeed = -8;
            missileSpeed = -10;

        } else if (score > 15000 && score < 19999) {
            time = (int) (Math.random() * 400 + 150);
            planeSpeed = -9;
            missileSpeed = -11;
            obsNum2 = (int) (Math.random() * 2 + 1);
        } else if (score > 20000 && score < 29999) {
            time = (int) (Math.random() * 300 + 100);
            planeSpeed = -10;
            missileSpeed = -13;
            obsNum2 = (int) (Math.random() * 2 + 1);
        } else if (score > 30000) {
            time = (int) (Math.random() * 300 + 100);
            planeSpeed = -12;
            missileSpeed = -15;
            obsNum2 = (int) (Math.random() * 2 + 1);
        }
    }

    public void generateObstacle() {

        obsNum = (int) (Math.random() * 5 + 1);

        if (obsNum == 1 || obsNum == 4 || obsNum2 == 1) {
            planeArray.add(new Plane());
        }

        if (obsNum == 2) {
            tankArray.add(new Tank());
        }

        if (obsNum == 3 || obsNum == 5 || obsNum2 == 2) {
            missileArray.add(new Missile());
        }

    }


    public void update(Graphics g) {
        paint(g);
    }

    // /////////////// MAIN PAINT METHOD //////////////////////

    @Override
    public void paint(Graphics g) {

        g.clearRect(0,0,800,400);

        if (!startscreen) {

            g.drawImage(image, bgx, 0, null);
            g.drawImage(imageTwo, bgxTwo, 0, null);

            for (int i = 0; i < planeArray.size(); i++) {
                Plane obs = planeArray.get(i);

                if (obs.xPos <= -50) {
                    planeArray.remove(i);
                } else {

                    g.drawImage(plane, obs.xPos, obs.yPos, null);
                }
            }

            for (int i = 0; i < tankArray.size(); i++) {
                Tank obs = tankArray.get(i);

                if (obs.xPos <= -50) {
                    tankArray.remove(i);
                } else {

                    g.drawImage(tank, obs.xPos, obs.yPos, null);
                    if (shooting) {
                        g.setColor(bulletColor);
                        g.fillOval(obs.bulletXPos, obs.bulletYPos, 5,
                                5);
                    }
                }
            }

            for (int i = 0; i < missileArray.size(); i++) {
                Missile obs = missileArray.get(i);

                if (obs.xPos <= -50) {
                    missileArray.remove(i);
                } else {

                    g.drawImage(missile, obs.xPos, obs.yPos, null);
                }
            }

            if (gameOver) {
                movementtimer.cancel();
                obstacletimer.cancel();
                g.setColor(Color.WHITE);
                g.setFont(f2);
                g.drawString("GAME OVER", 250, 150);
                g.setFont(f3);
                g.drawString("Your score: " + score, 250, 200);
                g.setColor(restartColor);
                g.drawString("Click to restart!", 250, 250);
                g.setColor(menuColor);
                g.drawString("Back to menu", 250, 300);
                g.drawImage(explosion, 200, y, this);
            }

        } else if (startscreen) {

            g.drawImage(image, 0, 0, this);
            g.drawImage(imageTwo, 0, 0, this);
            g.drawImage(chopper, 200, 50, this);
            g.setColor(Color.WHITE);
            g.setFont(f2);
            g.drawString("Choose a level:", 200, 150);
            g.setFont(f3);
            g.setColor(colorone);
            g.drawString("Grass Level!", 250, 200);
            g.setColor(colortwo);
            g.drawString("Snow Level!", 250, 250);

        }

        if (count <= 9 && !gameOver && !startscreen) {
            g.drawImage(chopper, 200, y, this);
            count++;
        } else if (count >= 10 && count < 20 && !gameOver && !startscreen) {
            g.drawImage(chopper2, 200, y, this);
            count++;
        } else if (count == 20 && !gameOver && !startscreen) {
            count = 1;
            g.drawImage(chopper, 200, y, this);
        }

        g.setFont(f1);
        g.setColor(Color.WHITE);
        g.drawString(version, 10, 10);
        g.drawString("Score: " + score + "", 700, 10);
    }



    // ///////////////////OVERRIDE KEYPRESSED EVENTS//////////////////////

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub

        if (e.getKeyCode() == 32) {
            holding = true;
            repaint();
        }

    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

        if (e.getKeyCode() == 32) {
            holding = false;
            repaint();
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    public void mousePressed(MouseEvent e) {

        if (e.getX() >= 250 && e.getX() <= 400 && e.getY() >= 180
                && e.getY() <= 200 && startscreen) {
            startscreen = false;
            level = 1;
            getImages();
            startGame();
        }

        if (e.getX() >= 250 && e.getX() <= 400 && e.getY() >= 230
                && e.getY() <= 250 && startscreen) {
            startscreen = false;
            level = 2;
            getImages();
            startGame();
        }

        if (e.getX() >= 250 && e.getX() <= 420 && e.getY() >= 230
                && e.getY() <= 250 && gameOver) {
            startGame();
        }

        if (e.getX() >= 250 && e.getX() <= 420 && e.getY() >= 280
                && e.getY() <= 320 && gameOver) {
            gameOver = false;
            startscreen = true;
            repaint();
        }

    }

    @Override
    public void mouseClicked(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    public void mouseMoved(MouseEvent e) {
        if (e.getX() >= 250 && e.getX() <= 400 && e.getY() >= 180
                && e.getY() <= 200 && startscreen) {
            colorone = Color.RED;
            repaint();
        } else if (e.getX() >= 250 && e.getX() <= 400 && e.getY() >= 230
                && e.getY() <= 250 && startscreen) {
            colortwo = Color.RED;
            repaint();
        } else if (startscreen) {
            colorone = Color.white;
            colortwo = Color.white;
            repaint();
        }

        if (e.getX() >= 250 && e.getX() <= 420 && e.getY() >= 230
                && e.getY() <= 250 && gameOver) {
            restartColor = Color.red;
            repaint();
        } else if (e.getX() >= 250 && e.getX() <= 420 && e.getY() >= 280
                && e.getY() <= 320 && gameOver) {
            menuColor = Color.red;
            repaint();
        } else if (gameOver) {
            restartColor = Color.white;
            menuColor = Color.white;
            repaint();
        }
    }

    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseDragged(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }
}
class ImagePanel扩展JPanel实现KeyListener、MouseListener、,
MouseMotionListener{
/**
* 
*/
私有静态最终长SerialVersionId=-6096603231469523786L;
平面o1=新平面();
储罐o2=新储罐();
阵列列表平面阵列;
ArrayList数组;
ArrayList missileArray;
int-bgx;
int-bgxTwo;
整数时间;
int-y;
智力得分;
int obsNum;
int obsNum2;
内平面速度;
导弹速度;
整数计数;
布尔保持;
布尔博弈;
布尔startscreen;
布尔射击;
布尔obsOne=false;
布尔值2=假;
Color colorone=Color.WHITE;
Color colortwo=Color.WHITE;
Color restarcolor=Color.white;
颜色菜单颜色=Color.white;
颜色bulletColor=Color.white;
字体f1;
字体f2;
字体f3;
String version=“进入斩波器Beta 1.2”;
智力水平=1;
java.util.Timer movementtimer;
时间任务;
计时器obstacletimer;
TimerTask2;
私有图像;
二是私人形象;
专用图像斩波器;
私有图像切碎器2;
私人图像库;
专用图像平面;
私人图像导弹;
私人形象爆炸;
BuffereImage BuffereImage;
图形缓冲区;
java.net.URL bgurl;
java.net.URL;
java.net.URL c2url;
java.net.URL turl;
java.net.URL purl;
java.net.URL murl;
java.net.URL eurl;
////构造函数设置不可更改的变量////////////////
公众影像小组(){
设置聚焦(真);
addKeyListener(此);
addMouseListener(这个);
addMouseMotionListener(此);
f1=新字体(“Helvetica”,Font.BOLD,10);
f2=新字体(“Helvetica”,Font.PLAIN,30);
f3=新字体(“Helvetica”,Font.PLAIN,25);
startscreen=true;
getImages();
planeArray=新的ArrayList();
tankArray=新的ArrayList();
missileArray=新的ArrayList();
重新油漆();
}
public-void-getImages(){
bgurl=getClass().getResource(“images/background.png”);
开关(电平){
案例(1):
bgurl=getClass().getResource(“images/grassbackground.png”);
bulletColor=Color.black;
打破
案例(2):
bgurl=getClass().getResource(“images/snowbackground.png”);
bulletColor=Color.red;
打破
}
curl=getClass().getResource(“images/heli.png”);
c2url=getClass().getResource(“images/heli2.png”);
turl=getClass().getResource(“images/tank.png”);
purl=getClass().getResource(“images/plane.png”);
murl=getClass();
eurl=getClass().getResource(“images/explosion.png”);
试一试{
image=Toolkit.getDefaultToolkit().getImage(bgurl);
imageTwo=Toolkit.getDefaultToolkit().getImage(bgurl);
chopper=Toolkit.getDefaultToolkit().getImage(curl);
chopper2=Toolkit.getDefaultToolkit().getImage(c2url);
tank=Toolkit.getDefaultToolkit().getImage(turl);
平面=Toolkit.getDefaultToolkit().getImage(purl);
导弹=Toolkit.getDefaultToolkit().getImage(murl);
explosion=Toolkit.getDefaultToolkit().getImage(eurl);
}捕获(例外情况除外){
System.out.println(“未找到文件”);
}
}
////设置游戏启动或重新启动时的变量
// //////////////////
公共无效StartName(){
bgx=0;
bgxTwo=800;
y=50;
得分=0;
持有=虚假;
gameOver=false;
时间=(int)(Math.random()*500+500);
obsNum2=0;
射击=假;
计数=1;
飞机速度=-6;
导弹速度=-7;
planeArray.clear();
tankArray.clear();
missileArray.clear();
colorone=Color.WHITE;
colortwo=Color.WHITE;
restartColor=Color.white;
menuColor=颜色为白色;
movementtimer=newjava.util.Timer();
任务=新时间任务(){
公开募捐{
移动图像();重新绘制();
}
};
movementtimer.schedule(任务,0,13);
obstacletimer=newjava.util.Timer();
taskTwo=新的TimerTask(){
公开募捐{
生成障碍();
}
};
《障碍物制造者时间表》(任务二,2000年,时间);
}
////碰撞检测//////////////////
公共图像(){
moveBackground();
addToScore();
如果(持有){
y+=-3;
}否则{
y+=3;
}
对于(int i=0;i=plane.yPos&&y+30=200&&plane.xPos&&y=200&&plane.xPos&&y+50=tank.yPos&&y+30=200&&tank.xPos=tank.yPos&&y=200&&tank.bulletYPos&&y=200&&tank.bulletXPos=飞弹.yPos&&y+30=200&&em弹.xPos=200&&y=200&&em弹.xPos+50=300){
gameOver=true;
}否则如果(y 5000和分数<9999){
时间=(int)(Math.random()*400+250);
飞机速度=-7;
导弹
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

@SuppressWarnings("serial")
public class PaintVsPaintComponent extends JPanel {
   public static final String DUKE_WAVE = "http://duke.kenai.com/iconSized/duke4.gif";
   private static final int PREF_WIDTH = 300;
   private static final int PREF_HEIGHT = 250;
   private static final int TIMER_DELAY = 20;
   private static final int DELTA_X = 1;
   private static final int DELTA_Y = DELTA_X;
   private boolean awtDrawing;
   private BufferedImage image;
   private int x = 0;
   private int y = 0;

   public PaintVsPaintComponent(boolean awtDrawing, BufferedImage image) {
      this.awtDrawing = awtDrawing;
      this.image = image;

      new Timer(TIMER_DELAY, new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            timerActionPerformed(ae);
         }
      }).start();
   }

   private void timerActionPerformed(ActionEvent ae) {
      x += DELTA_X;
      y += DELTA_Y;

      if (x >= getWidth()) {
         x = 0;
      }
      if (y >= getHeight()) {
         y = 0;
      }

      repaint();
   }

   @Override
   public void paint(Graphics g) {
      super.paint(g);
      if (awtDrawing) {
         drawImage(g);
      }
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (!awtDrawing) {
         drawImage(g);
      }
   }

   private void drawImage(Graphics g) {
      g.drawImage(image, x, y, null);
   }

   @Override
   public void update(Graphics g) {
      if (awtDrawing) {
         paint(g);
      } else {
         super.update(g);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_WIDTH, PREF_HEIGHT);
   }

   private static void createAndShowGui() {
      BufferedImage dukeWaveImage = null;

      URL dukeWaveUrl;
      try {
         dukeWaveUrl = new URL(DUKE_WAVE);
         dukeWaveImage = ImageIO.read(dukeWaveUrl);


         PaintVsPaintComponent awtPanel = new PaintVsPaintComponent(true, dukeWaveImage);
         PaintVsPaintComponent swingPanel = new PaintVsPaintComponent(false, dukeWaveImage);
         awtPanel.setBorder(BorderFactory.createTitledBorder("AWT Panel"));
         swingPanel.setBorder(BorderFactory.createTitledBorder("Swing Panel"));

         JPanel gridPanel = new JPanel(new GridLayout(1, 0));
         gridPanel.add(awtPanel);
         gridPanel.add(swingPanel);

         JFrame frame = new JFrame("PaintVsPaintComponent");
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.getContentPane().add(gridPanel);
         frame.pack();
         frame.setLocationByPlatform(true);
         frame.setVisible(true);
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }

   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }

}