CPU-Auslastung des repaints zu hoch.

Kai008

Erfahrenes Mitglied
Hi.
Habe ein simples Frame mit einen simplen Spiel. Dieses startet folgenden Thread:

Java:
package paint;

public class Timer extends Thread
{
	final int fps = 33;
	MainFrame MainFrame;

	public Timer(MainFrame MainFrame)
	{
		this.MainFrame = MainFrame;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				long nowtime = System.currentTimeMillis();
				this.MainFrame.repaint();
				Thread.sleep(1000 / this.fps - (System.currentTimeMillis() - nowtime));
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}
}

Nur irgendwie schafft es der, immer meinen Lieblingskern auf 99 % auszulasten.
Dabei besteht das was er zeichnen soll bloß aus ein paar Classes die von einer Abstracten mit ein paar abstracten Methoden erben.
Also wirklich nichts weltbewegendes.
Ich habe es so, dass die paint des Frames immer eine neue Instanz einer Klasse erzeugt, welches je nach einer Variable, die bestimmt wo der Spieler sich gerade befindet, wieder neue Instanzen erzeugt die dann zeichnen. Kann es sein, dass das der Grund ist, also soll ich lieber am Anfang intialisieren und dann nur noch Methoden aufrufen? Oder hat das höchstwarscheinlich einen anderen Grund?
 
Also was du in dem try-Block machst sieht ziemlich wild aus.
1000/33 ergibt rund 30.
davon ziehst du im Prinzip zweimal eine sehr grosse Zahl ab.
Das Ergebnis ist negativ.
Ich weiss nicht genau was bei einem Sleep von negativen Werten passiert aber im Ernstfall wartet er 0 Millisekunden. Deshalb dann auch die hohe Prozessorlast.
Ich persönlich würde auch das repaint() vor den try-Block schreiben.
Versuch mal folgendes:
Code:
public void run()
{
tm = System.currentTimeMillis();
while (true)
{
repaint();
try
{
tm += 30;
Thread.sleep(Math.max(0, tm - System.currentTimeMillis);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
 
Zuletzt bearbeitet:
Wenn er eine negative Zeit warten soll gibt er mir durch das e.printStackTrace() nen Fehler aus und fahrt dann am Anfang der Schleife fort.
Nein, sollte eigendlich dort passen. Durch die Klammern sollte er zuerst eine kleine Zahl rausbekommen und die erst abziehen.

Wenn ich
Java:
long nowtime = System.currentTimeMillis();
this.MainFrame.repaint();
System.out.println(System.currentTimeMillis() - nowtime);
Thread.sleep(1000 / this.fps - (System.currentTimeMillis() - nowtime));
System.out.println(System.currentTimeMillis() - nowtime);
schreibe, kommt als Ausgabe in etwa
Code:
0
47
Also scheint ein Thread beim Aufruf einer void nicht zu warten. Man lernt nie aus. ^^
Der Timestamp sollte dazu da sein, dass er auf jeder Maschine etwa gleich schnell arbeitet. Mache ich auch in anderen Threads so.
 
Egal, trotzdem danke. ^^
Na ja, repaint ist ja eine void. Geplant war, dass er wenn er bei dem repaint falls er wartet und diese z. B. 100 ms braucht, diese am Ende abzieht damit er für den gesamten Schleifendurchlauf in etwa "1000/fps" Millisekunden braucht. Und wenn eine andere Maschine verwendet wird, die das ganze in 50 Sekunden schafft, sollte er eben 50 Sekunden länger als bei der anderen warten.

Ich habe mal das ganze Paint-Package hochgeladen.
MainFrame.java ist das Frame auf das eben gepaintet wird.
Timer.java ist der hier gepostete Thread.
PaintTypmenue.java ist (bzw. wird eigendlich erst) die Auswahl der Spielart.
PaintSingleplayerMenu.java ist wieder ein kleines Hauptmenü.
PaintIngame.java zeichnet, wie der Name schon sagt dem Spielinhalt.
PaintIngameMenu.java ist dann das Auswahlmenü in das man von der PaintIngame kommt.

Die letzten beiden sind noch nicht fertig, also nicht wundern. Wäre echt klasse (<- Java-Witz. ^^) wenn jemand dem Fehler finden würde.
 

Anhänge

Also, vielleicht bin ich ja nun komplett blöde, aber du machst in der MainFrame Klasse bei der Methode hier:

Java:
	public void paint(java.awt.Graphics g)
	{
		new Paint(g, this);
	}

immer ein new Paint() und in der Klasse werden auch wieder neue Objekte erzeugt. Wie oft wird paint denn da aufgerufen? Wenn du alle 30 ms neue Objekte erzeugst ist klar das die CPU durchdreht.

Mfg
Chriz
 
Ja, eben das dachte ich auch.
Nur ich habe schon in ähnlichen Projekten so gehandelt, und da (bzw. allgemein) hatte ich das Problem noch nie.

Habs aber mal trotzdem umgebaut. -> Anhang.

Das Problem scheint teilweiße in der Zeile
Java:
g.drawImage(mainframe.getMain().getRahmen(), 4, 23, mainframe);
und in der Schleife der neuen Methode
Code:
PaintIngame.drawTerrainAndUnits()
zu liegen. :confused:
 

Anhänge

Zurück