所以我有一个我试图制作的游戏,在游戏循环中,我称之为Thread.sleep()。否则,我有代码在调整大小时保持窗口的宽高比。这很有效,除了在我调整大小时我得到奇怪的闪烁。我把问题缩小到了Thread.sleep(),当我把这一行拿出来时,我的程序运行正常,但是这会导致CPU飙升到如此高,以至于在我的Macbook上,Activity Monitor应用程序说我的游戏使用170 +%!现在这是有问题的,而且无论如何我都把睡眠线放在那里。我听说睡在事件调度线程上会导致这种效果,但是我在一个新线程中运行这个循环,所以我觉得我很好。你们知道会发生什么吗?这是源代码的一部分(你真的需要查看run()方法):
package jeffrey_ryan.game2d;
public class GameLoop implements Runnable {
private boolean running = false;
private boolean paused = false;
private float gameHertz = 30.0f;
private long timeBetweenUpdates = (long) (1_000_000_000 / gameHertz);
private int maxUpdates = 5;
private LoopListener loopListener;
public void run() {
long lastUpdateTime = System.nanoTime();
running = true;
while (running) {
long now = System.nanoTime();
if (!paused) {
int updates = 0;
while (now - lastUpdateTime >= timeBetweenUpdates && updates < maxUpdates) {
if (loopListener != null) {
loopListener.update((double) timeBetweenUpdates / 1_000_000_000);
}
lastUpdateTime += timeBetweenUpdates;
updates++;
}
if (loopListener != null) {
float interpolation = Math.min(1.0f, (float) (now - lastUpdateTime) / timeBetweenUpdates);
loopListener.render(interpolation);
}
long timeRemaining = (timeBetweenUpdates - (now - lastUpdateTime)) / 1_000_000;
try {
Thread.sleep(Math.max(timeRemaining - 5, 0)); // HERE'S THE OFFENDING LINE ******************
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
}
else {
try {
Thread.sleep(25);
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public void start() {
running = true;
}
public void stop() {
running = false;
}
public void pause() {
paused = true;
}
public void play() {
paused = false;
}
public float getSpeed() {
return gameHertz;
}
public void setSpeed(float hertz) {
gameHertz = hertz;
timeBetweenUpdates = (long) (1_000_000_000 / gameHertz);
}
public int getMaxUpdates() {
return maxUpdates;
}
public void setMaxUpdates(int updates) {
maxUpdates = updates;
}
public void setLoopListener(LoopListener listener) {
loopListener = listener;
}
}
在我的JPanel子类中,运行此循环的代码(循环变量是上述类的实例):
@Override
public void addNotify() {
super.addNotify();
addKeyListener(this);
addMouseListener(this);
Thread thread = new Thread(loop, "GameLoop");
thread.start();
}
如果你们能帮助我,我会喜欢它,我真的很难过。谢谢!
答案 0 :(得分:0)
您应该使用SwingWorker而不是Thread来异步操作Swing组件。当我发现这个家伙时,我的生活发生了变化=)。 SwingWorker为您提供了一个方法“进程”,您可以使用它来逐步执行操作,并使用“完成”方法来完成处理,这两种方法都可以安全地处理事件派发线程。您应该在“doInBackground”上进行后台处理。
答案 1 :(得分:0)
调用&#39; Thread.sleep(n)&#39;导致整个线程无响应,如果此线程绑定到您的JFrame线程,那么该线程也将变得无响应并导致整个框架和组件冻结并停止响应 - 可能是闪烁的原因。因此,确保睡眠处于游戏循环而不是帧上,一种方法是在初始化时创建两个线程,一个用于帧,另一个用于逻辑,然后让游戏循环处理输入和输出,同时显示线程只显示(我相信这是大多数游戏引擎的工作方式)。还要确保任何线程都没有链接,否则睡眠线程会影响显示线程。
答案 2 :(得分:0)
我找到了问题的答案。调用循环的类是一个JPanel,在调整大小时没有重新绘制,只有当循环告诉它时,这导致了一些JPanel也没有画过的时期。我通过覆盖paintComponent来解决这个问题。