In diesem
Kommentar rĂŒhmte ich mich, ein Programm geschrieben zu haben, das in zweihundert Codezeilen einen âanstĂ€ndig aussehendenâ Wald erstellt. Leider stellte sich heraus, dass die RealitĂ€t etwas gröĂer war - die ausgegrabenen Quellen enthalten ungefĂ€hr 2100 Codezeilen, von denen ungefĂ€hr 700 Kommentare, laute Gedanken, alter verworfener Code und Versuche sind, Methoden zu dokumentieren. Die GröĂe der ausfĂŒhrbaren SWF-Datei betrug jedoch 13112 Byte.
Alles begann mit der Tatsache, dass im Kongregate.com-Forum, in dem ich zu der Zeit aktiv war, einer der Teilnehmer vorschlug, an der prozeduralen Generierung von etwas teilzunehmen. Das erste Thema war
"Wald" .

NatĂŒrlich hatte jeder seine eigene Vorstellung davon, was der Wald sein sollte, den er anbauen wird. Zu dieser Zeit las ich BĂŒcher ĂŒber alle Arten von Magie, deshalb wollte ich einen Wald wachsen lassen. Der Wald besteht aus BĂ€umen - wir schreiben die Klasse Tree {...}. Ein Baum besteht aus Zweigen und BlĂ€ttern - wir schreiben die Klasse Zweig {...} und wir denken, mĂŒssen wir wirklich jedes Blatt auf dem Baum berĂŒcksichtigen? Infolgedessen erhielt der âZweigâ den Parameter âmit BlĂ€tternâ, und der Baum erhielt ein Paar Texturen, eine fĂŒr Zweige und einen Stamm, eine fĂŒr BlĂ€tter. Die Textur âunter dem Baumâ war relativ einfach herzustellen - es gibt PerlingerĂ€usche, man kann sie dehnen, einwickeln, bemalen, als fertig betrachten, aber man musste an den BlĂ€ttern basteln.
Ich war jedoch nicht nur mit dem Trosse-GerĂ€usch auf der Textur eines Baumes zufrieden, sondern habe mir stattdessen ein Bumpmapping ausgedacht - d. H. Er erstellte eine Höhenkarte, optimierte sie unter dem von der Seite sichtbaren Halbkreis des Zweigs, fĂŒllte die Haupttextur mit Braun und ĂŒberlagerte eine Höhenkarte mit der auf das Seitenquietschen angepassten Beleuchtung. Der resultierende Code lautet wie folgt:
private function generateBranch():void { branchBitmap = new BitmapData(512, 512, true, 0xff8080ff);
"Basis" ist eine Hilfsklasse fĂŒr Vektoren a la Vector3D, aber da der Code damals unter Flash 10.1 geschrieben wurde, gab es dort noch keine solchen Vektoren, oder ich zog es vor, mein eigenes Fahrrad zu bauen. Die Textur unter dem Zweig mit BlĂ€ttern wurde wie folgt gezeichnet: Zuerst wurde ein Blatt hergestellt, dann wurde bestimmt, ob die Zweige ein zentrales Blatt hatten, dies bestimmte die LĂ€nge des StĂŒcks des Zweigs, an dem die BlĂ€tter befestigt waren, dann wurden sie in einem Winkel zum Zweig durch die berechnete Breite des Blattes befestigt (berechnet auf der Textur) . Die Form des Blattes wurde als verzerrter Kreis mit mehreren Bezugspunkten festgelegt, die um einen halben Blattradius vom Kreis versetzt waren, und die LĂ€nge des Stiels wurde separat festgelegt. All dies wurde in SchwarzweiĂ auf die Blatttextur gezeichnet und fĂŒr die Zukunft gespeichert. (Genauer gesagt gab es zwei "Zweig mit BlĂ€ttern" -Texturen, eine fĂŒr die Enden, dh Zweige, fĂŒr die nichts vom "Ende" wĂ€chst, aber mit BlĂ€ttern wurde am Ende des Zweigs ein Blatt darauf gezeichnet, das zweite fĂŒr "Mitte" "Ohne Endblatt.)
Das Schwierigste ist dann, wie der Baum aussehen wird. Hier habe ich lange nachgedacht und experimentiert. Ich beschloss, den Baum wirklich wachsen zu lassen - die Zweige dehnen sich in der LĂ€nge (wachsen tatsĂ€chlich vom Ende), manchmal laichen Zweige zur Seite, die Zweige erstrecken sich zur Sonne (nach oben) und ein paar weitere Bedingungen. Es stellte sich als schrecklicher Hash heraus. Die beste Option, die wir teilen konnten, sah folgendermaĂen aus:
(Seltsamerweise ist diary.ru ein ausgezeichneter Foto-Hosting-Service, bisher ist nichts schlecht geworden!)Ich bin zu dem Schluss gekommen, dass wir die Dichte der Zweige irgendwie reduzieren mĂŒssen. UrsprĂŒnglich bestand die Idee darin, sie durch Gravitation zu begrenzen - d. H. zu "schwere" Ăste brechen einfach ab und fallen. Ich fing an, den Moment der Kraft beim Biegen zu zĂ€hlen und verglich ihn mit der StĂ€rke des Baumes (ich zog die Werte von irgendwoher, bewertete sie als Konstanten und begann zu testen) - es stellte sich als schlecht heraus, manchmal brach der Stamm, obwohl es nicht hĂ€tte passieren dĂŒrfen, und der Baum war sicher gebogen Manchmal brach zuerst ein groĂer Ast, das Ergebnis fĂŒhrte zu einem unausgeglichenen Stamm und er brach erneut, diesmal aufgrund eines Verlustes des vertikalen Gleichgewichts, und manchmal eines Astes, dessen Struktur ganz normal war, dessen Dicke zunahm und der zunĂ€chst unter seinem Gewicht gebogen wurde pleite, VerkĂ€ufe wenn nichts drin ist, nicht mehr gewachsen ist. Er traf, weil die Herausforderung eine Frist war.
Der zweite Versuch bestand darin, sowohl das Wachstum neuer Zweige als auch das Ăberleben alter / frĂŒherer Zweige durch Beleuchtung zu begrenzen. Beim dritten Implementierungsversuch (die ersten beiden blieben in Form von auskommentierten Funktionen) stellte sich Folgendes heraus: Ich baute ein dreidimensionales Voxelgitter mit einer Seite von 0,5 Metern (ja, alle Werte waren in Metern und Kilogramm angegeben - ich wollte damals wirklich echte Physik fĂŒr einen echten Wald), das gefĂŒllt war Zuerst Nullen, dann trug jeder Zweig beim Umrunden des Baumes zur FĂŒllung des Gitters in Form seines Volumens geteilt durch ein oder zwei Voxel bei. Tatsache ist, dass alle Zweige (auf jeden Fall fast alle) als separate Teile des berechneten Rahmens kĂŒrzer als 0,5 m waren, was es uns ermöglichte, eine grobe NĂ€herung zu verwenden. ZusĂ€tzlich zum FĂŒllen warf jeder Zweig einen Schatten auf die darunter liegenden Voxel in Form einer zusĂ€tzlichen FĂŒllung der Voxel unter und leicht um das Voxel mit einem Zweig (die endgĂŒltige Form ist eine quadratische Pyramide, aber das Spielen mit einem Kreis brach und wurde daher ohnehin nicht beleuchtet). Dieses Gitter wurde als Begrenzer verwendet, wenn einer der Zweige in der Mitte des Baumes zu wachsen beginnt - er hat dort weniger Licht, ist kĂŒrzer und wĂ€chst möglicherweise ĂŒberhaupt nicht oder stirbt an mangelnder Beleuchtung. Tote Ăste fielen dann ab.
Diese Option ermöglichte es, BĂ€ume zu erhalten, die beim Betrachten relativ transparent und in Bezug auf den Umfang relativ kompakt waren. Die erste Arbeitsversion sah folgendermaĂen aus:

In dieser Version habe ich immer noch den Baumwachstumsmechanismus selbst getestet, und der Baum konnte von allen Seiten betrachtet werden. Ein Baum wurde Ast fĂŒr Ast gezeichnet, die Anordnung der Ăste wurde zunĂ€chst nach Entfernung vom Beobachter sortiert, da ich im guten alten VMX-Kurs ĂŒber dreidimensionale Grafiken von 1996 fĂŒr jeden Aufruf âZeichne mir einen Baumâ Farben fĂŒr kosmetische Zwecke aus dem HSB-Bereich auswĂ€hlte. Damit der Wald nicht eintönig ist, wird auch das Skelett des Baumes zufĂ€llig gedreht, um zu zeichnen. Insgesamt gab es sechs bis acht Baummodelle zum Zeichnen, von denen jedes unter seinem eigenen RNG-Einfluss wuchs. Die Landschaft der Erde verursachte ein weiteres Trosse-GerĂ€usch, und der Ort, an dem der Baum wachsen sollte, wurde zufĂ€llig ausgewĂ€hlt, wobei eine Reihe von zulĂ€ssigen Wachstumspunkten beim Bewegen zur Seite verwendet wurden Entfernungsbeobachter. Wenn der am Punkt A gepflanzte Baum und der Radius des Baums R zum âWachsenâ ausgewĂ€hlt wurden, wurden die Werte (AR, A + R) fĂŒr das Wachstum in der aktuellen Entfernung verboten, wenn beim Ăbergang zum nĂ€chsten (-0,05) dieses Intervall um verringert wurde 0,1 und wurde entfernt, als es auf Null reduziert wurde.
Die letzte (und tatsĂ€chlich die erste und unmittelbar berĂŒcksichtigte) Nuance des gesamten Algorithmus ist, dass er SEHR LANG ist. Um den "erwachsenen" Baum zu umgehen, dauert das Zeichnen einige Sekunden, das Zeichnen der Texturen eines Baums einige Sekunden, eine halbe bis zwei Sekunden, und Adobe Flash ist nicht fĂŒr so lange Berechnungsintervalle ohne Aktualisierung des Bildschirms ausgelegt (genauer gesagt, ohne die Steuerung an die Engine zurĂŒckzugeben). . Daher brauchten wir einen Algorithmus, der den Status zwischen Aufrufen speichern, an der Stelle, an der er unterbrochen wurde, weiterarbeiten und die AusfĂŒhrungszeit steuern kann und gleichzeitig nicht in Panik gerĂ€t und die Flash-Engine nicht in Panik versetzt. Das Speichern des Zustands wurde als ein Paar von Eigenschaften der Hauptklasse implementiert, die in Stufen aufgeteilt wurden - durch Auswahl der Funktionen "einmal einen Baum wachsen lassen", "einen fertigen Baum zeichnen" und "ein StĂŒck Land zeichnen" und die aufgewendete Zeit messen, sobald die nĂ€chste "einmal" Es dauerte mehr als ein paar Sekunden fĂŒr einen Baum, der Baum wurde als "fertig" betrachtet und beiseite gelegt. Es stellte sich heraus, dass es drei groĂe Phasen gab: Texturen erstellen, BĂ€ume âwachsenâ, fertige BĂ€ume auf dem Bildschirm platzieren.
Das Ergebnis sieht folgendermaĂen aus:

Du kannst
hier spielen. Die Optimierung (genauer gesagt, geschrieben) fĂŒr Flash 10.1 unter BerĂŒcksichtigung einer Reihe von Flash-Updates in Bezug auf die Sicherheit kann sehr langsam sein. In diesem Fall empfehle ich Ihnen, die Debug-Version von Adobe Flash Player 11.5 herunterzuladen und offline zu öffnen. Die gesamte Zeichnung dauert 5-6 Minuten. Nach den ersten beiden auf dem Bildschirm treten einige Bewegungen auf, die möglicherweise interessant zu beobachten sind. Nach dem Zeichnen können Sie Strg + Klick drĂŒcken, um das Ergebnis als vierfache PNG-Datei im Vergleich zur FenstergröĂe zu speichern.