如何加倍缓冲矩形

时间:2014-04-22 00:48:38

标签: java swing jpanel keylistener thread-sleep

它总是适用于图像,但矩形和椭圆永远不会缓冲。我的游戏面板类中有一个基本的游戏循环,可以反复绘制玩家。它不会删除矩形,只留下痕迹。我想使用矩形而不是图像来进行学习。我尝试在游戏循环中使用重绘,但它像疯了一样闪烁,仍然无法正常工作。我在这个网站上查看了另一个关于此的教程,但他们使用的opengl女巫对我来说很陌生,我不想花时间去弄明白。

的JFrame:

import javax.swing.JFrame;

public class Game {

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setTitle("OMG I MADE A GAME");
        f.setResizable(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new Panel());
        f.pack();

        f.setVisible(true);
       }
   }

JPanel Class:

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import javax.swing.JPanel;
import com.game.entity.Player;

public class Panel extends JPanel implements Runnable, KeyListener{ 

private static final long serialVersionUID = -5122190028751177848L;
    // dimensions
    public static final int WIDTH = 320;
    public static final int HEIGHT = 240;
    public static final int SCALE = 2;      
    // game thread
    private Thread thread;
    private boolean running;        
    // image
    private BufferedImage image;
    private Graphics2D g;

    private Player p;

    public Panel() {
        super();
        setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        setFocusable(true);
        requestFocus();
    }
    // DRAWS PANEL TO FRAME
    public void addNotify() {
        super.addNotify();
        if(thread == null) {
            thread = new Thread(this);
            addKeyListener(this);
            thread.start();
        }
    }

    private void init() {           
        image = new BufferedImage(
                    WIDTH, HEIGHT,
                    BufferedImage.TYPE_INT_RGB                  );
        g = (Graphics2D) image.getGraphics();
        p = new Player(100, 100);           
        running = true;
    }

    public void run() {         
        init();
        // game loop
        while(running) {                
            update();
            draw();
            drawToScreen();  
            System.out.println("ELAPSED :" + System.nanoTime()/ 1000000 + " Seconds");              
            try {
                Thread.sleep(10);
            }
            catch(Exception e) {
                e.printStackTrace();
            }           
        }           
    }

    private void update() {
        p.update();
    }
    private void draw(){
        // NAME (remember it loops) 
        String name = "2014 Jay H.";
        g.setFont(new Font("Name", 0, 12)); 
        g.setColor(Color.WHITE);
        g.drawString(name, 0, 10);
        g.setColor(Color.BLUE);
        g.fillRect( 0, 10, 65, 5);          
        //TITLE                       looks sexy :D
        g.setColor(Color.GREEN);
        g.setFont(new Font("Title", 0, WIDTH/ 10));
        g.drawString("JAY'S GAME", WIDTH/ 5, 100);
        //DRAW PLAYER
        p.draw(g);

        }
    // SCREEN IMAGE (dont have to use. Just use this^)
    private void drawToScreen() {  
        Graphics g2 = getGraphics();
        g2.drawImage(image, 0, 0,
                WIDTH * SCALE, HEIGHT * SCALE,null);
        g2.dispose(); 
    }

    public void keyTyped(KeyEvent key) {}

    // PUBLIC KEYRELEASES
    public void keyPressed(KeyEvent key) {
        int KeyCode = key.getKeyCode();             
        //EXIT SYSTEM
        if(KeyCode == KeyEvent.VK_Q) {System.exit(0);
            }           //UP
        if(KeyCode == KeyEvent.VK_W){p.setDY(-2);}      
    }       

    // PUBLIC KEYRELEASES
    public void keyReleased(KeyEvent key) {
        int KeyCode = key.getKeyCode();             
        //UP
        if(KeyCode == KeyEvent.VK_W) {p.setDY(0);}
    }      
}

玩家等级:

   import java.awt.Color;
   import java.awt.Graphics2D;
   import java.awt.Image;      
   import javax.swing.ImageIcon;

    //FOR NOW THE PLAYER IS A RECTANGLE
   public class Player {

    // PLAYER CORDINATES AND VELOCITY
    int x,y,dx,dy;      

    public Player(int x, int y) {           
        //NEEDED TO USE THE X AND Y
        this.x =x;
        this.y = y;
    } 

    public void update() {
        x += dx;
        y += dy;            
    }

    // DRAW TO PANEL CLASS
    public void draw(Graphics2D g) {
        //BODY
        g.setColor(Color.PINK);
        g.fillRect(x, y, 20, 20);
        //EYES
        g.setColor(Color.BLACK);
        g.fillRect(x+3, y+2, 5, 10);
        g.fillRect(x+ 12, y+2, 5, 10);
        //EYERIS
        g.setColor(Color.WHITE);
        g.fillRect(x+3, y+2, 2, 10);
        g.fillRect(x+15, y+2, 2, 10);
        //NOSE
        g.setColor(Color.MAGENTA);
        g.fillRect(x+5, y+13, 10, 5);
        //NOSTRILLS
        g.setColor(Color.red);
        g.fillRect(x+6, y+15, 2, 2);
        g.fillRect(x+12, y+15, 2, 2);           
    }

    //GET METHODS FOR CORDINATES AND VELOCITY  (Unused for now... i think)
    public int getX() {return x;}
    public int getY() {return y;}
    public int getDX() {return dx;}
    public int getDY() {return dy;}         
    //SET METHODS TO CHANGE
    public void setX(int x) {this.x = x;}
    public void setY(int y) {this.y = y;}
    public void setDX(int dx) {this.dx = dx;}
    public void setDY(int dy) {this.dy = dy;}
 }

1 个答案:

答案 0 :(得分:0)

你需要"重置"在绘制之前缓冲区的背景。

请记住,绘画是累积性的,也就是说,你以前绘过的东西都会留下来。每次绘制时都需要从头开始重建每个框架

出现闪烁有两个原因......

  1. 您正在使用基于AWT的组件,这些组件不是双重缓冲的
  2. 您正在覆盖paint这样的顶级容器的JFrame,它不是双重缓冲的。
  3. 您应该使用BufferStrategy或覆盖基于Swing的组件的paintComponent方法,例如默认为双缓冲的JPanel