Framerate-Einbrüche durch Synchronisation

Irreparabel

Aktives Mitglied
Heyho,

nachdem ich mir ein paar Ideen aus dem Tutorial von Quaxli (ein dickes Danke an dieser Stelle ;)) geholt habe, wollte ich dann auch mal ein Spiel programmieren, ein 2D Sidescroller um genau zu sein.
Bisher hat auch alles prima funktioniert, gestern habe ich dann das Scrollen implementiert was auch funktioniert, nur leider kommt es während des Scrollens oft zu kleinen Spalten zwischen den Objekten.
Der Grund ist mir klar, da die paint Methode (Applet) nicht alle Objekte mit der neuen Position zeichnet, darum habe ich mithilfe der Collection in der sich die ganzen Objekte befinden die Threads synchronisiert, was jedoch zu den krassen Framerate-Einbrüchen führte. Jetzt sieht das ganze zwar schicker aus und die Spalten bleiben aus, jedoch ist die Framerate von 90-100 fps auf 50-60 fps gefallen und das schon bei ~10 Objekten in der Collection, bei mehr Objekten sinkt es natürlich weiterhin. Darum hoffe ich jetzt, dass es hier eventuell Leute gibt, die schon Mal das selbe Problem hatten und eine Lösung gefunden haben, da ich bezüglich des Problems ideenlos bin. :(
Falls es hilft, hier mal Auszüge aus der paint Methode und dem Scrollen:
Java:
synchronized(actors) {
	for (Actor actor : actors) {
		actor.drawActor(buffgraphics);
	}
}
Ein Objekt zu zeichnen dauert etwa 1.5-2ms
Java:
synchronized(actors) {
	for (Actor actor : actors) {
		if (player.x < 200) {
			actor.x++;
		}
		if (player.x + player.width > 500) {
			actor.x--;
		}
		if (player.y < 100) {
			actor.y++;
		}
		if (player.y + player.height > 300) {
			actor.y--;
		}
	}
}
 
Zuletzt bearbeitet von einem Moderator:

dayaftereh

Top Contributor
Also ich weiß ja nicht wie du das angehst! ich würde das so machen, also meine grund-idee für das spiel! Meinem Spieler Objekt eine Position zuweißen playerX & playerY. So und dan würde ich meine Spiel Feld einfach als Mega Universum sehen, und einen Camera Bereich Festlegen, am besten als Rectangel! in dem immer meine Spieler ist. Wenn jetzt meine Spieler sich nach vorbewegt, ziegt die Kamera einfach mit sodas meine Spieler immer in der Mitte ist! Wenn ich die Objekte jetzt zeichne, dan schaue ich erstmal ob sie in meinem Camera Bereich sind, wenn nicht dann vergessen. Mann kan sich das so vorstellen ich beobachte eine Armeise zur eine Luppe. die Luppe ist meine Kamera Bereich und die Armeise meine Spiel Figur. So ich kann immer nur den bericht von der Luppe sehen, wenn jetzt ein stein kommt, kann ich ihn nur sehen wenn er in der Luppe auf taucht, kommt mir eine armeise engegen und betritt meinen Luppen bereich, dann muss ich sie auf meine Luppe zeichen. mach einfach jedem Objekt eine Update Methode und eine Zeichne methode, bei update gibst du das delay der letzten runde mit und beim der Zeichne Methode das Graphic objekt ( auch beim spieler) dan rufst du für jedes Objekt update und dan repaint auf. in der update methode, berechnest du die neue position von dem Objekt in abhänigkeit vom speed und der richtung. wenn du das gemacht hast berechnest du die Screen Position in relation zum Spieler und seinem Camera bereich. jetzt rufst du repaint auf und zeichnest einfach alle objekt mit ihren screen positionen.Wenn eine objekt noch nicht in einer Camera berich ist, dann ist die ScreenPositon eh nicht auf dem Panel, und es wird ins nevahner gezeichnet!Ich würde ints für x und y nehmen, da musst du dan auch nis synchronized, nur wenn du obejtze aus der list löscht, nutzt da für einfach eine CopyAndWriteList! muss einfach nix synchronized.
 
S

SlaterB

Gast
mathematischer Hinweis nebenbei:
> Ein Objekt zu zeichnen dauert etwa 1.5-2ms

macht maximal 666 Zeichnungen pro Sekunde, bei 10 Zeichnungen pro Frame wären optimal nicht mehr 67 fps möglich
 

Irreparabel

Aktives Mitglied
@dayaftereh
Nur das zu zeichnen was auch in dem Bereich ist habe ich bereits versucht, jedoch kommt es ja auch vor dass sich mal mehr und mal weniger Objekte im Sichtbereich befinden, da schwanken die fps dann sehr und es wirkt unflüssig.

@SlaterB
Naja, eben doch:
Da bisher die paint Methode unabhängig von der Spielschleife gearbeitet hat, bis darauf, dass sie am Ende aufgerufen wird und dann nicht mehr auf dem gleichen Thread arbeitet, waren 90-100 fps in der Tat möglich.
Nachdem aber an der Stelle synchronisiert wird muss in der paint Methode gewartet werden, da tritt deine Rechnung dann wohl in Kraft (sofern ich dich jetzt richtig verstanden habe).
 

dayaftereh

Top Contributor
Wie viel threads Hast du den am Laufen, normal doch nur zwei, den GameLoop Therade und den EventDispatcher-Therad.sagen wir mal wir haben 100 objete und um die Position zu berechnen mache ich 10 operationen (addition, multi, etc) das dürchte geradem 1 - 5 ms dauern! Ich weiß nicht warum du synchronized machen willst! nutze doch einfach CopyOnWriteArrayList
 

Irreparabel

Aktives Mitglied
Genau, 2 Threads, den der Spielschleife und der EDT.
Synchronisieren möchte ich, damit nicht auf dem EDT gezeichnet wird während die Spielschleife noch die Positionen errechnet, denn genau das führt momentan zu den Spalten zwischen den gezeichneten Objekten...
Die CopyOnWriteArrayList ist übrigens schon drinne, aber ändert überhaupt nichts an meinem Problem...
 

dayaftereh

Top Contributor
also bei 100 Frps, ist es doch egahl on die Positionen berechnung hinter her ist,ich meine einfach 5 ms! ich glaube du berechnet einfach zu viel, schau mal wie lange deine berechnung von den Positionen dauer.wie lange der repaint dauer! kannst du deine Code mal als sip mir schicken oder so?
 

dayaftereh

Top Contributor
Also ich habe mal die Applet Größe auf 800x800 gemacht und habe es 10 mal gurchlaufen lassen mit scpringen von rechts nach links und dem ganzen scrollen, mein niedrigster frame ist 87 und mein höchst 100, das liegt daran das du halt immer feste 10 schläfst. du müsstest einfach schauen wie lange dein durchlauf gedauert hat und das von deine 10 am ziehen! so das du konstant 100 fps hast. wenn sie dan weg berchen, dann ist was faul! ich kann dir nacher mal ne Klasse bereistellen wo so was eingebaut ist!
 

Irreparabel

Aktives Mitglied
Ehm, das ist jetzt aber auch der Code ohne Synchronisation, der sollte stabil(er) laufen. ;)
Aber beweg dich mal ein bisschen dann sollte dir auffallen, dass zwischen den Blöcken ab und zu die Risse/Spalten entstehen.
 

