游戏延迟,什么问题?

问题描述 投票:0回答:1

白色方块移动时有滞后。我没有发现代码有任何问题,而且由于应用程序非常简单,我认为硬件也不是问题。

演示该问题的视频https://youtu.be/B9BweJw2KZk?si=Hr2RrktubZkKU9aa

import javax.swing.*;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;

public class GamePanel extends JPanel implements Runnable {
    // SCREEN SETTINGS
    final int originalTileSize = 16; //16x16 tile.
    final int scale = 3;
    //the actual tileSize on screen.
    final int tileSize = originalTileSize * scale; // 48x48
    //horizontally
    final int maxScreenCol = 16;
    //vertically
    final int maxScreenRow = 12;
    final int screenWidth = tileSize * maxScreenCol; //768 px.
    final int screenHeight = tileSize * maxScreenRow; // 576 px;

    //FPS
    int FPS = 60;

    KeyHandler keyH = new KeyHandler();
    Thread gameThread;


    //set player's default position.
    int playerX = 100;
    int playerY = 100;
    int playerSpeed = 4;


    public GamePanel() {
        this.setPreferredSize(new Dimension(screenWidth, screenHeight));
        this.setBackground(Color.BLACK);
        this.setDoubleBuffered(true);
        this.addKeyListener(keyH);
        this.setFocusable(true);
    }


    public void startGameThread() {
        gameThread = new Thread(this);
        gameThread.start();
    }


    public void run() {
        double drawInterval = 1_000_000_000.0 / FPS; // 0.01666 seconds.
        double delta = 0;
        long currentTime;
        long timer = 0;
        int drawCount = 0;
        long lastTime = System.nanoTime();
        while (gameThread != null) {
            currentTime = System.nanoTime();
            delta += (currentTime - lastTime) / drawInterval;
            timer += (currentTime - lastTime);
            lastTime = currentTime;
            if (delta >= 1) {
                update();
                repaint();
                delta--;
                drawCount++;
            }

            if (timer >= 1_000_000_000) {
                System.out.println("FPS: " + drawCount);
                drawCount = 0;
                timer = 0;
            }
        }
    }

    public void update() {
        if (keyH.upPressed) {
            playerY -= playerSpeed;
        } else if (keyH.downPressed) {
            playerY += playerSpeed;
        } else if (keyH.leftPressed) {
            playerX -= playerSpeed;
        } else if (keyH.rightPressed) {
            playerX += playerSpeed;
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.white);
        g2.fillRect(playerX, playerY, tileSize, tileSize);
        g2.dispose();
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame window = new JFrame();
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.setResizable(false);
            window.setTitle("2D Adventure");
            GamePanel gamePanel = new GamePanel();
            window.add(gamePanel);
            window.pack();
            window.setVisible(true);
            gamePanel.startGameThread();
        });
    }
}

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyHandler implements KeyListener {


    public boolean upPressed, downPressed, leftPressed, rightPressed;

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();

        if (code == KeyEvent.VK_W) {
            upPressed = true;
        }
        if (code == KeyEvent.VK_S) {
            downPressed = true;
        }
        if (code == KeyEvent.VK_A) {
            leftPressed = true;
        }
        if (code == KeyEvent.VK_D) {
            rightPressed = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int code = e.getKeyCode();

        if (code == KeyEvent.VK_W) {
            upPressed = false;
        }
        if (code == KeyEvent.VK_S) {
            downPressed = false;
        }
        if (code == KeyEvent.VK_A) {
            leftPressed = false;
        }
        if (code == KeyEvent.VK_D) {
            rightPressed = false;
        }

    }
}

程序运行时我的活动监视器:

enter image description here

enter image description here

我已将电脑更新至最新版本。

java swing cpu lag game-loop
1个回答
1
投票

那个

        while (gameThread != null) {
            currentTime = System.nanoTime();
            delta += (currentTime - lastTime) / drawInterval;
            timer += (currentTime - lastTime);
            lastTime = currentTime;
            if (delta >= 1) {
                update();
                repaint();
                delta--;
                drawCount++;
            }

            if (timer >= 1_000_000_000) {
                System.out.println("FPS: " + drawCount);
                drawCount = 0;
                timer = 0;
            }
        }

部分是“忙碌等待”,似乎是问题的罪魁祸首,因为它会反复检查是否到达结束标志,并在此过程中耗尽资源。相反,您应该使用线程的 join() 方法,该方法将暂停当前线程,直到另一个线程完成其工作。因此,请尝试使用

gameThread.join()
来代替。
    

© www.soinside.com 2019 - 2024. All rights reserved.