白色方块移动时有滞后。我没有发现代码有任何问题,而且由于应用程序非常简单,我认为硬件也不是问题。
演示该问题的视频: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;
}
}
}
程序运行时我的活动监视器:
我已将电脑更新至最新版本。
那个
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()
来代替。