Java:绘制画布时的白框

时间:2014-06-04 23:03:22

标签: java canvas paint

public class Screen extends Canvas implements Runnable {
    private static final int MAX_FPS = 60;
    private static final int FPS_SAMPLE_SIZE = 6;

    private boolean[] keysPressed = new boolean[256];

    private ArrayList<Character> characters = new ArrayList<>();
    private ArrayList<Character> ai = new ArrayList<>();
    private Thread thread;
    private BufferedImage bg;

    //for testing putposes
    private Player slime = new Player("Slime.png", 100, 100);
    private Player bird = new Player("Bird.png", 250, 250);
    private Player giant = new Player("Giant.png", 250, 500);
    private Player swordsman = new Player("Swordsman.png", 500, 250);

    //screen dimensions
    private int height = ((Toolkit.getDefaultToolkit().getScreenSize().height-32)/5*4);
    private int width = Toolkit.getDefaultToolkit().getScreenSize().width;

    private long prevTick = -1;
    private LinkedList<Long> frames = new LinkedList<>();
    private int averageFPS;
    private boolean running;


    public Screen() {
    setSize(width, height);
    try {bg = ImageIO.read(new File("GUI Images/success.jpg"));}
    catch (Exception e) {Utilities.showErrorMessage(this, e);}
    characters.add(slime);
    //  ai.add(bird);
    //ai.add(giant);
    //  ai.add(swordsman);
    addKeyListener(new KeyListener() {
        public void keyPressed(KeyEvent e) {keysPressed[e.getKeyCode()] = true;}
        public void keyReleased(KeyEvent e) {keysPressed[e.getKeyCode()] = false;}
        public void keyTyped(KeyEvent e) {}
        });
    addMouseListener(new MouseListener() {
        public void mouseClicked(MouseEvent e) {}
        public void mouseEntered(MouseEvent e) {}
        public void mouseExited(MouseEvent e) {}
        public void mousePressed(MouseEvent e) {}
        public void mouseReleased(MouseEvent e) {}
        });
    addMouseMotionListener(new MouseMotionListener() {
        public void mouseDragged(MouseEvent e) {}
        public void mouseMoved(MouseEvent e) {}
        });
    addMouseWheelListener(new MouseWheelListener() {
        public void mouseWheelMoved(MouseWheelEvent e) {}
        });

    setVisible(true);
    start();
    }

    public void paint(Graphics g){
    BufferStrategy bs = getBufferStrategy();
    if(getBufferStrategy() == null){
        createBufferStrategy(3);
        return;
    }
    g = bs.getDrawGraphics();
    g.drawImage(bg,0,0,width,height, null);
    g.drawString(String.valueOf(averageFPS), 0, 0);
    for (Character character : ai){
        character.setY(character.getY() + (int)(Math.random() * 10 - 5));
        character.setX(character.getX() + (int)(Math.random() * 10 - 5));
    }
    for (Character character : ai) {g.drawImage(character.getImage(), character.getX(), character.getY(), null);}
    for (Character character : characters) {g.drawImage(character.getImage(), character.getX(), character.getY(), null);}
    g.dispose();
    bs.show();
    }

    public void run() {
    while (running) {
        tick();
        repaint();
    }
    }

    public synchronized void start() {
    running = true;
    thread = new Thread(this);
    thread.start();
    }

    public synchronized void stop() {
    try {thread.join();}
    catch (InterruptedException e) {Utilities.showErrorMessage(this, e);}
    }

    public void tick() {
    if (keysPressed[KeyEvent.VK_W] && (slime.getY() > 0)) {slime.setY(slime.getY() - 1);}
    if (keysPressed[KeyEvent.VK_S] && (slime.getY() < height)) {slime.setY(slime.getY() + 1);}
    if (keysPressed[KeyEvent.VK_A] && (slime.getY() > 0)) {slime.setX(slime.getX() - 1);}
    if (keysPressed[KeyEvent.VK_D] && (slime.getY() < width)) {slime.setX(slime.getX() + 1);}
    //  System.out.println(slime.getX() + ", " + slime.getY());

        long pastTime = System.currentTimeMillis() - prevTick;
        prevTick = System.currentTimeMillis();

        if (frames.size() == FPS_SAMPLE_SIZE) {
            frames.remove();
        }
        frames.add(pastTime);

        // Calculate average FPS
        long sum = 0;
        for (long frame : frames) {
            sum += frame;
        }
        long averageFrame = sum / FPS_SAMPLE_SIZE;
        averageFPS = (int)(1000 / averageFrame);

        // Only if the time passed since the previous tick is less than one
        // second divided by the number of maximum FPS allowed do we delay
        // ourselves to give Time time to catch up to our rendering.
    if (pastTime < 1000.0 / MAX_FPS) {
            try {
                Thread.sleep((1000 / MAX_FPS) - pastTime);
            System.out.println(averageFPS);
            } catch (InterruptedException e) {
                System.out.println(e);
        }
    }

    }
}

