Was ist "Game Logic Code"?

50

Ich verwende C # / XNA und wurde einige Male angewiesen, Update-Code nicht mit Draw-Code zu mischen - und ich bin mir sicher, dass ich es nicht bin! Aber könnte jemand bitte beschreiben, was genau "Logikcode" ist?

Wie hier zu sehen: http://blogs.msdn.com/b/shawnhar/archive/2007/07/25/understanding-gametime.aspx

[...] stellen Sie sicher, dass Sie Ihre gesamte Spiellogik in die Update-Methode (nicht in Draw!) einfügen und alles mit einer schönen konstanten Geschwindigkeit läuft.

Ich frage dies, da die Geschwindigkeit meines Spiels relativ zur FPS schwankt. Langsame FPS entsprechen sich langsam bewegenden Objekten und umgekehrt. Und ja, ich füge den erwarteten position += speed * (float)gt.ElapsedGameTime.TotalSeconds;Code ein.

Dies ist wahrscheinlich eine große Anfängerfrage, aber ich möchte nur die Definition dieser Frage absolut klarstellen.

Schüchterner Kerl
quelle
Ich denke du meintest position = speed * ...TotalSeconds. Beachten Sie, dass es =nicht ist +=. Wenn es +=so wäre, wie Sie es eingegeben haben, würde Ihre Position fast augenblicklich vom Bildschirm verschwinden.
DrZ214
Ich habe Code, der aussieht wie "Position + = Richtung * Geschwindigkeit * ... TotalSeconds" und das funktioniert sehr gut. Ich habe vielleicht etwas falsch geschrieben, aber position = speed würde es jedem Update zuweisen. Ihr Weg mag funktionieren, aber ich habe meinen Code so. (Beachten Sie, dass die Richtung normalisiert ist)
Shyy Guy
Ich dachte, es gt.ElapsedGameTime.TotalSecondsist die Anzahl der Sekunden, die seit dem Starten des Programms (des Spiels) vergangen sind. Wenn Sie Ihre Geschwindigkeit damit multiplizieren, ist Ihre Geschwindigkeit nach 5 Sekunden fünfmal höher (mit Ausnahme des Sonderfalls, bei dem die Geschwindigkeit auf 0 gesetzt ist). Ich bin mir nicht sicher, was Sie sonst noch haben könnten, aber ich bin fasziniert.
DrZ214
1
Aha, es ist seit dem letzten Update. gamedev.stackexchange.com/questions/67968/...
shyy Guy
2
Faszinierend hätte ich das nie gedacht. Ich brauchte so etwas nie in Sekunden, weil ich persönlich meine eigene Variable benutze, die heißt, iiidass ich jedes Update manuell inkrementiere, weil ich es nicht in Sekunden will, ich will Schritte oder Frames. Ich kann jedoch erkennen, dass Ihr Weg ein gültiger Weg ist, um Dinge weich zu kodieren.
DrZ214

Antworten:

102

Verändert es den Zustand Ihrer Spielwelt? Es ist ein Logikcode.

Zeigt es den Stand der Spielwelt an? Es rendert Code.

Nils Ole Timm
quelle
Ich werde meinen Code durchsehen, um 100% sicher zu sein. Gute Erklärung, danke.
Shyy Guy
38
Kann es Eingaben verarbeiten? Sein Controller-Code. Trennen Sie die Steuerung von der Logik, damit Sie dieselbe Logik mit verschiedenen Arten von Steuerelementen verwenden können. ZB ein FPSInputController + CharacterMotor vs. AIInputController + CharacterMotor vs. NetworkInputController (zB andere Spieler in einer Multiplayer-Instanz) + CharacterMotor. Dem Motor (Logikcode) ist es egal, wie er die Anweisungen erhält, nur dass sie geliefert werden (diese Art der Entkopplung ermöglicht einen einfachen Übergang vom Spieler zum KI-Bot (denke Left 4 Dead und Idle-Spieler) und zurück, unter anderem).
Draco18s
10
Draco bringt einen guten Punkt vor. Es gibt viele verschiedene Unterteilungen, die Sie in den Code einfügen können. Nils 'Unterteilung ist das, was ich als archetypische Unterteilung zwischen Logik und Rendering bezeichnen würde, aber es gibt noch viele andere Ebenen, die Sie sehen werden. Der eigentliche Grund, sie in Ebenen aufzuteilen, besteht darin, dass jede Ebene aus ähnlichen Aktionen besteht, für die ein ähnlicher Codestil mit ähnlichen Anforderungen erforderlich ist. In vielen Spielen kann es beispielsweise passieren, dass die Spielelogik 2 oder 3 Frames benötigt. Wenn Sie jedoch nicht jedes Frame rendern, wird das Auge des Benutzers schnell darauf aufmerksam.
Cort Ammon
Wenn Sie sie getrennt halten, können Sie Ihre Anforderungen besser verwalten, wenn sie zu einer Belastungsquelle werden.
Cort Ammon
6
Und denken Sie daran, dass zu viel MVC das Crawling verlangsamen kann. Streben Sie daher immer nach einem Gleichgewicht zwischen Wartbarkeit und Optimierung. Optimieren Sie jedoch nicht zu früh, es sei denn, Sie sind sich absolut sicher, was Sie tun. Und denken Sie daran, Sie können immer umgestalten. Und ... Äh, mache viele Spiele und lerne aus deinen Fehlern.
Maurycy
24

