Create TimingThread to better control worker timings.
This commit is contained in:
parent
b42c8f3a1a
commit
a733187887
@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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!");
|
||||
}
|
||||
|
||||
@ -2,6 +2,6 @@ package de.teamteamteam.spacescooter.entities;
|
||||
|
||||
public interface Updateable {
|
||||
|
||||
public void update(long millisecondsSinceLastCall);
|
||||
public void update();
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/de/teamteamteam/spacescooter/threads/PaintThread.java
Normal file
28
src/de/teamteamteam/spacescooter/threads/PaintThread.java
Normal 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
51
src/de/teamteamteam/spacescooter/threads/TimingThread.java
Normal file
51
src/de/teamteamteam/spacescooter/threads/TimingThread.java
Normal 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();
|
||||
|
||||
}
|
||||
36
src/de/teamteamteam/spacescooter/threads/UpdateThread.java
Normal file
36
src/de/teamteamteam/spacescooter/threads/UpdateThread.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user