簡體   English   中英

Swing 應用程序中的低 FPS

[英]Low FPS in Swing Application

您好,我正在使用 Java 和 Swing GUI 的原始 Snake 構建一個相對較小的 2D 游戲。 盡管我的應用程序目前非常小,但我的 FPS 計數在 ~7 到 ~10 FPS 的范圍內非常低。 所有顯示在屏幕上的都是 4 個 10x10 PNG,所以考慮到我希望實現的內容,這有點令人擔憂。

下面給出了我的主要 class 的代碼,下面給出了我用來顯示 FPS 的方法。

public class Board extends JPanel implements ActionListener {

    private final int BOARD_WIDTH = 300;
    private final int BOARD_HEIGHT = 300;
    private final int SEGMENT_SIZE = 10;
    private final int MAX_PARTS = (BOARD_WIDTH / SEGMENT_SIZE) * (BOARD_HEIGHT * SEGMENT_SIZE);
    private final int DELAY = 140;
    private final int RAND_POS = 29;

    private final int x[] = new int[MAX_PARTS];
    private final int y[] = new int[MAX_PARTS];

    private int bodyLen;
    private int appleX;
    private int appleY;

    private boolean rightDirection = true;
    private boolean leftDirection = false;
    private boolean upDirection = false;
    private boolean downDirection = false;
    private boolean inGame = true;

    private Timer timer;
    private Image body;
    private Image head;
    private Image apple;

    private FPSCounter fpscount;

    public Board() {
        initBoard();
    }

    private void initBoard() {
        fpscount = new FPSCounter();
        fpscount.start();
        addKeyListener(new TAdapter());
        setBackground(Color.black);
        setFocusable(true);

        setPreferredSize(new Dimension(BOARD_WIDTH, BOARD_HEIGHT));
        loadImages();
        initGame();
    }

    private void loadImages() {
        ImageIcon app = new ImageIcon("src/main/resources/Apple.png");
        apple = app.getImage();

        ImageIcon bod = new ImageIcon("src/main/resources/Body.png");
        body = bod.getImage();
    }

    private void initGame() {
        bodyLen = 3;
        for(int i = 0; i < bodyLen; i++) {
            x[i] = 50 - i * 10;
            y[i] = 50;
        }

        getApple();

        timer = new Timer(DELAY, this);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        doDrawing(g);
        fpscount.frame(); //added line (step 4).
        g.drawString("" + fpscount.get(), 5, 22); //added line (step 5).
    }

    private void doDrawing(Graphics g) {
        if (inGame) {
            g.drawImage(apple, appleX, appleY, this);

            for(int i = 0; i < bodyLen; i++) {
                g.drawImage(body, x[i], y[i], this);
            }

            Toolkit.getDefaultToolkit().sync();
        }
    }

    private void getApple() {
        int r = (int) (Math.random() * RAND_POS);
        appleX = r * SEGMENT_SIZE;

        r = (int) (Math.random() * RAND_POS);
        appleY = r * SEGMENT_SIZE;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(inGame) {
            move();
        }
        repaint();
    }
    private void move() {
        for(int i = bodyLen; i > 0; i--) {
            x[i] = x[i - 1];
            y[i] = y[i - 1];
        }

        if(leftDirection) {
            x[0] -= SEGMENT_SIZE;
        }
        if(rightDirection) {
            x[0] += SEGMENT_SIZE;
        }
        if(upDirection) {
            y[0] -= SEGMENT_SIZE;
        }
        if(downDirection) {
            y[0] += SEGMENT_SIZE;
        }
    }



    private class TAdapter extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
            if((key == KeyEvent.VK_RIGHT) && (!leftDirection)) {
                rightDirection = true;
                upDirection = false;
                downDirection = false;
                leftDirection = false;
            }
            if((key == KeyEvent.VK_LEFT) && (!rightDirection)) {
                leftDirection = true;
                upDirection = false;
                downDirection = false;
                rightDirection = false;
            }
            if((key == KeyEvent.VK_UP) && (!downDirection)) {
                upDirection = true;
                rightDirection = false;
                leftDirection = false;
                downDirection = false;
            }
            if((key == KeyEvent.VK_DOWN) && (!upDirection)) {
                downDirection = true;
                leftDirection = false;
                rightDirection = false;
                upDirection = false;
            }
        }
    }
}

FPS計數器 Class

        private final Timer resetTimer;
        private int current, last;

        public FPSCounter() {
            resetTimer = new Timer(1000, this);
        }

        public synchronized void start() {
            resetTimer.start();
            current = 0;
            last = -1;
        }

        public synchronized void stop() {
            resetTimer.stop();
            current = -1;
        }

        public synchronized void frame() {
            current++;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            last = current;
            current = 0;
        }

        public synchronized int get() {
            return last;
        }
    }

也許只是我的 FPS 計數器 class 關閉了,但您可以提供任何可能解決此問題的信息將不勝感激。

private final int DELAY = 140;

你的延遲是140。

所以你的每秒幀數將是 1000 / 140 = 7.14。

通常人們的目標是幀速率為 60。因此您應該使用 1000 / 60 = 16 的延遲。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM