java 摆动计时器在调试时工作正常但在运行时不工作
java swing timer works fine in debug but not in runtime
我已经尝试这个几个小时了,我 lost.I 想要 运行 我的游戏以 30 fps 的速度运行。摆动定时器延迟设置为 1000/30。即使我将它减慢到 1000 或 2000,它也不会改变任何东西。在逐步调试中,一切都按预期工作。 "updateALL()" 方法在下次定时器刷新时被调用。但是在 运行time updateAll 从未被调用,甚至一次都没有(sysout 从不打印)。我精简了下面的代码以显示基本部分。它应该编译。
这是我的听众class:
public class Observer implements ActionListener {
private int timerFrame;
private int fps;
private boolean frameComplete;
public Observer() {
this.frameComplete = true;
this.timerFrame = 0;
}
@Override
public void actionPerformed(ActionEvent aEvent) {
nextTimerFrame();
}
public void frameCompleted() {
frameComplete = true;
System.out.println("Fcompleted");
}
public int getTimerFrame() {
return timerFrame;
}
public void setFps(int fps) {
this.fps = fps;
}
private void nextTimerFrame() {
System.out.println(timerFrame);
if(frameComplete) {
if(timerFrame == fps) {
timerFrame = 1;
} else {
++timerFrame;
}
frameComplete = false;
}
}
}
这是我的 GameClock 中的代码 Class:
public class GameClock {
private Timer timer;
private Observer observer;
private GameEngine gameEngine;
private View view;
private boolean paused;
private boolean quit;
private int clockFrame;
public GameClock() {}
public GameClock(GameEngine gameEngine) {
this.gameEngine = gameEngine;
this.paused = false;
this.quit = false;
setupTimer();
this.clockFrame = 0;
run();
}
public void updateAll() {
readInputs();
updateGameEngine();
updateCanvas2D();
updateCanvas3D();
clockFrame = clockFrame == 30? 1:clockFrame+1;
observer.frameCompleted(); // puts frameComplete at "true" in Observer
System.out.println("update" + clockFrame);
}
public void run() {
while(!quit) {
int timerFrame = observer.getRefreshFrame();
if(!paused && (clockFrame < timerFrame || (clockFrame == 30 && timerFrame == 1))) {
updateAll();
//System.out.println("update");
}
}
}
private void setupTimer() {
int fps = Config.getFps();
int delay = Math.round(1000/fps);
observer.setFps(fps);
this.timer = new Timer(delay, observer);
timer.start();
}
private void readInputs() {
}
private void updateGameEngine() {
}
private void updateCanvas2D() {
}
private void updateCanvas3D() {
}
}
更新:
一些奇怪的观察:
如果我将 2 sysout 放入我的 while 循环的 "if" 语句中,它们永远不会打印。这没有打印输出:
public void run() {
while(!quit) {
int clockFrame = observer.getRefreshFrame();
//System.out.println("clock" + clockFrame);
//System.out.println("frame" + refreshFrame);
if(!paused && (refreshFrame < clockFrame || (refreshFrame == 30 && clockFrame == 1))) {
System.out.println("clock" + clockFrame);
System.out.println("frame" + refreshFrame);
updateAll();
//System.out.println("update");
}
}
}
如果我将之前的 sysout 放在注释中并从 "if" 语句之外的 2 中删除 //,如下所示:
public void run() {
while(!quit) {
int clockFrame = observer.getRefreshFrame();
System.out.println("clock" + clockFrame);
System.out.println("frame" + refreshFrame);
if(!paused && (refreshFrame < clockFrame || (refreshFrame == 30 && clockFrame == 1))) {
//System.out.println("clock" + clockFrame);
//System.out.println("frame" + refreshFrame);
updateAll();
//System.out.println("update");
}
}
}
我看到 refreshFrame 总是随着 clockFrame 递增。这是没有意义的。如果从不调用 updateAll refreshFrame 则不会递增。
更新 2 - 一些解释:
- 摆动计时器需要一个侦听器并在它计时时生成一个 actionPerformed() 事件。这就是为什么我需要一个观察者。
- 我不能直接调用定时器 "updateAll()" 因为定时器在它自己的线程上。如果我这样做,计时器可能会调用 "updateAll()",而之前的更新尚未完全完成。
- 它 "should" 的工作方式:while 一直循环不做任何事情,直到它看到计时器已计时(clockFrame 低于 timerFrame)。然后它 updateAll()。除非最后一个 updateAll() 已完全完成(frameComplete 在 updateAll 结束时设置为 true),否则 timerFrame 不能递增。更新完成后,下一个计时器滴答将增加 timerFrame,从而生成新的更新。
- 理论上和逐步调试它有效,但在 运行 时间无效。
以下是一个文件 mre(将整个代码复制粘贴到 GameClock.java
)演示如何使用秋千 Timer
更新秋千 View
在 30fps:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Timer;
public class GameClock {
private final Observer observer;
private final View view;
public GameClock() {
view = new View();
observer = new Observer(view);
setupTimer();
}
private void setupTimer() {
int fps = 30;
int delay = Math.round(1000/fps);
observer.setFps(fps);
Timer timer = new Timer(delay, observer);
timer.setInitialDelay(0);
timer.start();
}
public static void main(String[] args) {
new GameClock();
}
}
class View {
private JLabel counter;
View(){
createAndShowGui();
}
void createAndShowGui(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
counter = new JLabel("0", SwingConstants.CENTER);
f.add(counter);
f.pack();
f.setVisible(true);
}
void setCounter(int i){
counter.setText(String.valueOf(i));
}
}
class Observer implements ActionListener {
private int timerFrame;
private int fps;
private final boolean paused;
private final View view;
public Observer(View view) {
this.view = view;
paused = false;
timerFrame = 0;
}
@Override
public void actionPerformed(ActionEvent aEvent) {
if (! paused) {
updateAll();
}
}
public int getTimerFrame() {
return timerFrame;
}
public void setFps(int fps) {
this.fps = fps;
}
private void nextTimerFrame() {
timerFrame = timerFrame >= fps ? 0 : timerFrame + 1;
}
public void updateAll() {
nextTimerFrame();
view.setCounter(timerFrame);
}
}
我已经尝试这个几个小时了,我 lost.I 想要 运行 我的游戏以 30 fps 的速度运行。摆动定时器延迟设置为 1000/30。即使我将它减慢到 1000 或 2000,它也不会改变任何东西。在逐步调试中,一切都按预期工作。 "updateALL()" 方法在下次定时器刷新时被调用。但是在 运行time updateAll 从未被调用,甚至一次都没有(sysout 从不打印)。我精简了下面的代码以显示基本部分。它应该编译。
这是我的听众class:
public class Observer implements ActionListener {
private int timerFrame;
private int fps;
private boolean frameComplete;
public Observer() {
this.frameComplete = true;
this.timerFrame = 0;
}
@Override
public void actionPerformed(ActionEvent aEvent) {
nextTimerFrame();
}
public void frameCompleted() {
frameComplete = true;
System.out.println("Fcompleted");
}
public int getTimerFrame() {
return timerFrame;
}
public void setFps(int fps) {
this.fps = fps;
}
private void nextTimerFrame() {
System.out.println(timerFrame);
if(frameComplete) {
if(timerFrame == fps) {
timerFrame = 1;
} else {
++timerFrame;
}
frameComplete = false;
}
}
}
这是我的 GameClock 中的代码 Class:
public class GameClock {
private Timer timer;
private Observer observer;
private GameEngine gameEngine;
private View view;
private boolean paused;
private boolean quit;
private int clockFrame;
public GameClock() {}
public GameClock(GameEngine gameEngine) {
this.gameEngine = gameEngine;
this.paused = false;
this.quit = false;
setupTimer();
this.clockFrame = 0;
run();
}
public void updateAll() {
readInputs();
updateGameEngine();
updateCanvas2D();
updateCanvas3D();
clockFrame = clockFrame == 30? 1:clockFrame+1;
observer.frameCompleted(); // puts frameComplete at "true" in Observer
System.out.println("update" + clockFrame);
}
public void run() {
while(!quit) {
int timerFrame = observer.getRefreshFrame();
if(!paused && (clockFrame < timerFrame || (clockFrame == 30 && timerFrame == 1))) {
updateAll();
//System.out.println("update");
}
}
}
private void setupTimer() {
int fps = Config.getFps();
int delay = Math.round(1000/fps);
observer.setFps(fps);
this.timer = new Timer(delay, observer);
timer.start();
}
private void readInputs() {
}
private void updateGameEngine() {
}
private void updateCanvas2D() {
}
private void updateCanvas3D() {
}
}
更新:
一些奇怪的观察:
如果我将 2 sysout 放入我的 while 循环的 "if" 语句中,它们永远不会打印。这没有打印输出:
public void run() {
while(!quit) {
int clockFrame = observer.getRefreshFrame();
//System.out.println("clock" + clockFrame);
//System.out.println("frame" + refreshFrame);
if(!paused && (refreshFrame < clockFrame || (refreshFrame == 30 && clockFrame == 1))) {
System.out.println("clock" + clockFrame);
System.out.println("frame" + refreshFrame);
updateAll();
//System.out.println("update");
}
}
}
如果我将之前的 sysout 放在注释中并从 "if" 语句之外的 2 中删除 //,如下所示:
public void run() {
while(!quit) {
int clockFrame = observer.getRefreshFrame();
System.out.println("clock" + clockFrame);
System.out.println("frame" + refreshFrame);
if(!paused && (refreshFrame < clockFrame || (refreshFrame == 30 && clockFrame == 1))) {
//System.out.println("clock" + clockFrame);
//System.out.println("frame" + refreshFrame);
updateAll();
//System.out.println("update");
}
}
}
我看到 refreshFrame 总是随着 clockFrame 递增。这是没有意义的。如果从不调用 updateAll refreshFrame 则不会递增。
更新 2 - 一些解释:
- 摆动计时器需要一个侦听器并在它计时时生成一个 actionPerformed() 事件。这就是为什么我需要一个观察者。
- 我不能直接调用定时器 "updateAll()" 因为定时器在它自己的线程上。如果我这样做,计时器可能会调用 "updateAll()",而之前的更新尚未完全完成。
- 它 "should" 的工作方式:while 一直循环不做任何事情,直到它看到计时器已计时(clockFrame 低于 timerFrame)。然后它 updateAll()。除非最后一个 updateAll() 已完全完成(frameComplete 在 updateAll 结束时设置为 true),否则 timerFrame 不能递增。更新完成后,下一个计时器滴答将增加 timerFrame,从而生成新的更新。
- 理论上和逐步调试它有效,但在 运行 时间无效。
以下是一个文件 mre(将整个代码复制粘贴到 GameClock.java
)演示如何使用秋千 Timer
更新秋千 View
在 30fps:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Timer;
public class GameClock {
private final Observer observer;
private final View view;
public GameClock() {
view = new View();
observer = new Observer(view);
setupTimer();
}
private void setupTimer() {
int fps = 30;
int delay = Math.round(1000/fps);
observer.setFps(fps);
Timer timer = new Timer(delay, observer);
timer.setInitialDelay(0);
timer.start();
}
public static void main(String[] args) {
new GameClock();
}
}
class View {
private JLabel counter;
View(){
createAndShowGui();
}
void createAndShowGui(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
counter = new JLabel("0", SwingConstants.CENTER);
f.add(counter);
f.pack();
f.setVisible(true);
}
void setCounter(int i){
counter.setText(String.valueOf(i));
}
}
class Observer implements ActionListener {
private int timerFrame;
private int fps;
private final boolean paused;
private final View view;
public Observer(View view) {
this.view = view;
paused = false;
timerFrame = 0;
}
@Override
public void actionPerformed(ActionEvent aEvent) {
if (! paused) {
updateAll();
}
}
public int getTimerFrame() {
return timerFrame;
}
public void setFps(int fps) {
this.fps = fps;
}
private void nextTimerFrame() {
timerFrame = timerFrame >= fps ? 0 : timerFrame + 1;
}
public void updateAll() {
nextTimerFrame();
view.setCounter(timerFrame);
}
}