使图像重绘更快

时间:2015-04-17 16:39:02

标签: java graphics keyboard repaint thread-sleep

我有一个工作代码,您可以使用箭头键盘控制金鱼的移动。当你按下向上键时,金鱼会游起来。按下向下键时,金鱼会向下游泳。按左键时,金鱼向左游动。当你按下右键时,金鱼游向右边。我这样做是为了让金鱼的像素每次朝新的方向移动时增加或减少1个像素,但是当你这样做的时候,金鱼游得非常慢。我知道如果你将像素增加1以上,金鱼似乎游得更快,但那样它就不会画出每个像素,金鱼游泳看起来也不会那么光滑。所以我的问题是,有没有办法重新绘制金鱼以加快速度而不增加它所绘制的像素?这是我的代码:

public class Fishy extends Panel implements KeyListener, MouseMotionListener {
static int x1;// first x location of the shape.
static int x2;// second x location of the shape
static int y1;// first y location of the shape
static int y2;// second y location of the shape
static int shapeWidth;// width of the shape
static int shapeHeight;// height of the shape
static final int left = 37;
static final int right = 39;
static final int down = 40;
static final int up = 38;
static boolean leftPress;
static boolean rightPress;
static boolean upPress;
static boolean downPress;
static int speed = 1;
static int x;
static int y;
static int size = 50;
static String facingDirection = "RIGHT";
int enemyX1;
int enemyY1;
int enemyX2;
int enemyY2;
int enemySpeed;
int enemySize;

static Image LimageFishy = new ImageIcon("F://Picture//Lfish.png").getImage();
static Image RimageFishy = new ImageIcon("F://Picture//Rfish.png").getImage();
static BufferedImage bufferedImageFishy;

Fishy enemyFish[] = new Fishy[20];

static JFrame frame = new JFrame("Fishy");

// TREE method of extending classes[]

static Fishy fishy = new Fishy(1000, 500, 9);

Fishy(int width, int length, int minusBy) {
    super(width, length, minusBy);
}

/* Graphics goes here */
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.BLUE);
    g.fillRect(0, 0, 1000, 500);

    // size++;
     if (facingDirection.equals("RIGHT")) {
     g.drawImage(RimageFishy, x1, y1, size, size, null);
     }
     if (facingDirection.equals("LEFT")) {
     g.drawImage(LimageFishy, x1, y1, size, size, null);
     }

    g.drawString(DraggingShapes.mousePointerLocation, 50, 50);

}

public static void main(String args[]) throws IOException, InterruptedException {

    frame.addKeyListener(fishy);
    fishy.addMouseMotionListener(fishy);

    frame.add(fishy);
    Frame.showFrame(frame, false);

    /*while (true) {
        Thread.sleep(1);
        if (x1 < 1000) {
            x1++;
        } else {
            x1 = 0;
        }
        frame.repaint();
    }*/

}

@Override
public void keyPressed(KeyEvent e) {

    if (up == e.getKeyCode()) {

        upPress = true;
    }
    if (down == e.getKeyCode()) {

        downPress = true;
    }
    if (left == e.getKeyCode()) {

        leftPress = true;
        facingDirection = "LEFT";
    }
    if (right == e.getKeyCode()) {

        rightPress = true;
        facingDirection = "RIGHT";
    }

    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

    if (upPress == true && leftPress == false && rightPress == false) {
        fishy.y1 -= speed;
    }
    if (downPress == true && leftPress == false && rightPress == false) {
        fishy.y1 += speed;
    }
    if (leftPress == true && upPress == false && downPress == false) {
        fishy.x1 -= speed;
    }
    if (rightPress == true && upPress == false && downPress == false) {
        fishy.x1 += speed;
    }

    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

    if (leftPress == true && upPress == true) {
        fishy.x1 -= speed;
        fishy.y1 -= speed;
    }
    if (leftPress == true && downPress == true) {
        fishy.x1 -= speed;
        fishy.y1 += speed;
    }
    if (rightPress == true && upPress == true) {
        fishy.x1 += speed;
        fishy.y1 -= speed;
    }
    if (rightPress == true && downPress == true) {
        fishy.x1 += speed;
        fishy.y1 += speed;
    }

    System.out.println("PRESSING (Left:" + leftPress + ") (Right:" + rightPress + ") (Up:" + upPress + ") (Down:" + downPress + ")");
    repaint();

}

@Override
public void keyReleased(KeyEvent e) {

    if (up == e.getKeyCode()) {
        upPress = false;

    }
    if (down == e.getKeyCode()) {
        downPress = false;

    }
    if (left == e.getKeyCode()) {
        leftPress = false;

    }
    if (right == e.getKeyCode()) {
        rightPress = false;

    }

}

@Override
public void mouseMoved(MouseEvent e) {
    DraggingShapes.showPointerLocation(e.getX(), e.getY());
    repaint();

}

/*** METHODS THAT WE'RE NOT GOING TO USE ***/
@Override
public void keyTyped(KeyEvent e) {

}

@Override
public void mouseDragged(MouseEvent e) {

}

}

另外,我注意到当你用键盘输入控制图像时,只是告诉它使用Thread.sleep(毫秒)进行重绘,当你将它告诉Thread.sleep时(1)毫秒),图像重新绘制得非常快,即使你只增加了1个像素,我也想知道它为什么与键盘输入不一样。