Ihre Trennung ist korrekt, wenn:

  • Wenn Sie Draw () mehrmals hintereinander aufrufen, ohne dass sich Aufrufe von Update () dazwischen befinden, würde dies niemals zu sichtbaren Änderungen zwischen den Aufrufen führen.
  • Wenn Sie Update () mehrmals hintereinander aufrufen, ohne dass Draw () dazwischengeschaltet ist, wird das Spiel mit ausgeschaltetem Bildschirm gespielt: Alles läuft perfekt und gleichmäßig ab, Sie können es einfach nicht sehen.
Thomas
quelle
5
Richtig geschrieben, Draw()kann es sein, dass im Laufe der Zeit unterschiedliche Bilder gezeichnet werden. Beispielsweise können sich Frames von animierten Sprites weiterhin ändern. Objekte können sich auch weiterhin visuell vorwärts bewegen, wenn beim Rendern von Code ein allgemeiner Trick verwendet wird und die velocity * time since last update / period of updatesichtbare Position von Objekten vergrößert wird (während ihre tatsächliche Position unverändert bleibt).
HolyBlackCat
2
iffwas bedeutet, wenn und nur wenn?
BalinKingOfMoria
3
@HolyBlackCat: Das ist fraglich. Was ist, wenn ich Grafiken anhalten möchte? Was passiert, wenn die Frames der Animation das Spiel beeinflussen (Angriffsanimationen, die Hitboxen entsprechen, usw.)? Visuelle Interpolation impliziert immer noch, dass "Zeit" (wie in der Delta-Zeit des Spiels) vergeht, aber wenn die Zeit vergeht und Sie dies nicht tun, Updatewas kommt sonst noch aus der Synchronisation heraus? Fehlende Player-Eingaben, nicht verarbeitete Netzwerkereignisse usw.? Das Spiel sollte von einer einzelnen Uhr gesteuert werden, mit festen "Häkchen" für die von dieser Uhr abgeleitete Spiellogik oder -physik und abgeleitetem Grafikstatus, der auch von derselben Uhr gesteuert wird.
Sean Middleditch
@ SeanMiddleditch Ich stimme zu, fast immer kann man so schreiben Draw(), dass es immer das gleiche Bild zeichnet, wenn es mehrmals hintereinander aufgerufen wird. Das sollte man wenn möglich machen. Es gibt jedoch Fälle, in denen Sie nicht wissen, mit welcher Frequenz Sie Draw()angerufen werden. Zum Beispiel, wenn Sie volle Unterstützung (tatsächlich 120 FPS) für neue 120-Hz-Monitore wünschen und vsync einschalten möchten. What if I want to pause graphics?Dann übergeben Sie 0 anstelle der tatsächlichen Deltazeit an die Draw().
HolyBlackCat
2
@HolyBlackCat: Nichts, woran ich mich gewöhnt hätte, würde die Verwendung von 120-Hz-Rendering ausschließen. Ich empfehle absolut keine feste Ziehungsrate. das ist nur amateurhaft. Es sollte eine globale Spieluhr geben, deren Delta in Form von Render-Frames gemessen wird, die in den Akkumulationswert für den Spiellogik-Tick mit fester Rate eingehen. Diese globale Uhr steuert Grafiken, einschließlich Interpolation. Sie können Grafiken anhalten, indem Sie die Taktskala auf einstellen 0. Sie können hierarchische Uhren verwenden, sodass z. B. die Benutzeroberfläche weiterhin ausgeführt und animiert wird, während die Zeicheninterpolation ebenfalls sehr einfach gestoppt wird.
Sean Middleditch
7

Der Punkt hier ist die Trennung von Modell-Dingen, die nicht das Modell sind.

Die Spielelogik ist das Modell, auf das in Bezug genommen wird

Dies sind alles unterschiedliche, verwandte Softwarearchitekturmuster. Aber in jedem Fall ist das Modell dasselbe, es ist die wahre Logik und der wahre Zustand.

Bei der Erstellung von Unternehmenssoftware wird diese manchmal als Geschäftslogik bezeichnet und in einigen Unternehmensrichtlinien kodiert. Wenn Sie zum Beispiel etwas für eine Bank codieren, um Kreditkartenrechnungen zu berechnen, ist es Teil der Geschäftslogik, dass jemand keine Zinsen zahlen muss, wenn er seine Schulden in weniger als 30 Tagen begleicht Modell. Es lebt beispielsweise nicht auf einer der Anzeigeebenen. Der Code zum Drucken einer Rechnung bearbeitet beispielsweise den Text nicht basierend auf deren Aktionen. Dieses Beispiel zeigt vielleicht, warum Sie Ihren Code auf diese Weise organisieren möchten.

Ähnliches gilt für die Spielelogik.

Stellen Sie sich vor, Ihr Spiel wurde irgendwann auf eine andere Konsole portiert. Es könnte hilfreich sein, sich etwas anderes als Ihr aktuelles Ziel vorzustellen. Wenn Sie beispielsweise mit einem Gamepad / Controller auf etwas zielen, können Sie sich vorstellen, dass Ihr Spiel auf ein Touchscreen-Tablet portiert wird. Die Spielelogik ist der Teil des Codes, der sich beim Portieren nicht ändert.

Wenn Ihr Spiel so etwas wie ein militärisches Strategiespiel wäre, stellen Sie sich vor, es würde zum komplexesten Brettspiel der Welt. Die Spiellogik besteht aus den Codeabschnitten, die den Zeilen im Regelbuch direkt entsprechen. (Nicht alle Zeilen im Regelbuch, nicht die über bewegte Teile, aber einige.)

Die Spiellogik ist das, was sich nie ändert, egal in welcher Form.

Lyndon White
quelle