Create TimingThread to better control worker timings.

This commit is contained in:
Jan Philipp Timme 2014-10-24 21:38:36 +02:00
parent b42c8f3a1a
commit a733187887
10 changed files with 146 additions and 109 deletions

View File

@ -6,7 +6,8 @@ import de.teamteamteam.spacescooter.background.StarBackground;
import de.teamteamteam.spacescooter.entities.Player;
import de.teamteamteam.spacescooter.entities.TestEntity;
import de.teamteamteam.spacescooter.gui.GameFrame;
import de.teamteamteam.spacescooter.threads.GameThread;
import de.teamteamteam.spacescooter.threads.PaintThread;
import de.teamteamteam.spacescooter.threads.UpdateThread;
/**
* Nothing but a class containing the main method.
@ -36,8 +37,12 @@ public class Main {
});
//Initialize GameThread
GameThread gameThread = new GameThread(gf);
gameThread.start();
PaintThread paintThread = new PaintThread(gf);
paintThread.start();
//Initialize UpdateThread
UpdateThread updateThread = new UpdateThread();
updateThread.start();
}
}

View File

@ -23,16 +23,17 @@ public class StarBackground extends Background {
private int offset = 0;
public void update(long millisecondsSinceLastCall) {
this.offset -= 5;
public void update() {
this.offset -= 3;
//System.out.println(this.offset);
if(Math.abs(this.offset) > StarBackground.img.getWidth()) {
this.offset += StarBackground.img.getWidth();
}
}
public void paint(Graphics g) {
g.drawImage(StarBackground.img, 0+this.offset, 0, StarBackground.img.getWidth(), StarBackground.img.getHeight(), null);
g.drawImage(StarBackground.img, StarBackground.img.getWidth()+this.offset, 0, StarBackground.img.getWidth(), StarBackground.img.getHeight(), null);
g.drawImage(StarBackground.img, (0+this.offset), 0, null);
g.drawImage(StarBackground.img, (StarBackground.img.getWidth()+this.offset), 0, null);
}
}

View File

@ -31,7 +31,7 @@ public class Player extends Entity {
this.y = 300;
}
public void update(long millisecondsSinceLastCall) {
public void update() {
int off = 3;
if(Keyboard.isKeyDown(KeyEvent.VK_UP) && this.y > 0) {
this.y -= off;

View File

@ -21,7 +21,7 @@ public class TestEntity extends Entity {
g.fillRect(300, 300, 100, 100);
}
public void update(long millisecondsSinceLastCall) {
public void update() {
if(Keyboard.isKeyDown(KeyEvent.VK_SPACE)) {
System.out.println("Hallo Welt!");
}

View File

@ -2,6 +2,6 @@ package de.teamteamteam.spacescooter.entities;
public interface Updateable {
public void update(long millisecondsSinceLastCall);
public void update();
}

View File

@ -18,6 +18,8 @@ public class GameFrame extends JFrame {
private static final long serialVersionUID = 1L;
private BufferStrategy bufferStrategy;
public GameFrame() {
super();
}
@ -36,27 +38,29 @@ public class GameFrame extends JFrame {
this.addKeyListener(new Keyboard());
this.setVisible(true);
this.createBufferStrategy(2);
this.bufferStrategy = this.getBufferStrategy();
}
/**
* The pain, do not underestimate it!
*
* @see http://content.gpwiki.org/index.php/Java:Tutorials:Double_Buffering for details.
*/
public void draw() {
this.createBufferStrategy(2);
Graphics bufferedGraphics = null;
BufferStrategy bufferStrategy = this.getBufferStrategy();
do { //while bufferStrategy.contentsLost()
do { //bufferStrategy.contentsRestored()
do { // while bufferStrategy.contentsLost()
do { // bufferStrategy.contentsRestored()
try {
bufferedGraphics = bufferStrategy.getDrawGraphics();
bufferedGraphics = this.bufferStrategy.getDrawGraphics();
// Now we can use bufferedGraphics to actually draw stuff
this.drawBackgrounds(bufferedGraphics);
this.drawEntities(bufferedGraphics);
} catch(Exception e) {
} catch (Exception e) {
System.out.println("Hier geht was schief");
System.out.println(e);
} finally {
@ -64,11 +68,10 @@ public class GameFrame extends JFrame {
if (bufferedGraphics != null)
bufferedGraphics.dispose();
}
} while (bufferStrategy.contentsRestored());
bufferStrategy.show();
} while (bufferStrategy.contentsLost());
} while (this.bufferStrategy.contentsRestored());
this.bufferStrategy.show();
} while (this.bufferStrategy.contentsLost());
Toolkit.getDefaultToolkit().sync();
}
public void drawBackgrounds(Graphics g) {
@ -78,7 +81,7 @@ public class GameFrame extends JFrame {
b.paint(g);
}
}
public void drawEntities(Graphics g) {
Iterator<Entity> i = Entity.entities.iterator();
while (i.hasNext()) {
@ -86,7 +89,4 @@ public class GameFrame extends JFrame {
e.paint(g);
}
}
}

View File

@ -1,84 +0,0 @@
package de.teamteamteam.spacescooter.threads;
import java.awt.EventQueue;
import java.util.Iterator;
import de.teamteamteam.spacescooter.background.Background;
import de.teamteamteam.spacescooter.entities.Entity;
import de.teamteamteam.spacescooter.gui.GameFrame;
/**
* This thread triggers about 60 redraws per second.
*/
public class GameThread extends Thread {
private GameFrame gf;
private long lastFrame;
/**
* 60FPS => 1/60s in nanoseconds (10^-9).
*/
private long frameTime = (1000L*1000L*1000L) / 60L;
public GameThread(GameFrame gf) {
this.setName("GameThread");
this.gf = gf;
// this.setPriority(Thread.MAX_PRIORITY);
}
public void run() {
final GameFrame gf = this.gf; // :'-(
while (true) {
long frameStart = System.nanoTime();
//Update all the entities
this.updateBackgrounds();
this.updateEntities();
//Trigger redrawing the things. Important: AWT-Context needed here!
EventQueue.invokeLater(new Runnable() {
public void run() {
gf.draw();
}
});
long frameDone = System.nanoTime();
long workTime = (frameDone - frameStart);
//System.out.println("Arbeitszeit: " + (workTime) + "ns");
long timeToWait = this.frameTime - workTime;
long msToWait = timeToWait / 1000000;
//wait using sleep for bigger intervals
if(msToWait > 1) {
try {
Thread.sleep(msToWait);
} catch(InterruptedException e) {
System.err.println(e.getStackTrace());
}
}
System.out.println("1: " + (System.nanoTime() - frameStart));
System.out.println("2: " + (System.nanoTime() - frameStart));
System.out.println("3: " + (System.nanoTime() - frameStart));
System.out.println("4: " + (System.nanoTime() - frameStart));
System.out.println("5: " + (System.nanoTime() - frameStart));
}
}
private void updateBackgrounds() {
Iterator<Background> i = Background.backgrounds.iterator();
while(i.hasNext()) {
Background b = i.next();
b.update(System.nanoTime() - this.lastFrame);
}
}
private void updateEntities() {
Iterator<Entity> i = Entity.entities.iterator();
while(i.hasNext()) {
Entity e = i.next();
e.update(System.nanoTime() - this.lastFrame);
}
}
}

View File

@ -0,0 +1,28 @@
package de.teamteamteam.spacescooter.threads;
import java.awt.EventQueue;
import de.teamteamteam.spacescooter.gui.GameFrame;
/**
* This thread triggers about 60 redraws per second.
*/
public class PaintThread extends TimingThread {
private GameFrame gf;
public PaintThread(GameFrame gf) {
this.gf = gf;
this.setName("GameThread");
this.setHz(60);
}
public void work() {
//Trigger redrawing the things. Important: AWT-Context needed here!
EventQueue.invokeLater(new Runnable() {
public void run() {
gf.draw();
}
});
}
}

View File

@ -0,0 +1,51 @@
package de.teamteamteam.spacescooter.threads;
public abstract class TimingThread extends Thread {
private long workInterval;
/**
* This method sets the actual working interval based on hz.
*
* @param hz
*/
public void setHz(int hz) {
this.workInterval = (1000L * 1000L * 1000L) / (long) hz;
}
/**
* This method takes care of the timing.
*/
public void run() {
while (true) {
long workStart = System.nanoTime();
// do the actual work
this.work();
long workDone = System.nanoTime();
long workTime = (workDone - workStart);
long timeToWait = this.workInterval - workTime;
long msToWait = timeToWait / 1000000;
// wait using sleep for bigger intervals
if (msToWait > 1) {
try {
Thread.sleep(msToWait);
} catch (InterruptedException e) {
System.err.println("[" + this.getName() + "]" + e.getStackTrace());
}
}
while (this.workInterval - (System.nanoTime() - workStart) > 100);
//System.out.println("[" + this.getName() + "]: "+ (System.nanoTime() - workStart));
}
}
/**
* Do the actual thread work in here.
*/
public abstract void work();
}

View File

@ -0,0 +1,36 @@
package de.teamteamteam.spacescooter.threads;
import java.util.Iterator;
import de.teamteamteam.spacescooter.background.Background;
import de.teamteamteam.spacescooter.entities.Entity;
public class UpdateThread extends TimingThread {
public UpdateThread() {
this.setName("UpdateThread");
this.setHz(100);
}
public void work() {
// Update all the entities
this.updateBackgrounds();
this.updateEntities();
}
private void updateBackgrounds() {
Iterator<Background> i = Background.backgrounds.iterator();
while (i.hasNext()) {
Background b = i.next();
b.update();
}
}
private void updateEntities() {
Iterator<Entity> i = Entity.entities.iterator();
while (i.hasNext()) {
Entity e = i.next();
e.update();
}
}
}