2 个答案:

答案 0 :(得分:0)

如果保持密钥,KeyListener将每隔n毫秒触发一次(这可能取决于操作系统,但在我的Windows系统上为n~33ms)。因此重绘将每隔~n毫秒调用一次。相对于Thread.sleep(1)方法,这慢了约n倍(注意这是近似的,因为重绘是对EDT绘制的请求,实际工作的速度可能取决于重绘队列和绘画本身)。因此,在33毫秒时,您的物体仅行进约30像素/秒。

我没有必要建议尝试提高重新绘制的速度来加快速度,而不是通过提高它的移动速度来加快速度(例如速度变量)。沿着这些相同的行,您可以使用Swing计时器来提供动画循环。

javax.swing.Timer timer = new javax.swing.Timer(60, new ActionListener(){

    @Override
    public void actionPerformed(ActionEvent arg0) {
        repaint();
    }

});
timer.start();

这使您可以更好地控制动画发生的速度。您可以使用UI侦听器元素(或其他方式)更改模型,并依赖此计时器进行动画处理。下降经验法则可能是计时器每隔60ms发射一次。请注意,这不会加快速度 - 只需让您更好地控制动画过程。

答案 1 :(得分:-1)

我不确定这是否正是您所寻找的,但这可能是您使用sleep(1)与使用键盘移动鱼之间存在一些差异的原因。我通过添加HashMap重构了您的代码,因为它允许更容易更新并使用它来更新方向变量。

public class Fishy extends Panel implements KeyListener, MouseMotionListener {


    // here is the map declaration for the data structure
    // that will map the key, which was an integer, to
    // (up,down,right,left)press, which was a boolean.

    static Map<Integer, Boolean> map = new HashMap<>();


    static int x1;// first x location of the shape.
    static int x2;// second x location of the shape
    static int y1;// first y location of the shape
    static int y2;// second y location of the shape
    static int shapeWidth;// width of the shape
    static int shapeHeight;// height of the shape
    static final int left = 37;
    static final int right = 39;
    static final int down = 40;
    static final int up = 38;
    static boolean leftPress;
    static boolean rightPress;
    static boolean upPress;
    static boolean downPress;
    static int speed = 1;
    static int x;
    static int y;
    static int size = 50;
    static String facingDirection = "RIGHT";
    int enemyX1;
    int enemyY1;
    int enemyX2;
    int enemyY2;
    int enemySpeed;
    int enemySize;


    static Image LimageFishy = new ImageIcon("F://Picture//Lfish.png").getImage();
    static Image RimageFishy = new ImageIcon("F://Picture//Rfish.png").getImage();
    static BufferedImage bufferedImageFishy;

    Fishy enemyFish[] = new Fishy[20];

    static JFrame frame = new JFrame("Fishy");

    // TREE method of extending classes[]

    static Fishy fishy = new Fishy(1000, 500, 9);

    Fishy(int width, int length, int minusBy) {
        super(width, length, minusBy);
    }

    /* Graphics goes here */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        g.fillRect(0, 0, 1000, 500);

        // size++;
         if (facingDirection.equals("RIGHT")) {
         g.drawImage(RimageFishy, x1, y1, size, size, null);
         }
         if (facingDirection.equals("LEFT")) {
         g.drawImage(LimageFishy, x1, y1, size, size, null);
         }

        g.drawString(DraggingShapes.mousePointerLocation, 50, 50);

    }


    static void buildMap() {
        map.put(up, false);
        map.put(down, false);
        map.put(left, false);
        map.put(right, false);

    }


    public static void main(String args[]) throws IOException, InterruptedException {

        buildMap();

        frame.addKeyListener(fishy);
        fishy.addMouseMotionListener(fishy);

        frame.add(fishy);
        Frame.showFrame(frame, false);

        /*while (true) {
            Thread.sleep(1);
            if (x1 < 1000) {
                x1++;
            } else {
                x1 = 0;
            }
            frame.repaint();
        }*/

    }

    @Override
    public void keyPressed(KeyEvent e) {

        // using the hashmap, we can refactor away the if statements
        map.put(e.getKeyCode(), true);

        /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

        // It is possible to refactor away the following if statements
        // but that requires further surgery on the code.

        for (Map.Entry<Integer, Boolean> entry: map.entrySet()) {
            if (entry.getValue()) {
                if (entry.getKey() == up) {
                    fishy.y1 -= speed;
                }
                else if (entry.getKey() == down) {
                    fishy.y1 += speed;

                }
                else if (entry.getKey() == right) {
                    fishy.x1 += speed;

                }
                else if (entry.getKey() == left) {
                    fishy.x1 -= speed;

                }
            }
        }



        System.out.println("PRESSING (Left:" + leftPress + ") (Right:" + rightPress + ") (Up:" + upPress + ") (Down:" + downPress + ")");
        repaint();

    }

    @Override
    public void keyReleased(KeyEvent e) {

        // got rid of the unnecessary if statements
        // and directly accessed the hashmap to update the value
        map.put(e.getKeyCode(), false);

    }

    @Override
    public void mouseMoved(MouseEvent e) {
        DraggingShapes.showPointerLocation(e.getX(), e.getY());
        repaint();

    }

    /*** METHODS THAT WE'RE NOT GOING TO USE ***/
    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void mouseDragged(MouseEvent e) {

    }

    }