Bagaimana Perusahaan Game "Membuat Game dengan Tangan" Sebelum Mesin yang Matang?
Jawaban untuk pertanyaan ini jauh lebih mentah daripada yang dibayangkan kebanyakan orang.
Pengembang game masa kini membuka Unity atau Unreal, editornya sudah ada, engine fisiknya sudah ada, pipeline renderingnya sudah ada, sistem pencahayaannya sudah ada. Tugas mereka adalah mengisi konten ke dalam kerangka yang sudah dibangun. Hal itu tidak ada di tahun 1980-an. Tidak ada framework, tidak ada engine, tidak ada infrastruktur yang dapat digunakan kembali. Jika Anda ingin membuat game, pertama-tama Anda harus membangun mesin yang bisa menjalankannya, lalu di atas mesin itu, menggunakan bahasa assembly, Anda memberi tahu setiap piksel apa warnanya.
Semuanya dimulai dari piksel.
Grafik game awal ditulis langsung ke memori. Programmer harus mengetahui alamat memori yang sesuai dengan setiap posisi di layar. Untuk menggambar titik di lokasi tertentu, Anda menulis nilai ke alamat itu — nilai tersebut mewakili warna. Untuk menggambar garis, Anda menulis sebuah loop, memberi tahu CPU untuk menulis di setiap N byte dari alamat ini ke alamat itu. Untuk menggambar karakter, Anda mengonversi setiap baris piksel menjadi bilangan heksadesimal, menulisnya baris demi baris, menemukan offset yang benar di layar, dan menempatkan angka-angka itu di sana.
Proses ini sekarang disebut “software rendering”. Saat itu tidak punya nama, karena tidak ada alternatif — hanya disebut “bagaimana gambar muncul.”
Ketika Carmack mengerjakan Wolfenstein pertama, dia menghadapi masalah spesifik: arsitektur grafis IBM PC tidak mendukung pengguliran horizontal yang mulus. Layar diperbarui dengan menyegarkan seluruh bingkai sekaligus, menyebabkan robekan saat gambar bergerak — tampak seperti bergetar. Dia menghabiskan banyak waktu mempelajari register tingkat rendah kartu grafis, dan menemukan cara untuk menipu perangkat keras agar melakukan sesuatu yang tidak didukung secara native, mensimulasikannya melalui perangkat lunak — dan gambar bisa bergulir dengan mulus.
Tidak ada dokumentasi untuk ini, tidak ada pengalaman pendahulu. Dia hanya duduk di sana, membaca manual perangkat keras sampai habis, dan menemukannya sedikit demi sedikit melalui trial and error.
Ini adalah kondisi kerja dasar programmer di era itu. Anda tidak berhadapan dengan sistem yang memiliki buku petunjuk — Anda berhadapan dengan perangkat keras itu sendiri. Anda harus mengenal perangkat keras lebih baik daripada perangkat keras mengenal dirinya sendiri, dan menemukan ruang di celah-celahnya.
Suara adalah masalah dimensi yang sama sekali berbeda.
Sistem suara PC awal adalah sebuah buzzer — PC Speaker. Ia hanya bisa menghasilkan satu suara: bunyi bip. Untuk memutar musik dengannya, Anda harus mengontrol frekuensi getaran buzzer ini, beralih di antara frekuensi yang berbeda dengan kecepatan sangat tinggi, memanfaatkan efek persistensi pendengaran manusia agar terdengar seperti melodi yang dimainkan. Teknik ini disebut PWM, pulse-width modulation. Prinsipnya adalah fisika akustik, implementasinya adalah kontrol waktu yang presisi hingga tingkat mikrodetik. Salah sedikit saja, yang keluar hanyalah kebisingan.
Ada programmer pada saat itu专门 meneliti cara memeras lebih banyak lapisan suara dari PC Speaker. Metode mereka adalah beralih di antara frekuensi yang berbeda dalam jendela waktu yang sangat singkat, menciptakan efek pseudo-stereo. Teknik ini diperlakukan seperti sihir hitam dalam scene demo pada masa itu. Anda mengambil buzzer yang hanya bisa berbunyi “bip,” dan menghasilkan sesuatu yang terdengar mendekati musik. Programmer lain yang mendengarnya tidak tahu bagaimana Anda melakukannya — karena prinsipnya tidak intuitif. Anda membutuhkan pemahaman yang sangat presisi tentang kontrol waktu untuk mewujudkannya.
Ketika Adlib dan Sound Blaster muncul, mereka membawa suara sintesis FM. Ini adalah sistem lain yang harus dipelajari dari awal. Prinsip sintesis FM adalah menggunakan bentuk gelombang dari satu frekuensi untuk memodulasi bentuk gelombang frekuensi lain, menghasilkan timbre yang kompleks. Parameter modulasi yang berbeda menghasilkan suara instrumen yang berbeda. Programmer harus menyetel parameter sendiri, menguji kombinasi mana yang terdengar seperti piano, mana yang seperti biola, mana yang seperti ledakan. Tidak ada jawaban standar — semuanya bergantung pada telinga dan pengalaman. Saat itu, setiap programmer suara di setiap perusahaan memiliki tabel parameter akumulasi mereka sendiri. Itu adalah rahasia dagang dalam arti yang sesungguhnya.
Rasa desain di tingkat logika game adalah bentuk yang lain lagi.
Tidak adanya engine berarti tidak ada deteksi tabrakan yang siap pakai, tidak ada simulasi fisika yang siap pakai, tidak ada framework AI yang siap pakai. Jika Anda ingin karakter berhenti saat mencapai dinding alih-alih menembusnya, Anda harus menulis deteksi tabrakan sendiri, mendefinisikan sendiri apa itu “tabrakan,” dan memutuskan sendiri bagaimana kecepatan dan posisi karakter berubah setelah tabrakan.
Deteksi tabrakan game awal sederhana dan brutal: memperlakukan karakter dan rintangan sebagai persegi panjang, memeriksa apakah kedua persegi panjang tumpang tindih, dan jika ya, berhenti. Skema ini cepat, tetapi masalahnya adalah karakter game nyata bukanlah persegi panjang — mereka adalah sprite dengan bentuk. Selalu ada kesenjangan antara kotak tabrakan persegi panjang dan grafis aktual. Itulah mengapa dalam game awal, peluru yang jelas meleset tetap dihitung sebagai mengenai, atau karakter berhenti sebelum secara visual menyentuh dinding.
Pemain saat itu tidak menyebut ini bug. Mereka menyebutnya fitur game. Karena mereka tidak tahu bahwa bisa berbeda.
Hal lain yang perlu disebutkan: PC awal memiliki memori yang sangat terbatas. 640KB adalah batas atas perangkat keras selama satu dekade penuh. Angka itu hari ini bahkan tidak bisa menyimpan satu tangkapan layar. Programmer harus memasukkan semua konten game — grafis, efek suara, peta, kode logika — ke dalam 640KB itu, dan masih menyisakan ruang untuk data runtime.
Bagaimana? Kompresi, pemuatan bertahap, dan penggunaan ulang.
Kompresi data grafis adalah disiplin tersendiri. Programmer harus menemukan algoritma kompresi mereka sendiri, membuat data grafis sekecil mungkin saat disimpan dan mendekompresinya secara instan saat diperlukan. Jika peta terlalu besar, Anda membaginya menjadi potongan-potongan, memuat potongan tempat pemain berdiri, dan membongkarnya saat pemain pergi. Hari ini teknik ini disebut streaming. Saat itu disebut “tidak ada cara lain.”
Setiap byte dalam memori diperebutkan. Saat menulis kode, programmer terus-menerus harus berpikir: dapatkah saya menggunakan tipe data yang lebih kecil untuk variabel ini? Dapatkah saya menggunakan lebih sedikit variabel sementara untuk logika ini? Dapatkah saya mengurangi jumlah akses memori dalam loop ini? Cara berpikir ini sebagian besar tidak diperlukan bagi programmer masa kini. Perangkat keras modern memiliki cukup ruang memori, dan compiler cukup pintar dalam optimasi — Anda tidak perlu menghitung setiap byte.
Tapi programmer era itu membawa seluruh cara kerja internal komputer di kepala mereka. Dari siklus instruksi CPU hingga tata letak memori hingga register GPU, mereka harus memahami setiap lapisan, karena setiap lapisan adalah celah yang mungkin perlu mereka eksploitasi.
Carmack pernah menulis kode untuk menghitung kebalikan akar kuadrat, dengan sebuah komentar di dalamnya yang bertuliskan “what the fuck.” Kode ini menggunakan trik manipulasi bit yang sangat kontraintuitif untuk memperkirakan kebalikan akar kuadrat dengan cepat, jauh lebih cepat daripada pustaka matematika standar — semuanya untuk menghemat waktu komputasi dalam rendering 3D. Potongan kode ini kemudian menjadi legenda dalam budaya programmer, dikutip berulang kali, karena ia mewakili cara berpikir yang telah hilang: metode memeras kinerja dari matematika dan kreativitas dalam batasan perangkat keras.
Programmer game era itu lebih dekat ke hibrida insinyur dan ilmuwan. Masalah yang mereka selesaikan bukan hanya “bagaimana mengimplementasikan fitur ini” — melainkan “dapatkah fitur ini diimplementasikan dalam batas fisik mesin ini.”
Kedua pertanyaan itu sangat berbeda.
Pertanyaan pertama memiliki jawaban standar: lihat dokumentasi, panggil API, ikuti langkah-langkahnya. Pertanyaan kedua tidak memiliki jawaban standar. Anda harus menemukan jawabannya sendiri. Terkadang jawabannya ada, terkadang tidak. Anda harus mencari tahu dulu dalam kasus mana Anda berada, lalu memutuskan apa yang harus dilakukan.
Industri game saat ini adalah sistem kolaborasi yang sangat besar. Perusahaan engine, perusahaan middleware, perusahaan toolchain — setiap lapisan ada yang mengerjakannya. Pengembang berdiri di puncak sistem ini, fokus pada konten itu sendiri. Ini adalah kemajuan, ini hal yang baik — memungkinkan lebih banyak orang membuat game, dan membuat skala serta kompleksitas game jauh melampaui apa yang mungkin di masa lalu.
Tapi era membangun game dari piksel itu memiliki sesuatu yang tidak lagi ada saat ini.
Anda membuka game, dan Anda tahu dari mana setiap titik di layar berasal, bagaimana setiap suara dibuat, bagaimana setiap tabrakan dinilai. Karena semua itu ditulis oleh Anda, baris demi baris. Tidak ada bagian yang dikerjakan orang lain untuk Anda.
Perasaan ini memiliki nama. Namanya adalah kendali penuh.
Jadi, para hebat yang mengembangkan game di masa itu — mereka benar-benar hebat. Sungguh luar biasa.