Laden...

[MDX] Die richtige "Taktung"

Erstellt von Floste vor 15 Jahren Letzter Beitrag vor 15 Jahren 907 Views
Floste Themenstarter:in
1.130 Beiträge seit 2007
vor 15 Jahren
[MDX] Die richtige "Taktung"

Hallo, ich hoffe,dass ich im richtigen Forum gelandet bin.
Ich versuche ein spiel mit MDX zu schreiben. Ich habe schon eine Funktion geschrieben, die den Spielablauf weiterberechnet und zurückgiebt, in wie viel ms sie wieder aufgerufen werden will (oder -1 wenn nichts weiter ansteht und auf benutzereingaben gewartet wird.)

Momentan Rufe ich die Methode bei Benutzereingaben solange in einer Schleife auf, bis sie -1 zurückgibt. Danach wird gerendert. Allerdings kann ich so natürlich keine Animationen einbauen und der Spielablauf ist sprunghaft.

Wie "takte" ich mein Programm, sodass die Rendermethode in gleichmäßigen Abständen und die Berechnemethode in den Abständen, die sie zurückgibt aufgerufen wird?
Mehrere Threads will ich wenn irgendwie möglich vermeiden. Außerdem will ich den Prozessor so wenig wie möglich auslasten (also keine Warteschleife) und man soll die Framerate eistellen können.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

N
335 Beiträge seit 2006
vor 15 Jahren

Hallo floste,

Nach meinem Verständnis funktioniert das in aller Regel etwas anders:
Normalerweise arbeitet die Spiellogik mit der im letzten Frame vergangenen Zeit.
Du hast eine Hauptschleife, in der du dir zu Beginn einen Timestamp holst und am Ende die Differenz aus dem gemerkten Timestamp und dem aktuellen bildest.
Mit dieser Zeitdifferenz kannst du dann arbeiten. So benötigst du keine Framebremse (Thread warten lassen).
Die Framerate kann man so allerdings nicht ohne weiteres einstellen. Das wird nicht ohne Warteschleife / Framebremse gehen (und das wolltest du ja vermeiden).

In Code sieht das etwa so aus:


private void MainLoop()
{
	double elapsed = 0;
	double lastTime = 0;
	bool runs = true;

	while (runs)
	{
		lastTime = GetTickCount(); // Lieber QueryPerformanceCounter
		
		HandleUserInput(elapsed);
		CalculateEntities(elapsed);
		Render(elapsed); // Für Animationen
		
		elapsed = GetTickCount() - lastTime;
	}
}

private void CalculateEntities(double elapsed)
{
	foreach(Entity e in _entitiesList)
	{
		// Position updaten
		// Strecke = Geschwindigkeit * Zeit
		// Position und Velocity sind Vektoren
		e.Position += e.Velocity * elapsed;
	}
}

Die Zeitabstände sind so nicht gleich und eben das ist der Trick: Das Spiel läuft rein optisch auf verschiedenen Systemen gleich schnell.
Bei kleiner Framerate bewegen sich die Objekte mehr (vergangene Zeit ist hoch) und bei großer Framerate bewegen sie sich nur um kleine Stücke (vergangene Zeit ist klein). Im gleichen Zeitraum, haben sie sich auf beiden Systemen um die gleiche Strecke bewegt.
Natürlich machen die Systeme in diesem Zeitfenster unterschiedlich viele Frames - das wird in Netzwerkspielen z.B. zum Problem (-> Synchronisierung).

Mfg NeuroCoder

C
401 Beiträge seit 2007
vor 15 Jahren

Gibt es einen besonderen Grund, warum du mehrere Threads vermeiden möchtest? Imho machen Threads die ganze Sache um einiges leichter und in .Net sind die ja auch recht einfach zu verwenden.