Wie am besten sleep berechnen

Hallo Leute.
Ich greif mal wieder ein älteres thema auf, aber es interessiert mich jetzt einfach mal:
Hier ist der Code von einem kleinen “Story Viewer” oder sowas, hab ich halt einfach gemacht, weil ein freund sehen wollte wies aussieht :smiley:
naja, der sleep() wert ist hier ja fixed: immer 10. Nun gibt es ja verschiedene varianten, wie man das ganze am besten anpasst, an die dauer des durchlaufs:
Zwei davon - entweder man berechnet wie lange man schläft, oder aber man schläft immer gleichlang und berechnet wie weit man was bewegt…
was haltet ihr für “besser” bzw geeigneter?

Vielen Dank.
hier der code:

code
[spoiler]

package de.skysoldier.tests;

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ComicTest extends JPanel implements Runnable {

	private JFrame f;
	private Thread t;
	private boolean running;
	private BufferedImage woman;
	private double x, y, x2, y2;
	private Font font;
	private float fl;
	
	public ComicTest(){
		f = new JFrame("Comic Test");
		f.setSize(600, 400);
		f.setLocationRelativeTo(null);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setLayout(new BorderLayout());
		f.add(this);
		init();
	}
	
	public void init(){
		woman = getImage("frau.png");
		font = new Font("Borealis", 0, 20);
		t = new Thread(this);
		running = true;
		f.setVisible(true);	
		t.start();
	}
	
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, getWidth(), getHeight());
		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, fl));
		g.drawImage(woman, (int) x, (int) y, null);
		g.setColor(Color.WHITE);
		g.setFont(font);
		g.drawString("Und da kam sie aus den Tiefen des Warps...", (int) x2, (int) y2);
	}
	
	public BufferedImage getImage(String name){
		try{
			return ImageIO.read(getClass().getClassLoader().getResource(name));
		}
		catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	public void run(){
		int t = 0;
		while(running){
			if(t < 1000){if(fl < 0.99){fl+=0.001;}}
			if(t > 1000){if(fl>0){fl-=0.001;}}
			x-=0.1;
			y-=0.1;
			x2+=0.08;
			y2+=0.08;
			t++;
			repaint();
			System.out.println(t);
			try{Thread.sleep(10);}catch(Exception e){}
		}
	}
	
	public static void main(String[] args) {
		new ComicTest();
	}
}

[/spoiler]

*** Edit ***

ja, am ende fliegen exceptions, aber das ist ja jetzt erstmal egal :stuck_out_tongue:

Ohne sicher zu sein, verstanden zu haben, was du meinst…:

so macht man es üblicherweise bei Spielen, bei denen irgendwas eine “gefühlt konstante Geschwindigkeit” haben soll…

das Berechnen des Weges, der vergangenen Zeit für Berechnung, ist sowieso Pflicht,
falls durch irgendwelche nebenläufigen Threads wie Speicher-Management Pausen nicht exakt eingehalten werden können,

von Sekunden langen Pausen des Computers ganz zu schweigen, aber da muss ja ein Spiel auch nicht zwingend weiterlaufen


von diesem Stand aus kann man immer noch überlegen ob konstante Wartezeit,
dagegen spricht zum einen wiederum die nicht vorhersehbar unterschiedlich langen Pausen/ Unterbrechungen,
aber auch innerhalb des Programms unterschiedliche Belastung pro Runde, je nach Fortschritt/ Aktivität,

einen bestimmten Zeitpunkt anzupeilen, evtl. auch den übernächsten, ruhig mal ne Runde auslassen, ‘frame per second’ senken,
ist real denke ich, sleep(zielZeit - aktuelleZeit)

Ich habs jetzt mal so implementiert:

code
[spoiler]``` public void run(){
long timeLast = System.currentTimeMillis();
while(running){
long timeThis = System.currentTimeMillis();
double timePast = ((double) (timeThis - timeLast)) / 1000d;
timeLast = timeThis;
update(timePast);
repaint();
try{Thread.sleep(10);}catch(Exception e){}
}
}

private int time;
private float opacity;

public void update(double last){
	System.out.println(last);
	if(time < 1000){if(opacity < 0.99){opacity+=0.001;}}
	if(time > 1000){if(opacity>0){opacity-=0.001;}}
	x-=20*last;
	y-=20*last;
	x2+=15*last;
	y2+=15*last;
	time++;
}```[/spoiler]

aber es laggt irgendwie immer noch. wie kann man das noch verbessern? :confused:

für die milli-Differenz habe ich bei mir
0.016
0.016
0.015
aber auch neueren Rechnern/ Betriebssystem als WinXP mag das besser sein,
mit nanotime() könntest du noch genauer rechnen,

ein anderer Trick ist noch, am Anfang eine Startzeit zu merken und die aktuelle Zeit als eben Zeitstempel,
nicht die Differenz, da addieren sich Ungenauigkeiten, Zeit zum Zeit-bestimmen geht evtl. verloren

	public void run() {
		long start =System.nanoTime();
		while (running) {
			double timePast = (System.nanoTime() - start) / 1000000000d;
			update(timePast);

	public void update(double last) {

		x = 20 * last;  // statt += oder bei dir merkwürdigerweise -=
		y = 20 * last;
		x2 = 15 * last;
		y2 = 15 * last;
		time++;
	}

endgültig hübsch bei Swing letztlich nicht zu erwarten denke ich, da braucht es besseres aber kann ich nicht genau sagen