Was sind Ihre bevorzugten spielspezifischen Codierungsjuwelen? [geschlossen]
24
Ich beginne mit John Carmacks Fast Inverse Square Root in Quake III:
float Q_rsqrt(float number){long i;float x2, y;constfloat threehalfs =1.5F;
x2 = number *0.5F;
y = number;
i =*(long*)&y;
i =0x5f3759df-( i >>1);
y =*(float*)&i;
y = y *( threehalfs -( x2 * y * y ));return y;}
Es nimmt einen Wert an, konvertiert ihn in eine Proportion innerhalb eines Bereichs und skaliert ihn dann relativ zu einem anderen Bereich. Wie ein Doppelgänger.
Sie können es verwenden, um Dinge zu normalisieren:
Ich kann immer noch nicht glauben, wie oft ich den Satz von Pythagoras in meinem Spielcode verwendet habe. Für mich ist diese einfache Formel ein Juwel in der Spieleentwicklung.
Um ehrlich zu sein, wird die pythagoreische Mathematik im GANZEN Code des Spiels verwendet, insbesondere bei Engines wie Physikcode, Renderingcode und KI.
Nick Bedford
1
Wahr. Deshalb ist es ein Juwel. ;)
MrValdez
4
Eine interessante Variante ist, wenn Sie sich nur um die relativen Abstände kümmern . Dann können Sie den möglicherweise teuren sqrtAnruf überspringen und einfach berechnen distance2 = x^2 + y^2.
Mmyers
@mmyers - Eine weitere wunderbare Sache: Wenn Sie im x ^ 2-Raum arbeiten, ist die Entfernung nicht nur relativ.
Steven Evers
Vielen Dank, dass Sie das relative Distanzbit erwähnt haben. Ich habe viel zu viele unnötige Quadratwurzeloperationen gesehen, genauso wie Leute, die A * verwenden, wenn sie etwas weniger Genaues verwenden sollten.
Ricket
13
Der größte von mir las über das GameObject-System von Scott Bilas. Obwohl ich kein Datenbanksystem wie dieses verwende, habe ich dadurch keine 6-Ebenen-Vererbungsbäume erstellt und ein Komponentensystem erstellt, das viel einfacher zu verwalten und wiederzuverwenden ist.
Das verschachtelte "do-while" im "switch-case" lässt mich immer blinken. Auch 20 Jahre später ...
Andreas
1
-1. Ich mag das nicht. Es ist heute nicht sehr nützlich (Sie würden es memcpystattdessen verwenden, wenn andere Ihren Code lesen können sollen)
bobobobo
1
@JoeWreschnig warum nicht? Memcpy wird immer lesbarer, portabler und wahrscheinlich optimierter.
KaoD
1
@kaoD: Da memcpy nicht mit Duffs Gerät vergleichbar ist, spielt es keine Rolle, wie "lesbar, portabel und wahrscheinlich optimierter" es ist, wenn es nicht dasselbe tut! Moderne CPU-Pipelines werden wahrscheinlich besser ohne Duffs Gerät auskommen als mit ihm, da Verzweigungsvorhersage und Befehls-Caching vorhanden sind, aber das hat nichts damit zu tun memcpy.
7
Ein kleines C / C ++ - Snippet aus einem Spiel, an dem ich vor vielen Jahren mitgearbeitet habe:
(fill ?FillRect:DrawRect)(x, y, w, h, colour);
Bei meinem ersten Spiel musste ich auf mehr als 1 MB RAM zugreifen, und da es vor dem Start des Internets keine Dokumentation für XMS und EMS gab, die DOS-Apps für den Zugriff auf den zusätzlichen RAM verwendeten.
Also habe ich eine kleine 'Hintertür' benutzt, die im 386 in Bezug auf die Segmentregister vorkam. Normalerweise wurde die Adresse im Real-Modus so berechnet, seg*16+offdass Sie auf 1 MB beschränkt waren.
Sie können jedoch in den geschützten Modus wechseln, ein Segment für die Adresse 4 MB einrichten, zurückschalten und auf das gesamte Segment zugreifen, sofern Sie nicht in das Segmentregister geschrieben haben (was in Ordnung war, da DOS nur die 8086-Segmentregister verwendet hat) 4 MB als flacher Adressraum. Das Zurückschalten in den Real-Modus war notwendig, wenn Sie die DOS-Dienste verwenden wollten.
Du meinst mit 32-Bit Adressierungsmodi im Realmodus? (dh ein Adressgrößenpräfix erforderlich). Sind Sie sicher, dass es notwendig war, einen Segmentdeskriptor einzurichten, und dass das Segmentregister tatsächlich nicht als normales 16 * FS + verwendet wurde? Ich hätte nicht gedacht, dass Segmente im 16-Bit-Modus überhaupt Grenzen haben, nur die Basisadresse (16 * deren Wert), also könnten Sie FS nicht einfach auf etwas im 16-Bit-Modus setzen und [fs:esi]oder was auch immer verwenden, um auf etwas von Ihnen zuzugreifen wollte?
Peter Cordes
Ich habe das noch nicht ausprobiert oder keinen echten Code für den 16-Bit-Modus geschrieben, nur 32- und 64-Bit-asm, aber es klingt komisch. Hmm, aber plausibel. Moderne CPUs zwischenspeichern Segmente definitiv intern und laden diese Caches nur dann neu, wenn Sie in Segmentregs schreiben. Auf diese Weise wurde möglicherweise die Basisgrenze + für den geschützten Modus beibehalten (wenn dies tatsächlich der Fall war und Sie nicht nur die verwendeten) 4 MB ab 16 * FS).
Peter Cordes
5
Persönlich bin ich ein großer Fan des Mersenne-Twisters für vorhersagbare Zufallszahlen, insbesondere wenn Sie mehrere unterschiedlich gesetzte Instanzen von Rand erstellen müssen
Mersenne Twister ist in dem Sinne nett, dass es ein guter Zufallszahlengenerator ist, aber nicht besonders elegant oder cool (oder schnell oder einfach zu implementieren). Vielleicht möchten Sie sich dafür en.wikipedia.org/wiki/Rule_30 ansehen .
Dieser Link ist jetzt defekt, daher wäre es hilfreich, hier eine Erklärung zu finden.
11.
Vielen Dank. Er ist gegangen und hat seine Website wieder geändert. Ich habe den Link aktualisiert.
Anthony
4
Aus irgendeinem Grund unterschätzen die Leute oft die Macht von Designmustern in Spielen. Ich habe fast jedes einzelne GoF-Muster mit Erfolg auf Spiele angewendet.
Eines der Dinge, die ich an der Programmierung von Spielen mag, ist, mich von der GoF-Standardmethode der "Korrektheit" zu lösen und mich nur auf reine Geschwindigkeit zu konzentrieren! Trotzdem habe ich viele schlechte Implementierungen von MVC in Spielen gesehen, die mehr schaden als nützen.
Iain
Ich denke, Designmuster haben ihren Platz. In Spielen allerdings nicht so sehr.
Blissfreak
@blissfreak: Es gibt nichts Besonderes an der Spielprogrammierung, das es zu einer Art wildem Westen macht, in dem Muster nicht häufig sind. Sie sind lächerlich verbreitet und hier sind einige Beispiele.
Steven Evers
4
Math.atan2 () ist extrem nützlich (zusammen mit allem was dazugehört).
Es ist, meine Güte! Ich habe viel 3D gemacht und es nie wirklich gebraucht.
Skizz
+1, es ist der einzige Weg, um von den x + y-Vektorkomponenten in die Bogenmaßrichtung zu gelangen.
RCIX,
1
@RCIX: Mein Punkt ist, dass diese Transformation nicht notwendig ist, dh (x, y) -> Winkel, es gibt eine Vektorlösung für jedes Winkelproblem.
Skizz
6
Ich würde eine nackte Standardbibliotheksfunktion nicht wirklich als "Juwel" bezeichnen.
1
@Skizz: Vielleicht für 3d, aber ich kenne keinen anderen Weg, um einen normalisierten Vektor zu nehmen und einen Richtungswert im Bogenmaß zu extrahieren. Welches als viel Wert in 2D-Spielen.
RCIX
3
Um das obige pythagoreische Juwel zu ergänzen ... Ich sage den Leuten immer, dass sie für die 3D-Programmierung nur wissen müssen:
- a ^ 2 + b ^ 2 = c ^ 2
- soscastoa (sin = Gegenseite / geneigte Seite, cos = angehängte Seite / geneigte Seite, tan = gegenüberliegende Seite / befestigte Seite)
- a. b = | a | * | b | * cos alpha
- a * b = | a | * | b | * sin alpha * unit vector
Es kann so ziemlich jedes 3D- (oder 2D-) Problem lösen, auf das Sie bei der Spieleentwicklung stoßen - 4 Regeln. Klar, es gibt schönere Wege, aber das kann sie alle lösen - ich sollte wissen, dass ich ein Hack bin, der eine Karriere auf sie gründet.
re: soscastoa Ich denke, die meisten Leute kennen das als sohcahtoa (Ersetzen der "geneigten Seite" durch die spezifischere, wenn auch weniger bekannte "Hypotenuse"). Fließt leichter von der Zunge, und ich denke damit leichter zu merken.
Asmor
1
Ich bevorzuge immer "Der alte Araber saß auf seinem Kamel und heulte", da die Sekundarschule (im Highschool-Alter) in meinem Gehirn eingeprägt ist.
George Duckett
Es gibt auch " S ome O ld H ippy C ame A nd H ad T riss O n A cid"
blissfreak
3
Einer meiner Favoriten ist die Assembler-Version von 'Life' und die gesamte Beschreibung der Optimierung in " The Zen of Code Optimization" von Michael Abrash.
Ich würde jedes seiner Bücher jedem empfehlen, der nach Codierungsedelsteinen sucht.
Antworten:
mapValue-Funktion:
Es nimmt einen Wert an, konvertiert ihn in eine Proportion innerhalb eines Bereichs und skaliert ihn dann relativ zu einem anderen Bereich. Wie ein Doppelgänger.
Sie können es verwenden, um Dinge zu normalisieren:
Oder Sie können von einem Bereich in einen anderen konvertieren:
Beachten Sie im zweiten Beispiel, dass der Out-Bereich eine andere Reihenfolge als der In-Bereich hat.
Es sieht nicht nach viel aus, aber ich benutze diesen kleinen Kerl überall.
quelle
Ich kann immer noch nicht glauben, wie oft ich den Satz von Pythagoras in meinem Spielcode verwendet habe. Für mich ist diese einfache Formel ein Juwel in der Spieleentwicklung.
(Quelle: mathurl.com )
oder
(Quelle: mathurl.com )
und wenn nur der relative Abstand von Bedeutung ist, kann er ohne teure Quadratwurzeloperation verwendet werden
(Quelle: mathurl.com )
quelle
sqrt
Anruf überspringen und einfach berechnendistance2 = x^2 + y^2
.Der größte von mir las über das GameObject-System von Scott Bilas. Obwohl ich kein Datenbanksystem wie dieses verwende, habe ich dadurch keine 6-Ebenen-Vererbungsbäume erstellt und ein Komponentensystem erstellt, das viel einfacher zu verwalten und wiederzuverwenden ist.
quelle
Ich muss mit Duffs Gerät gehen . Es war der erste Codeblock, der mir buchstäblich den Kiefer fallen ließ. "Das kannst du machen?!?"
quelle
memcpy
stattdessen verwenden, wenn andere Ihren Code lesen können sollen)memcpy
.Ein kleines C / C ++ - Snippet aus einem Spiel, an dem ich vor vielen Jahren mitgearbeitet habe:
Bei meinem ersten Spiel musste ich auf mehr als 1 MB RAM zugreifen, und da es vor dem Start des Internets keine Dokumentation für XMS und EMS gab, die DOS-Apps für den Zugriff auf den zusätzlichen RAM verwendeten.
Also habe ich eine kleine 'Hintertür' benutzt, die im 386 in Bezug auf die Segmentregister vorkam. Normalerweise wurde die Adresse im Real-Modus so berechnet,
seg*16+off
dass Sie auf 1 MB beschränkt waren.Sie können jedoch in den geschützten Modus wechseln, ein Segment für die Adresse 4 MB einrichten, zurückschalten und auf das gesamte Segment zugreifen, sofern Sie nicht in das Segmentregister geschrieben haben (was in Ordnung war, da DOS nur die 8086-Segmentregister verwendet hat) 4 MB als flacher Adressraum. Das Zurückschalten in den Real-Modus war notwendig, wenn Sie die DOS-Dienste verwenden wollten.
Es gab auch nicht viele DPMI-Extender.
quelle
[fs:esi]
oder was auch immer verwenden, um auf etwas von Ihnen zuzugreifen wollte?Persönlich bin ich ein großer Fan des Mersenne-Twisters für vorhersagbare Zufallszahlen, insbesondere wenn Sie mehrere unterschiedlich gesetzte Instanzen von Rand erstellen müssen
http://en.wikipedia.org/wiki/Mersenne_twister
quelle
Hier ist einer von Chris Crawford (und anscheinend von Atari verwendet), den er "A Graphics Trick" nennt:
Lesen Sie den vollständigen Artikel für eine Erklärung.
quelle
Aus irgendeinem Grund unterschätzen die Leute oft die Macht von Designmustern in Spielen. Ich habe fast jedes einzelne GoF-Muster mit Erfolg auf Spiele angewendet.
quelle
Math.atan2 () ist extrem nützlich (zusammen mit allem was dazugehört).
quelle
Um das obige pythagoreische Juwel zu ergänzen ...
Ich sage den Leuten immer, dass sie für die 3D-Programmierung nur wissen müssen:
- a ^ 2 + b ^ 2 = c ^ 2
- soscastoa (sin = Gegenseite / geneigte Seite, cos = angehängte Seite / geneigte Seite, tan = gegenüberliegende Seite / befestigte Seite)
- a. b = | a | * | b | * cos alpha
- a * b = | a | * | b | * sin alpha * unit vector
Es kann so ziemlich jedes 3D- (oder 2D-) Problem lösen, auf das Sie bei der Spieleentwicklung stoßen - 4 Regeln.
Klar, es gibt schönere Wege, aber das kann sie alle lösen - ich sollte wissen, dass ich ein Hack bin, der eine Karriere auf sie gründet.
quelle
Einer meiner Favoriten ist die Assembler-Version von 'Life' und die gesamte Beschreibung der Optimierung in " The Zen of Code Optimization" von Michael Abrash.
Ich würde jedes seiner Bücher jedem empfehlen, der nach Codierungsedelsteinen sucht.
quelle