Pertanyaan
Ketika Anda memiliki gim 2D yang menggunakan gambar sangat besar (lebih besar dari yang dapat didukung oleh perangkat keras Anda), apa yang Anda lakukan? Mungkin ada beberapa solusi menarik untuk masalah ini yang tidak pernah terjadi pada saya sebelumnya.
Saya pada dasarnya mengerjakan sejenis pembuat game petualangan grafis. Target audiens saya adalah orang-orang dengan sedikit pengalaman pengembangan game (dan pemrograman). Jika Anda bekerja dengan aplikasi seperti itu, tidakkah Anda lebih suka untuk itu menangani masalah secara internal daripada meminta Anda untuk "pergi membagi gambar Anda"?
Konteks
Sudah diketahui bahwa kartu grafis memaksakan serangkaian batasan pada ukuran tekstur yang dapat mereka gunakan. Misalnya, ketika bekerja dengan XNA, Anda dibatasi untuk ukuran tekstur maksimum 2048 atau 4096 piksel tergantung pada profil yang Anda pilih.
Biasanya ini tidak menimbulkan banyak masalah dalam game 2D karena kebanyakan dari mereka memiliki level yang dapat dibangun dari potongan individual yang lebih kecil (mis. Ubin atau sprite yang diubah).
Tapi pikirkan beberapa game petualangan grafis point'n'click klasik (mis. Monkey Island). Kamar-kamar dalam permainan petualangan grafis biasanya dirancang secara keseluruhan, dengan sedikit atau tanpa bagian yang dapat diulang, sama seperti pelukis yang bekerja pada lanskap. Atau mungkin gim seperti Final Fantasy 7 yang menggunakan latar belakang besar yang telah dirender.
Beberapa kamar ini bisa menjadi cukup besar, sering mencakup tiga atau lebih layar lebar. Sekarang jika kita mempertimbangkan latar belakang ini dalam konteks game definisi tinggi modern, mereka akan dengan mudah melebihi ukuran tekstur maksimum yang didukung.
Sekarang, solusi yang jelas untuk ini adalah untuk membagi latar belakang menjadi bagian-bagian yang lebih kecil yang sesuai dengan persyaratan dan menarik mereka berdampingan. Tetapi apakah Anda (atau artis Anda) harus menjadi orang yang membelah semua tekstur Anda?
Jika Anda bekerja dengan API tingkat tinggi, bukankah sebaiknya dipersiapkan untuk menghadapi situasi ini dan melakukan pemisahan dan pemasangan tekstur secara internal (baik sebagai pra-proses seperti Pipa Konten XNA atau saat runtime)?
Edit
Inilah yang saya pikirkan, dari sudut pandang implementasi XNA.
Mesin 2D saya hanya membutuhkan sebagian kecil fungsi Texture2D. Saya benar-benar dapat mengurangi ke antarmuka ini:
public interface ITexture
{
int Height { get; }
int Width { get; }
void Draw(SpriteBatch spriteBatch, Vector2 position, Rectangle? source, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
}
Satu-satunya metode eksternal yang saya gunakan yang bergantung pada Texture2D adalah SpriteBatch.Draw () sehingga saya bisa membuat jembatan di antara mereka dengan menambahkan metode ekstensi:
public static void Draw(this SpriteBatch spriteBatch, ITexture texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
{
texture.Draw(spriteBatch, position, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
}
Ini akan memungkinkan saya untuk menggunakan ITexture secara bergantian setiap kali saya menggunakan Texture2D sebelumnya.
Lalu saya bisa membuat dua implementasi berbeda dari ITexture misalnya RegularTexture dan LargeTexture, di mana RegularTexture hanya akan membungkus Texture2D biasa.
Di sisi lain, LargeTexture akan menyimpan daftar masing-masing Texture2D yang sesuai dengan salah satu potongan gambar penuh. Bagian yang paling penting adalah memanggil Draw () pada LargeTexture harus dapat menerapkan semua transformasi dan menggambar semua bagian seolah-olah mereka hanya satu gambar yang berdekatan.
Akhirnya, untuk membuat seluruh proses transparan, saya akan membuat kelas pemuat tekstur terpadu yang akan bertindak sebagai Metode Pabrik. Itu akan mengambil jalur tekstur sebagai parameter dan mengembalikan ITexture yang akan menjadi RegularTexture atau LargeTexture tergantung pada ukuran gambar yang melebihi batas atau tidak. Tetapi pengguna tidak perlu tahu yang mana itu.
Sedikit berlebihan atau apakah itu terdengar oke?
Jawaban:
Saya pikir Anda berada di jalur yang benar. Anda harus membagi gambar menjadi potongan-potongan kecil. Karena Anda membuat pembuat game, Anda tidak dapat menggunakan pipa Konten XNA. Kecuali jika pembuat Anda lebih seperti Mesin yang masih akan meminta pengembang untuk menggunakan Visual Studio. Jadi, Anda perlu membangun rutinitas Anda sendiri yang akan melakukan pemisahan. Anda bahkan harus mempertimbangkan streaming potongan-potongan sedikit sebelum menjadi visizble sehingga Anda masih tidak membatasi berapa banyak memori video yang harus dimiliki pemain.
Ada beberapa trik yang bisa Anda lakukan khusus untuk game petualangan. Saya membayangkan seperti semua game petualangan klasik, Anda akan memiliki beberapa lapisan tekstur ini sehingga ... karakter Anda dapat berjalan di belakang pohon atau bangunan ...
Jika Anda ingin lapisan ini memiliki efek paralaxing maka ketika Anda membelah ubin Anda cukup lewati semua tembus sekali. Di sini Anda perlu memikirkan ukuran ubin. Ubin yang lebih kecil akan menambah mengatur overhead dan menarik panggilan, tetapi akan lebih sedikit data di mana ubin yang lebih besar akan lebih ramah GPU tetapi akan memiliki banyak transparansi.
Jika Anda tidak memiliki efek paralaxing maka alih-alih menutupi seluruh adegan dengan 2-4 gambar raksasa yang memiliki kedalaman 32 bit Anda dapat membuat hanya satu kedalaman 32 bit. Dan Anda dapat memiliki lapisan stensil atau kedalaman yang hanya akan 8 bit per piksel.
Saya tahu ini terdengar sulit untuk mengelola aset oleh pengembang non-game tetapi sebenarnya tidak harus begitu. Misalnya jika Anda memiliki jalan dengan 3 pohon dan pemain berjalan di belakang 2 pohon dan di depan pohon ketiga dan latar belakang lainnya ... Buat tata letak adegan seperti yang Anda inginkan di editor dan kemudian di membangun langkah dari pembuat gim Anda, Anda dapat memanggang gambar raksasa ini (ubin kecil dari gambar besar).
Tentang bagaimana game klasik melakukannya. Saya tidak yakin mereka mungkin melakukan trik yang sama, tetapi Anda harus ingat bahwa pada saat layar berukuran 320x240 gim-gamenya memiliki 16 warna yang ketika menggunakan tekstur palattelized memungkinkan Anda untuk menyandikan 2 piksel dalam byte tunggal. Tapi ini bukan cara kerja arsitektur saat ini: D
Semoga berhasil
sumber
Potong mereka sehingga mereka tidak lagi besar, seperti yang Anda katakan. Tidak ada sihir. Game-game 2D lama itu melakukannya atau ditampilkan dalam perangkat lunak, dalam hal ini tidak ada batasan perangkat keras di luar ukuran RAM. Yang perlu dicatat adalah bahwa banyak dari game 2D tersebut benar-benar tidak memiliki latar belakang yang besar, mereka hanya menggulirnya secara perlahan sehingga mereka merasa besar.
Apa yang ingin Anda lakukan dalam pembuat game petualangan grafis adalah pra-proses gambar-gambar besar selama beberapa jenis "membangun" atau "mengintegrasikan" langkah sebelum permainan dikemas untuk dijalankan.
Jika Anda ingin menggunakan API dan pustaka yang sudah ada alih-alih menulis sendiri, saya sarankan Anda mengonversi gambar-gambar besar itu menjadi ubin selama "build" dan menggunakan mesin ubin 2D, yang jumlahnya banyak.
Jika Anda ingin menggunakan teknik 3D Anda sendiri, Anda mungkin masih ingin membagi menjadi ubin dan menggunakan 2D API yang terkenal dan dirancang dengan baik untuk menulis perpustakaan 3D Anda sendiri untuk itu, dengan cara ini Anda dijamin setidaknya mulai dengan desain API yang baik dan desain yang lebih sedikit diperlukan pada bagian Anda.
sumber
Jika Anda terbiasa dengan bagaimana tampilan quadtree dalam praktik visual, saya telah menggunakan metode yang memotong detail gambar besar menjadi gambar yang lebih kecil, relatif mirip dengan apa yang terlihat seperti bukti / visualisasi quadtree. Namun saya dibuat sedemikian rupa untuk memotong area khusus yang dapat dikodekan atau dikompres berbeda berdasarkan warna. Anda dapat menggunakan metode ini dan melakukan apa yang saya jelaskan, karena ini juga berguna.
Pada saat dijalankan, memotongnya akan membutuhkan lebih banyak memori untuk sementara dan menyebabkan waktu muat menjadi melambat. Saya akan mengatakan itu tergantung pada apakah Anda lebih peduli tentang penyimpanan fisik atau waktu buka game yang dibuat dengan editor Anda.
Load / Run Time: Cara saya melakukan pemuatan hanya memotongnya menjadi potongan-potongan berukuran proporsional. Akun untuk satu piksel pada bagian paling kanan jika jumlah piksel aneh, tidak ada yang suka gambar mereka dipotong, terutama pengguna yang tidak berpengalaman yang mungkin tidak tahu bahwa itu tidak sepenuhnya terserah mereka. Buatlah mereka setengah lebar ATAU setengah tinggi (atau 3rds, 4d apa pun) alasan untuk tidak menjadi kotak atau 4 bagian (2 baris 2 kolom) adalah karena itu akan membuat memori ubin lebih kecil karena Anda tidak akan khawatir tentang x dan y pada saat yang sama (dan tergantung pada berapa banyak gambar yang besar, itu bisa sangat penting)
Sebelum Tangan / Secara Otomatis: Dalam hal ini saya menyukai gagasan memberikan pengguna pilihan untuk menyimpannya dalam satu gambar atau menyimpannya sebagai bagian yang terpisah (satu gambar harus default). Menyimpan gambar sebagai .gif akan bekerja dengan baik. Gambar akan berada dalam satu file, dan alih-alih setiap frame menjadi animasi, gambar akan lebih seperti arsip terkompresi dari semua gambar yang sama (yang pada dasarnya adalah apa .gif sebenarnya). Ini akan memungkinkan kemudahan transportasi file fisik, kemudahan memuat:
Oh dan jika Anda menggunakan metode .gif, Anda harus mengubah ekstensi file ke sesuatu yang lain (.gif -> .kittens) demi mengurangi kebingungan ketika .gif Anda menjiwai seperti file yang rusak. (jangan khawatir tentang legalitas itu, .gif adalah format terbuka)
sumber
Ini akan terdengar jelas, tetapi, mengapa tidak membagi kamar Anda menjadi potongan-potongan kecil? Pilih ukuran sewenang-wenang yang tidak akan membenturkan kepala ke kartu grafis apa pun (seperti 1024x1024, atau mungkin lebih besar) dan pisahkan kamar Anda menjadi beberapa bagian.
Saya tahu ini menghindari masalah, dan jujur, ini adalah masalah yang sangat menarik untuk dipecahkan. Bagaimanapun, ini semacam solusi sepele, yang mungkin bisa digunakan untuk Anda.
sumber