dayaftereh

Top Contributor
Also bei mir leif es einband frei, mir ist nicht aufgefallen das die Blöcke mal wo anderst sind, bei mir ist der Block immer einband frei nach unten gefallen! und die anderen sind auf die Position gefahren!

Ich habe das mit meine FPS so gemacht, damit sie einfach immer konnstand sind, hier mal meine Hilfs Klassen:

Klasse FPSCounter.ava
Java:
public class FPSCounter {

	private long lastCount;
	private int currentFPS, frameCount;

	public FPSCounter() {
	}

	public void refresh() {
		this.frameCount = 0;
		this.lastCount = System.currentTimeMillis();
	}

	public void calculateFPS() {
		this.frameCount++;
		if (System.currentTimeMillis() - this.lastCount > 1000) {
			this.lastCount = System.currentTimeMillis();
			this.currentFPS = this.frameCount;
			this.frameCount = 0;
		}
	}

	public int getCurrentFPS() {
		return this.currentFPS;
	}

}

Die Klasse SystemTimer.java
Java:
public class SystemTimer {

	private boolean running;

	private int fps = 100;
	private long msDelay;
	private long start, end, timeDiff, sleepTime;
	private long overSleepTime;

	private FPSCounter fpsCounter;

	public SystemTimer() {
		this.fpsCounter = new FPSCounter();
	}

	public int getCurrentFPS() {
		return this.fpsCounter.getCurrentFPS();
	}

	public int getFPS() {
		return this.fps;
	}