有我的代码,基本上这只是屏幕的测试代码,看我是否可以正确地将对象绘制到屏幕上,但是有不稳定的白色框架不断被绘制。它们似乎并不是由任何类型的输入引起的,它们只是在帧刷新期间看似随机发生。关于它可能是什么的任何想法?

1 个答案:

答案 0 :(得分:1)

不要覆盖绘画并在其中使用BufferStrategy。绘画通常需要做基础(AKA“被动”渲染)。 BufferStrategy是一种“主动”渲染方法,您可以控制绘制过程并直接更新缓冲区,两者不能很好地协同工作

从当前paint方法中获取逻辑,并将其置于游戏循环中。

这将要求您在构造函数中删除对start的调用,因为该组件不会被添加到有效的本机对等方(屏幕上显示的组件)。

相反,创建一个Screen的实例,将其添加到您的框架然后调用start,例如......

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestScreen {

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

    public TestScreen() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                Frame frame = new Frame("Testing");
                frame.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        System.exit(0);
                    }
                });
                Screen screen = new Screen();
                frame.add(screen);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                screen.start();
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

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

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }

    }

    public class Screen extends Canvas implements Runnable {

        private static final int MAX_FPS = 60;
        private static final int FPS_SAMPLE_SIZE = 6;

        private boolean[] keysPressed = new boolean[256];

        private ArrayList<Character> characters = new ArrayList<>();
        private ArrayList<Character> ai = new ArrayList<>();
        private Thread thread;
        private BufferedImage bg;

        private long prevTick = -1;
        private LinkedList<Long> frames = new LinkedList<>();
        private int averageFPS;
        private boolean running;

        public Screen() {
            try {
                bg = ImageIO.read(new File("GUI Images/success.jpg"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            addKeyListener(new KeyListener() {
                public void keyPressed(KeyEvent e) {
                    keysPressed[e.getKeyCode()] = true;
                }

                public void keyReleased(KeyEvent e) {
                    keysPressed[e.getKeyCode()] = false;
                }

                public void keyTyped(KeyEvent e) {
                }
            });
            addMouseListener(new MouseListener() {
                public void mouseClicked(MouseEvent e) {
                }

                public void mouseEntered(MouseEvent e) {
                }

                public void mouseExited(MouseEvent e) {
                }

                public void mousePressed(MouseEvent e) {
                }

                public void mouseReleased(MouseEvent e) {
                }
            });
            addMouseMotionListener(new MouseMotionListener() {
                public void mouseDragged(MouseEvent e) {
                }

                public void mouseMoved(MouseEvent e) {
                }
            });
            addMouseWheelListener(new MouseWheelListener() {
                public void mouseWheelMoved(MouseWheelEvent e) {
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            int height = ((Toolkit.getDefaultToolkit().getScreenSize().height - 32) / 5 * 4);
            int width = Toolkit.getDefaultToolkit().getScreenSize().width;
            return new Dimension(width, height);
        }

        public void run() {

            createBufferStrategy(3);
            BufferStrategy bs = null;

            while (running) {
                bs = getBufferStrategy();
                Graphics g = bs.getDrawGraphics();
                g.drawImage(bg, 0, 0, getWidth(), getHeight(), null);
                FontMetrics fm = g.getFontMetrics();
                g.setColor(Color.RED);
                g.drawString(String.valueOf(averageFPS), 0, fm.getAscent());
                g.dispose();
                bs.show();
                tick();
            }
        }

        public synchronized void start() {
            running = true;
            thread = new Thread(this);
            thread.start();
        }

        public synchronized void stop() {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public void tick() {
//            if (keysPressed[KeyEvent.VK_W] && (slime.getY() > 0)) {
//                slime.setY(slime.getY() - 1);
//            }
//            if (keysPressed[KeyEvent.VK_S] && (slime.getY() < height)) {
//                slime.setY(slime.getY() + 1);
//            }
//            if (keysPressed[KeyEvent.VK_A] && (slime.getY() > 0)) {
//                slime.setX(slime.getX() - 1);
//            }
//            if (keysPressed[KeyEvent.VK_D] && (slime.getY() < width)) {
//                slime.setX(slime.getX() + 1);
//            }
//            //  System.out.println(slime.getX() + ", " + slime.getY());

            long pastTime = System.currentTimeMillis() - prevTick;
            prevTick = System.currentTimeMillis();

            if (frames.size() == FPS_SAMPLE_SIZE) {
                frames.remove();
            }
            frames.add(pastTime);

            // Calculate average FPS
            long sum = 0;
            for (long frame : frames) {
                sum += frame;
            }
            long averageFrame = sum / FPS_SAMPLE_SIZE;
            averageFPS = (int) (1000 / averageFrame);

            // Only if the time passed since the previous tick is less than one
            // second divided by the number of maximum FPS allowed do we delay
            // ourselves to give Time time to catch up to our rendering.
            if (pastTime < 1000.0 / MAX_FPS) {
                try {
                    Thread.sleep((1000 / MAX_FPS) - pastTime);
                    System.out.println(averageFPS);
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            }

        }
    }

}