Dalam
komentar ini
, saya membual bahwa saya telah menulis sebuah program yang menciptakan hutan yang “tampak baik” dalam dua ratus baris kode. Sayangnya, kenyataannya ternyata sedikit lebih besar dalam ukuran - sumber yang digali berisi sekitar 2100 baris kode, di mana sekitar 700 adalah komentar, pikiran keras, kode lama yang dibuang dan upaya untuk mendokumentasikan metode. Ukuran executable SWF, bagaimanapun, ternyata menjadi 13112 byte.
Semuanya berawal dari fakta bahwa di forum Kongregate.com, di mana saya aktif nongkrong pada saat itu, salah satu peserta menyarankan untuk bersaing dalam pembuatan prosedural sesuatu, topik pertama adalah
"Hutan" .

Secara alami, setiap orang memiliki ide sendiri tentang apa yang seharusnya menjadi hutan yang akan mereka tanam. Pada waktu itu saya membaca buku-buku tentang segala macam sihir, akibatnya, saya ingin menumbuhkan hutan. Hutan terdiri dari pohon - kita menulis kelas Tree {...}. Sebuah pohon terdiri dari cabang dan daun - kita menulis Cabang kelas {...} dan kita berpikir, apakah kita benar-benar perlu memperhitungkan setiap daun di pohon? Akibatnya, "cabang" memperoleh parameter "dengan daun", dan pohon memperoleh sepasang tekstur, satu untuk cabang dan batang, satu untuk daun. Tekstur "di bawah pohon" relatif mudah dibuat - ada suara perlin, Anda dapat meregangkannya, membungkusnya, melukisnya, menganggapnya sudah siap, tetapi Anda harus mengotak-atik daunnya.
Namun, saya tidak senang hanya dengan suara penjaja di tekstur pohon, sebagai gantinya, saya datang dengan bumpmapping - yaitu. Dia menciptakan peta tinggi, men-tweak-nya di bawah setengah lingkaran cabang yang terlihat dari samping, lalu mengisi tekstur utama dengan cokelat dan menambahkan peta ketinggian dengan pencahayaan disesuaikan dengan mencicit sisi. Kode yang dihasilkan adalah sebagai berikut:
private function generateBranch():void { branchBitmap = new BitmapData(512, 512, true, 0xff8080ff);
"Basis" adalah kelas pembantu untuk vektor a Vector3D, tetapi karena kode ini ditulis di bawah Flash 10.1 lalu, belum ada vektor seperti itu di sana, atau saya lebih suka membuat sepeda sendiri. Tekstur di bawah cabang dengan daun digambar sebagai berikut: pertama dibuat satu lembar, kemudian ditentukan apakah cabang memiliki lembaran tengah, ini menentukan panjang potongan cabang tempat daun dilampirkan, kemudian mereka dilampirkan (dihitung pada tekstur) pada sudut ke cabang dengan lebar dihitung dari lembar. . Bentuk daun ditetapkan sebagai lingkaran terdistorsi dengan beberapa titik referensi diimbangi dari lingkaran dengan radius setengah lembar, dan panjang stek ditetapkan secara terpisah, semua ini digambar pada tekstur daun hitam dan putih dan disimpan untuk masa depan. (Lebih tepatnya, ada dua tekstur "bercabang dengan daun", satu untuk ujung, yaitu cabang yang tidak ada yang tumbuh dari "ujung", tetapi dengan daun, daun digambar di ujung cabang, yang kedua untuk "pertengahan "Tanpa lembar akhir.)
Lalu bagian tersulitnya adalah seperti apa bentuk pohon itu? Di sini saya berpikir dan bereksperimen untuk waktu yang lama. Saya memutuskan untuk membuat pohon itu benar-benar tumbuh - cabang-cabangnya membentang panjang (sebenarnya tumbuh dari ujung), kadang-kadang menelurkan cabang ke samping, cabang-cabang membentang ke matahari (atas) dan beberapa kondisi lainnya. Ternyata hash yang mengerikan, opsi terbaik yang berhasil kami bagikan terlihat seperti ini:
(Anehnya, diary.ru adalah layanan hosting foto yang sangat baik, sejauh ini tidak ada yang buruk!)Saya sampai pada kesimpulan bahwa kita perlu mengurangi kepadatan cabang. Awalnya, idenya adalah untuk membatasi mereka secara gravitasi - yaitu cabang terlalu "berat" hanya putus dan jatuh. Saya mulai menghitung momen kekuatan dalam menekuk, membandingkannya dengan kekuatan pohon (saya menyeret nilai-nilai dari suatu tempat, mencetaknya sebagai konstanta dan mulai menguji) - ternyata buruk, kadang-kadang batangnya patah, meskipun seharusnya tidak terjadi, dan pohon itu tertekuk dengan aman , kadang-kadang cabang besar pecah pada awalnya, hasilnya menyebabkan batang tidak seimbang dan patah lagi, kali ini karena hilangnya keseimbangan vertikal, dan kadang-kadang cabang yang strukturnya cukup normal, bertambah tebal, awalnya bengkok karena berat, kemudian bangkrut, penjualan jika tidak ada di dalamnya tidak lagi tumbuh. Dia mencetak gol karena tantangannya adalah tenggat waktu.
Upaya kedua adalah membatasi pertumbuhan cabang baru dan kelangsungan hidup yang lama / sebelumnya menggunakan pencahayaan. Dari upaya ketiga implementasi (dua yang pertama tetap dalam bentuk fungsi yang dikomentari) ternyata seperti ini: Saya membangun kisi voxel tiga dimensi dengan sisi 0,5 meter (ya, semua nilai ada dalam meter dan kilogram - saya benar-benar ingin fisika nyata untuk hutan nyata saat itu), yang diisi pada nol pertama, lalu ketika mengelilingi pohon, setiap cabang berkontribusi pada pengisian kisi dalam bentuk volumenya dibagi satu atau dua voxel. Faktanya adalah bahwa semua cabang (dalam hal apapun, hampir semua) sebagai potongan terpisah dari frame yang dihitung lebih pendek dari 0,5m, yang memungkinkan kami untuk menggunakan perkiraan kasar. Selain mengisi, masing-masing cabang "melemparkan bayangan" pada voxel yang mendasari dalam bentuk pengisian tambahan voxel di bawah dan sedikit di sekitar voxel dengan cabang (bentuk terakhir adalah piramida persegi, tetapi bermain-main dengan lingkaran pecah, dan karenanya tidak menyala pula). Kisi ini digunakan sebagai pembatas, jika salah satu cabang mulai tumbuh di tengah pohon - akan ada lebih sedikit cahaya di sana, itu akan lebih pendek dan mungkin tidak tumbuh sama sekali atau mati karena kurangnya penerangan. Cabang-cabang yang mati kemudian jatuh.
Opsi ini memungkinkan untuk mendapatkan pohon yang relatif transparan saat dilihat dan relatif kompak dalam hal cakupan, versi kerja pertama terlihat seperti ini:

Dalam versi ini, saya masih memperdebatkan mekanisme pertumbuhan pohon itu sendiri, dan pohon itu dapat dilihat dari semua sisi. Pohon itu digambar satu cabang pada satu waktu, susunan cabang pertama kali diurutkan berdasarkan jarak dari pengamat, seperti dalam kursus VMX tua yang baik pada grafik tiga dimensi dari tahun 1996, saya memilih warna untuk keperluan kosmetik dari kisaran HSB untuk setiap panggilan "gambar saya pohon" Agar hutan tidak monoton, kerangka pohon juga diputar secara acak untuk menggambar. Secara total, ada enam hingga delapan model pohon untuk menggambar, masing-masing tumbuh di bawah pengaruh RNG-nya sendiri, bentang bumi menetapkan kebisingan hawser lain, dan tempat di mana menanam pohon dipilih secara acak menggunakan serangkaian rentang titik yang diizinkan untuk pertumbuhan bergerak ke sisi pengamat jarak. Jika pohon ditanam di titik A, dan jari-jari pohon R dipilih untuk "tumbuh", maka nilai-nilai (AR, A + R) menjadi terlarang untuk pertumbuhan pada jarak saat ini, ketika pindah ke yang berikutnya (-0,05) interval ini menurun oleh 0,1, dan telah dihapus ketika dikurangi menjadi nol.
Nuansa terakhir (dan sebenarnya yang pertama dan segera diperhitungkan) dari keseluruhan algoritma adalah SANGAT PANJANG. Untuk mengitari pohon "dewasa", diperlukan beberapa detik untuk menggambar, beberapa lagi untuk menggambar tekstur satu pohon, dibutuhkan dari setengah detik hingga dua, dan Adobe Flash tidak dirancang untuk interval perhitungan yang lama tanpa memperbarui layar (lebih tepatnya, tanpa mengembalikan kontrol ke mesin) . Oleh karena itu, kami memerlukan algoritme yang dapat menyimpan keadaan di antara panggilan, terus bekerja dari tempat di mana ia terputus dan mengontrol waktu pelaksanaannya, dan pada saat yang sama jangan panik sendiri dan jangan panik mesin flash. Menyelamatkan negara diimplementasikan sebagai sepasang properti dari kelas Utama, membelah menjadi beberapa tahap - dengan memilih fungsi "menumbuhkan pohon sekali", "menggambar pohon jadi" dan "menggambar sebidang tanah" dan mengukur waktu yang dihabiskan, masing-masing, segera setelah "sekali" berikutnya butuh lebih dari beberapa detik untuk sebuah pohon, pohon itu dianggap "siap" dan disingkirkan. Ternyata tiga fase besar: membuat tekstur, "tumbuh" pohon, menempatkan pohon jadi di layar.
Hasilnya terlihat seperti ini:

Anda bisa bermain di
sini . Dioptimalkan (lebih tepatnya, ditulis) untuk Flash 10.1, dengan mempertimbangkan sekelompok pembaruan flash dalam hal keamanan bisa sangat lambat - dalam hal ini, saya menyarankan Anda untuk mengunduh versi debug Adobe Flash Player 11.5 dan membukanya secara offline. Keseluruhan gambar membutuhkan 5-6 menit, setelah dua gambar pertama di layar beberapa gerakan mulai terjadi, yang mungkin menarik untuk diamati. Setelah menggambar, Anda dapat menekan Ctrl + klik untuk menyimpan hasilnya sebagai file PNG empat kali lipat dibandingkan dengan ukuran jendela.