Reputation: 51
I've been trying to work this one for hours now and i am at a lost.I want to run my game at 30 fps. the swing timer delay is set to 1000/30. Even if i slow it down to 1000 or 2000 it doesnt change anything. In step by step debug everything works as intended. The "updateALL()" method is called the next time the timer refresh. But in runtime updateAll is never called, not even once (the sysout never prints). Ive trimmed down the code below just to show the essential parts. It should compile.
This is my listener 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;
}
}
}
Here is the code in my 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() {
}
}
Update:
some weird observation:
if i put 2 sysout inside the "if" statement of my while loop they never print. This gives no printout:
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");
}
}
}
If i put the previous sysout in comments and remove the // from the 2 outside the "if" statement like this:
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");
}
}
}
i see that refreshFrame is always incremented with clockFrame. This makes no sense. If updateAll is never called refreshFrame shout not be incremented.
UPDATE 2 - some explanations:
Upvotes: 1
Views: 151
Reputation: 18792
The following is a one-file mre (copy-paste the entire code into GameClock.java
) demonstrating use of a swing Timer
to update a swing View
at 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);
}
}
Upvotes: 1