Pada tahun 2016, saya mulai mengerjakan proyek hobi untuk merekayasa balik game
Duke Nukem II dan menciptakan kembali mesinnya dari awal. Proyek ini disebut Rigel Engine dan tersedia dalam sumber terbuka (
halamannya di GitHub ). Hari ini, lebih dari dua setengah tahun kemudian, di mesin saya, Anda sudah dapat melewati seluruh episode shareware dari game asli dengan gameplay yang hampir sama dengan aslinya. Berikut ini adalah video dengan bagian dari tingkat pertama:
Apa yang bisa dia lakukan? Rigel Engine berfungsi sebagai pengganti lengkap untuk binari DOS asli (
NUKEM2.EXE
). Anda bisa menyalinnya ke direktori game dan mempertimbangkan semua data dari itu, atau menentukan jalur ke data game sebagai argumen ke baris perintah. Mesin dibangun dan dijalankan di bawah Windows, Mac OS X dan Linux. Ini didasarkan pada
SDL dan OpenGL 3 / OpenGL ES 2, dan ditulis dalam C ++ 17.
Ini mengimplementasikan logika game dari semua musuh dan mekanik game dari episode Shareware, ditambah sebagian besar sistem menu. Selain itu, Anda dapat mengimpor game yang disimpan dan tabel skor tinggi dari game asli ke dalamnya.
Selain itu, mesin memiliki keunggulan dibandingkan yang asli:
- Tidak diperlukan emulator atau perangkat keras lama, tidak diperlukan pengaturan
- Tanpa memuat layar - pilih "permainan baru" di menu, tekan Enter, dan segera mulai permainan
- Beberapa efek suara dapat dimainkan pada saat yang sama, yang tidak mungkin pada aslinya
- Tidak ada batasan jumlah efek simultan dari partikel, ledakan, dan sebagainya.
- Simpan file dan daftar skor tinggi untuk setiap pemain
- Menu jauh lebih responsif
Sejauh ini, saya tidak menganggap Mesin Rigel sepenuhnya "siap." Tapi ini adalah tahap yang bagus dalam pengembangan dan kesempatan yang baik untuk menulis tentang mesin lagi (posting lama diterbitkan di
sini dan di
sini ). Mari kita mulai dengan melihat keadaan kode saat ini dan mencari tahu bagaimana saya mendapatkannya.
Berapa banyak kode di mesin?
Pada saat penulisan, RigelEngine terdiri dari 270 file sumber yang berisi lebih dari 25 ribu baris kode (tidak ada komentar / baris kosong). Dari jumlah tersebut, 10 file dan 2,5 ribu baris adalah unit test. Rincian garis-garis kosong dan komentar tersedia di
sini .
Apa yang ada dalam semua kode ini? Sedikit infrastruktur umum dan fungsi pendukung, seperti hal-hal dasar seperti rendering, dan sekelompok kecil logika. Selain semua ini, bagian terbesar adalah:
- parser / pengunduh untuk 14 format file berbeda yang digunakan dalam gim asli - 2 ribu baris kode (LOC)
- logika perilaku / logika permainan untuk 24 musuh / benda bermusuhan - 3.8k LOC
- logika game untuk 14 elemen interaktif dan mekanika game - 2k LOC
- logika kontrol pemain - 1.2k LOC
- 154 entri konfigurasi (nilai kesehatan setiap musuh, jumlah poin yang diterima untuk item yang dikumpulkan, dll.) - 1k LOC
- 31 spesifikasi untuk efek kehancuran (efek yang dipicu oleh penghancuran musuh atau objek yang dapat dirusak lainnya) - 254 LOC
- kode kontrol kamera - 159 LOC
- menu game deskripsi bahasa juru / cutscene - 643 LOC
- HUD dan kode UI lainnya adalah 818 LOC
- 5 layar / mode di luar menu, misalnya, animasi awal, layar bonus, dll. - 789 LOC
Tentu saja, semua kode ini perlu ditulis, dan ini membawa kita ke pertanyaan berikutnya.
Berapa banyak pekerjaan yang diperlukan?
Meskipun dua setengah tahun telah berlalu sejak awal proyek, saya belum mengerjakannya selama ini. Selama beberapa bulan saya tidak melakukan proyek sama sekali, di beberapa yang lain saya hanya menghabiskan beberapa jam untuk itu. Tapi ada kalanya saya bekerja di Rigel Engine dengan cukup aktif. Melihat jadwal komit di Github, Anda bisa mendapatkan gambaran kasar tentang bagaimana pekerjaan saya didistribusikan dari waktu ke waktu:
Menurut jadwal, kita melihat bahwa 1081 komit dibuat untuk cabang utama. Namun, bahkan sebelum membuat repositori, saya sedang mengerjakan yang tertutup, di mana ada 247 lebih banyak komit, yang secara total memberi kita 1328 komit. Selain itu, ada beberapa cabang prototipe yang saya gunakan untuk penelitian dan eksperimen, tetapi tidak pernah dikombinasikan dengan yang utama; selain itu, sebelum bergabung, saya terkadang memadatkan cerita komit besar menjadi cerita pendek.
Saya juga harus mengatakan bahwa penulisan kode bukan satu-satunya bagian dari proyek - rekayasa balik adalah bagian penting lainnya. Saya menghabiskan beberapa jam mempelajari kode yang dibongkar dari file executable asli di
Ida Pro (dalam versi gratis), membuat catatan, menulis kodesemu, dan merencanakan implementasi elemen-elemen versi saya. Selain itu, saya aktif menguji game asli, menjalankannya di
DOSBox dan pada peralatan asli (mesin yang berbeda 386 dan 486 dibeli di eBay). Saya mengumpulkan level tes untuk pengamatan terpisah dari musuh spesifik dan mempelajari mekanika game, merekam klip video menggunakan DOSBox, dan melihat melalui bingkai frame-by-frame untuk mengkonfirmasi kesimpulan saya yang dibuat saat mempelajari kode assembler. Setelah musuh atau mekanik gim direalisasikan, saya biasanya merekam klip video dari versi saya dan membandingkannya satu per satu dengan yang asli untuk mengkonfirmasi keakuratan implementasi saya.
Berikut beberapa foto catatan saya:
Membalikkan kode kontrol kamera rekayasa. Kotak besar menunjukkan layar. Garis putus-putus menunjukkan zona dimana pemain dapat bergerak tanpa menggerakkan kamera. Jika Anda tertarik, kode kontrol kamera itu sendiri dapat ditemukan di sini .Catatan umum untuk membantu Anda memahami kode perakitan. Di sebelah kiri adalah prosedur untuk memperbarui gim asli di tingkat tinggi. Di sebelah kanan adalah catatan pada bidang bit yang menunjukkan status beberapa objek game.Transkripsi kode assembler ke pseudocode. Biasanya saya melakukannya secara mekanis, menyalin tanpa memikirkan apa yang dilakukan kode, dan kemudian menggunakan versi dalam pseudo-code untuk memahami logika yang mendasarinya. Dan atas dasar itu, saya sudah datang dengan implementasi saya. Lihat kode yang sudah selesai di sini .Kode palsu dari versi logika musuh yang dibersihkan. Header menunjukkan keadaan mesin negara, kode di bawah ini menjelaskan apa yang harus terjadi di masing-masing negara. Itu dibuat berdasarkan pseudocode mentah yang diperoleh dengan menyalin kode assembler. Kode siap dapat ditemukan di sini .Pada akhirnya, pekerjaan pada proyek tersebut ternyata sangat menarik, dan saya belajar banyak darinya: tentang reverse engineering, assembler x86 16-bit, pemrograman VGA tingkat rendah, pembatasan ketat yang harus dihadapi pengembang game PC di awal tahun 90-an; selain itu, saya membuat banyak penemuan tentang fitur internal dari game asli dan betapa aneh dan aneh beberapa dari mereka diimplementasikan - topik ini sendiri layak mendapatkan serangkaian posting yang terpisah.
Apa selanjutnya
Selain menambahkan fungsi terakhir yang tersisa dan menyelesaikan dukungan untuk versi terdaftar, saya punya beberapa ide untuk meningkatkan dan memperluas kemampuan Mesin Rigel, belum lagi membersihkan dan refactoring kode - seperti biasa, cara terbaik untuk membuat arsitektur perangkat lunak menjadi jelas hanya setelah pembuatan perangkat lunak ini selesai.
Adapun perbaikan di masa depan, berikut adalah beberapa poin yang saya pikirkan tentang penerapan:
- Gerakan halus dengan interpolasi. Gim ini memperbarui logikanya sekitar 15 kali per detik, dan dalam gim asli itu juga merupakan frame rate untuk rendering. Di sisi lain, Mesin Rigel dapat dengan mudah bekerja dengan frekuensi 60 FPS dan lebih tinggi. Saat ini, bingkai tambahan ini tidak memberikan keuntungan apa pun, tetapi saya pikir mereka dapat digunakan untuk bingkai menengah untuk mewujudkan pengguliran dan pergerakan objek yang lebih halus. Logika permainan masih akan bekerja pada kecepatan yang sama, tetapi objek akan bergerak dengan lancar, dan tidak "melompat" dengan penambahan 8 piksel, seperti yang mereka lakukan sekarang. Sebelumnya, saya membuat prototipe sistem seperti itu, dan itu terlihat hebat, meskipun perlu diperbaiki.
- Dukungan gamepad. Dalam gim asli, ada dukungan untuk joystick, dan DosBox dapat mengemulasi mereka pada gamepad modern, tetapi penyiapannya mungkin sulit - persiapan konfigurasi dan kalibrasi dalam gim diperlukan. Belum lagi bahwa tidak semua tombol controller didukung, tetapi untuk menggunakan menu Anda masih harus mengambil keyboard. Oleh karena itu, saya percaya bahwa dukungan pengontrol asli akan secara signifikan meningkatkan gameplay.
- Peningkatan suara. Saat ini, semua efek suara memiliki volume yang sama. Objek yang menghasilkan suara, misalnya, memaksa medan, menjadi terdengar tajam ketika mereka menekan layar, dan putus sama tajam. Saya ingin tahu bagaimana mereka akan terdengar jika volume efek di kejauhan memudar. Sebagai contoh, kita hampir tidak bisa mendengar medan gaya ketika belum ada di layar, dan ketika mendekatinya akan menjadi lebih keras.
- Kamera jarak jauh / lihat sebagian besar level. Gim ini tidak dirancang untuk ini, jadi kemungkinan ini dapat merusak gameplay - pemain akan mulai melihat musuh yang tidak aktif di luar layar, dan sejenisnya. Tapi saya masih bertanya-tanya bagaimana tampilannya dan bermain. Pada akhirnya, pemain sangat sering mengeluh tentang permainan ini karena ketidakmampuan mereka untuk melihat bagian yang cukup dari level. Akan menarik untuk menambahkan opsi untuk mematikan HUD atau menggantinya dengan yang lebih minimal menggunakan transparansi.
- Tambah resolusi grafis. Fitur ini sering ditemukan di banyak port / rekreasi permainan, dan akan menyenangkan untuk menambahkannya di sini. Mesin sudah memungkinkan Anda untuk mengganti grafik sprite dengan gambar Anda sendiri, tetapi sejauh ini mereka tidak dapat memiliki resolusi yang lebih tinggi, karena semuanya dirender menjadi buffer kecil dengan peningkatan skala berikutnya. Pertama, Anda perlu mengganti pendekatan ini sehingga penskalaan dapat dilakukan untuk objek individual.
Saya tidak punya peta jalan untuk masa depan, jadi saya bisa menerapkan poin ini dalam urutan apa pun. Namun sebelum semua ini, langkah selanjutnya adalah integrasi Dear ImGui untuk merakit lebih lanjut menu opsi, yang belum ada dalam game; selain itu, ini akan mengaktifkan atau menonaktifkan perbaikan di atas. Pada akhirnya, saya akan mengatakan bahwa saya akan berterima kasih atas
bantuan apa pun
dalam mengerjakan GitHub !