	public long getTime() {
		return System.currentTimeMillis();
	}

	public boolean isRunning() {
		return this.running;
	}

	public void refresh() {
		this.start = System.currentTimeMillis();
		this.overSleepTime = 0;
	}

	public void setFPS(int fps) {
		if (this.fps == fps) {
			return;
		}
		this.fps = fps;

		if (this.running) {
			this.startTimer();
		}
	}

	public long sleep() {
		this.end = System.currentTimeMillis();

		this.timeDiff = this.end - this.start;
		this.sleepTime = (this.msDelay - this.timeDiff) - this.overSleepTime;

		if (this.sleepTime > 0) {
			try {
				Thread.sleep(this.sleepTime);
			} catch (InterruptedException e) {
			}

			this.overSleepTime = (System.currentTimeMillis() - this.end) - this.sleepTime;

		} else {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
			}
			this.overSleepTime = 0;
		}

		this.fpsCounter.calculateFPS();

		long end = System.currentTimeMillis();
		long elapsedTime = end - this.start;
		this.start = end;

		return elapsedTime;
	}

	public void startTimer() {
		if (this.running) {
			this.stopTimer();
		}
		this.running = true;

		this.msDelay = 1000 / this.fps;
		this.refresh();

		this.fpsCounter.refresh();
	}

	public void stopTimer() {
		this.running = false;
	}

}

Und nutzen Habe ich sie genutz um immer zu schlafen und den Delay zurüuck zu bekommen führ die bewegung der Objekte:
Java:
// Erzugen des Timers
SystemTimer timer = new SystemTimer();
// Anzahl der FPS
timer.setFPS(100);
timer.startTimer();
timer.refresh();
// ....
// im GameLoop
// Schläft immer so das man 100 fps bekommt und gibt das Delay zurück
long delay= timer.sleep();
 

Irreparabel

Aktives Mitglied
Danke, die Klassen werde ich mir gleich mal anschauen.^^
Damit das mit den Spalten mal stärker auffällt, in der init() Methode in Main, änder map = "start" mal in map = "zweite", und fall nach rechts unten/links unten, dann sollte es auch dir auffallen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G Framerate anpassen Spiele- und Multimedia-Programmierung 3
P Zahlenwert durch Methode ersetzen Spiele- und Multimedia-Programmierung 1
D Iterieren durch einen Ordner mit Audiodateien und verketten eine andere Audiodatei Spiele- und Multimedia-Programmierung 17
A Spielfelder erstellen mit Jogl Java durch ein Koordinaten Array Spiele- und Multimedia-Programmierung 1
R Durch String Platform Game erstellen Spiele- und Multimedia-Programmierung 8
lord239123 JMonkey Schatten werden durch Terrain hindurch angezeigt Spiele- und Multimedia-Programmierung 1
R Mp3 Rating (POPM) durch JAudioTagger? Spiele- und Multimedia-Programmierung 2
M Objekte verschwinden durch Explosion Spiele- und Multimedia-Programmierung 2
B j3d Kamera Rotation durch Tastendruck Spiele- und Multimedia-Programmierung 12
E [JAVA3D] Schattenstrich durch die Szene Spiele- und Multimedia-Programmierung 4
N Zufallserzeugung durch KI Spiele- und Multimedia-Programmierung 23
H Grafik verschwindet durch Größenveränderung von GridBag Spiele- und Multimedia-Programmierung 5
S Hilfe: Ich sehe durch die ganze Api's nicht mehr durch! Spiele- und Multimedia-Programmierung 15
Fu3L Extreme Prozessorauslastung durch Hintergrundbild Spiele- und Multimedia-Programmierung 5
B Animation durch Button auslösen Spiele- und Multimedia-Programmierung 2
D Polygonsize durch das umliegende Reckteck verändern inJava2D Spiele- und Multimedia-Programmierung 6
S Fehlerhafte Darstellung durch Transparenz? Spiele- und Multimedia-Programmierung 8
A durch Objekte hindurchzoomen Spiele- und Multimedia-Programmierung 2
masta // thomas Kollisionsabfrage - inspiriert durch "pixelgenaue Kolli Spiele- und Multimedia-Programmierung 13
E Durch Klick auf den JButton will ich die Farbe ändern? Spiele- und Multimedia-Programmierung 8
R Enorme Leistungseinbußen durch Alphakanäle Spiele- und Multimedia-Programmierung 3

Ähnliche Java Themen

Neue Themen


Oben