Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

05.10.2016, 16:21

XNA, C# Was kann man tun damit ein Spiel immer und überall gleich schnell läuft?

Ich möchte dass sich meine Spielfigur auf jedem Spielgerät(iPhone, Windows Phone,...) gleich schnell bewegt, auch wenn dir Framerate nicht auf allen Geräten dieselbe ist. Muss ich dafür die Beschleunigung/das Abbremsen meiner Spielfigur immer mit der GameTime multiplizieren?
Würde sich meine Spielfigur auf unterschiedlichen Geräten unterschiedlich schnell bewegen wenn ich die Beschleunigung nicht mit der GameTime multiplizieren würde?

1)Ohne GameTime:

C#-Quelltext

1
2
3
4
5
6
 protected override void Update(GameTime gameTime)
    {
        SpielfigurPosition = new Vector2(SpielfigurPosition.X * 1.2f, SpielfigurPosition.Y);

        base.Update(gameTime);
    }


2)Mit GameTime multipliziert:

C#-Quelltext

1
2
3
4
5
6
7
 protected override void Update(GameTime gameTime)
    {
        var delta = (float)gameTime.ElapsedGameTime.TotalSeconds;
        SpielfigurPosition = new Vector2(SpielfigurPosition.X + (delta * 1.2f), SpielfigurPosition.Y);

        base.Update(gameTime);
    }


Würde sich die Spielfigur auf unterschiedlichen Geräten unterschiedlich schnell bewegen wenn ich den Code-Block 1) verwenden würde?
Sollte man bei Geschwindigkeiten(z.B. der Spielfigur) immer den Code-Block 2) benutzen damit sich immer(auch bei unterschiedlicher Framerate) alles gleich schnell bewegt?

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

3

11.10.2016, 14:39

In meinem Spiel arbeite ich mit variablen Zeitschritten. Sollte ich die Framerate in meinem Fall trotzdem auf 30fps beim Spielstart festlegen oder braucht man das nicht wenn man mit variablen Zeitschritten arbeitet?
Wenn man die Framerate auf 30fps festlegt, beträgt die Framerate dann immer 30fps(egal welche Hardware man hat) oder ist die Framerate auf schwächeren Geräten trotzdem niedriger?

C#-Quelltext

1
2
Auf Windows Phone:
TargetElapsedTime = TimeSpan.FromTicks(333333); // Frames Per Second is 30

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

4

11.10.2016, 14:42

Wenn man die Framerate auf 30fps festlegt, beträgt die Framerate dann immer 30fps(egal welche Hardware man hat) oder ist die Framerate auf schwächeren Geräten trotzdem niedriger?


3 mal darfst du raten ;)
Wie soll denn ein System, dass eine Sekunde braucht, um einen Frame zu berechnen, auf 30 Frames pro Sekunde kommen?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

11.10.2016, 15:08

Ein Ansatz den man öfter sieht ist dass du deine Updatelogik in einem festen Zeitintervall berechnest, aber die Szene zeichnest sobald möglich. Beim Zeichnen kannst du theoretisch allerlei Interpolation durchführen. Der Pseudocode sieht in etwa so aus:

Quellcode

1
2
3
4
5
6
7
8
while(true) {
  aktuelleZeit += zeitSeitLetztemSchleifendurchlauf;
  while(aktuelleZeit >= zeitProFrame) {
    aktuelleZeit -= zeitProFrame;
    spielWeltUpdaten(zeitProFrame);
  }
  spielweltRendern();
}


Deinen update-Code schreibst du in abhängigkeit der übergebenen Zeit. Du kannst bei diesem Ansatz die Zeit pro Frame nachträglich verändern ohne dass sich deine Spielgeschwindigkeit verändert, behältst die Vorteile von einem Ansatz mit fester Zeit pro Frame dennoch und kannst wie gesagt theoretisch beim rendern die Zustände interpolieren. Diesen Ansatz kann man dann noch erweitern um zum Beispiel bei zu langen Renderzeiten render-Steps ausfallen zu lassen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

6

11.10.2016, 23:04

Warum übergibst du die Konstante "zeitProFrame" an spielWeltUpdaten?

C#-Quelltext

1
spielWeltUpdaten(zeitProFrame);

Ich verstehe nicht wo man diese Konstante noch brauchen könnte?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

7

11.10.2016, 23:13

Ich verstehe nicht wo man diese Konstante noch brauchen könnte?

Für deine Bewegung. Der Trick ist, ist die Variable in deinem Spiel konstant so kann der Compiler das normal weg optimieren. Entwickelst du dein Spiel jetzt aber zum Beispiel mit 60fps und denkst dir irgendwann hey, 30fps fände ich viel schöner, so musst du nur die Konstante anpassen.
Kannst das natürlich komplett anders machen. Der Pseudocode ist einfach nur ein Vorschlag.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

8

12.10.2016, 00:49

Ich bin mir nicht sicher ob ich das mit der Bewegung updaten richtig verstanden habe. Also einfach nur mit zeitProFrame multiplizieren um die Position eines Opjekts(z.B. Spielfigur) zu ändern. Ist das richtig so?

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
//Lege ich beim Spielstart fest.
float zeitProFrame = 0.2f;

In der Update Methode:
var zeitSeitLetztemSchleifendurchlauf = (float)gameTime.ElapsedGameTime.TotalSeconds;
while(true) {
  aktuelleZeit += zeitSeitLetztemSchleifendurchlauf;
  while(aktuelleZeit >= zeitProFrame) {
    aktuelleZeit -= zeitProFrame;
    spielWeltUpdaten(zeitProFrame);
  }
  spielweltRendern();
}


Bewegung der Spielfigur(Objekt) in spielWelt updaten:

C#-Quelltext

1
2
3
4
5
6
//Die Beschleunigung lege ich nur einmal beim Spielstart fest.
float Objekt.Beschleunigung = 5f;

Update Methode von spielWelt:
Objekt.Position = Objekt.Position + zeitProFrame * Objekt.Geschwindigkeit
Objekt.Geschwindigkeit = Objekt.Geschwindigkeit + zeitProFrame * Objekt.Beschleunigung

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

12.10.2016, 07:01

Wenn das Spiel länger läuft, dürfte das hier zum echten Problem werden: aktuelleZeit += zeitSeitLetztemSchleifendurchlauf
Einfach weil die aktuelle Zeit so groß wird, dass bei der Addition dank des Datentyps floats nichts mehr passiert:
15203 + 0.016 == 15203
Das heißt nach einer Stunde fängt das Game an zu stottern und nach 4 Stunden durchgehender Spielzeit bewegt sich da überhaupt nichts mehr. Bei mehr als 60FPS treten die Probleme entsprechend früher auf.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (12.10.2016, 07:15)


David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

10

12.10.2016, 07:12

Einfach weil die aktuelle Zeit so groß wird, dass bei der Addition dank des Datentyps floats nichts mehr passiert:
15203 + 0.016 == 15203

Ganz so schlimm ist es nicht. Dass die Zahlen gleich dargestellt werden, liegt an der im stdout-Stream eingestellten Präzision. Wenn du die hochsetzt oder mit printf ausgibst, sind die Zahlen unterschiedlich: http://ideone.com/nUwE3c
Bis die Addition wirklich keinen Unterschied mehr macht, dauert es etwas länger. Aber das Problem existiert natürlich.

Edit: Huch, jetzt hast du den Link zu deinem Code entfernt.

Um das Problem zu vermeiden, sollte man mit Ganzzahlen zählen.

Werbeanzeige