Saat ini saya sedang membuat RPG 2D dalam C ++ 11 dengan Allegro 5 dan boost.
Tujuan saya adalah entah bagaimana memperbarui pengaturan gim saya ketika opsi diubah di Menu Opsi. Saya tidak ingin memaksa pengguna untuk memulai kembali gim saya. Game lain tidak membutuhkan restart saat mengubah resolusi atau beralih dari layar penuh ke windowed, jadi game saya juga tidak. Silakan lihat tampilan yang disederhanakan dari sistem di bawah ini.
Harap dicatat bahwa saya tidak selalu ingin langsung memanggil objek Game saya dari OptionsScreen. Garis putus-putus hanyalah untuk menggambarkan efek yang saya coba capai; entah bagaimana menyebabkan pembaruan game ketika opsi diubah di bagian yang berbeda dari sistem.
Penjelasan detail
ScreenManager berisi daftar semua GameScreen
objek yang saat ini ada. Ini akan menjadi berbagai layar dalam gim termasuk popup. Desain ini mematuhi kurang lebih sampel Manajemen Status Game di C # / XNA .
The ScreenManager
berisi referensi ke saya Game
objek. The Game
objek menginisialisasi dan memodifikasi pengaturan permainan. Jika saya ingin mengubah resolusi, buka layar penuh, atau bisu volume saya akan melakukannya di Game
kelas.
Namun, LayarScreen saat ini tidak dapat mengakses kelas Game. Lihat diagram di bawah ini:
GameScreen dapat memberi sinyal tiga peristiwa onFinished
,, onTransitionStart
dan onTransitionEnd
. Tidak ada onOptionsChanged
karena hanya satu layar yang melakukan itu. ScreenManager tidak dapat mengatur penanganan acara untuk itu karena ia menangani semua layar GameScreen
s.
Pertanyaan saya adalah, bagaimana saya bisa mengubah desain saya sehingga perubahan pada OptionsMenu tidak memerlukan restart, tetapi segera diubah? Saya lebih baik meminta Game
objek saya untuk memperbarui setelah tombol terapkan diklik.
Jawaban:
Dari apa yang saya lihat, pendekatan termudah adalah membaca file opsi saat startup untuk menentukan pengaturan tampilan saat ini; kemudian, ketika layar opsi Anda ditampilkan, muat semua opsi saat ini dari file.
Ketika perubahan diselesaikan melalui tombol
apply
atauok
, mereka disimpan kembali ke file. Jika ada perubahan yang memengaruhi tampilan, beri tahu pengguna bahwa game harus dimulai ulang agar dapat diterapkan.Ketika game dimulai kembali, pengaturan tampilan (sekarang baru) dibaca lagi dari file.
--EDIT--
Annd ... itu akan membantu jika aku memperhatikan kalimat terakhir itu. Anda tidak ingin harus memulai ulang. Membuat segalanya sedikit lebih sulit tergantung pada implementasi Anda dan Perpustakaan Grafik back-end Anda.
IIRC, Allegro memiliki panggilan fungsi yang memungkinkan Anda untuk mengubah pengaturan tampilan dengan cepat. Saya belum bangun pada Allegro 5 dulu, tapi saya tahu Anda bisa di 4.
sumber
Inilah yang saya lakukan untuk permainan saya. Saya memiliki 2 fungsi terpisah untuk menginisialisasi barang, 'init' dan 'reset'. Init hanya dipanggil sekali saat startup dan melakukan hal-hal yang tidak bergantung pada pengaturan apa pun, seperti memuat aset utama. Reset melakukan hal-hal seperti meletakkan UI berdasarkan resolusi layar, demikian disebut setiap kali pengaturan berubah.
Saya tidak terbiasa dengan Allegro, tetapi jawaban saya cukup umum, jadi saya harap ini membantu Anda atau orang lain dengan masalah yang sama.
sumber
Tanpa mengacaukan arsitektur Anda saat ini, saya melihat dua cara. Pertama, Anda bisa menyimpan pointer ke
Game
instance diOptionsScreen
kelas. Kedua, Anda dapatGame
kelas mengambil pengaturan saat ini dalam interval yang diberikan, katakan setiap detik.Untuk benar-benar beradaptasi dengan pengaturan baru,
Game
kelas harus mengimplementasikan semacam fungsi reset yang mengambil pengaturan saat ini dan menginisialisasi ulang berdasarkan itu.Untuk solusi bersih, Anda memerlukan semacam manajer global, sehingga lebih banyak upaya untuk diterapkan. Misalnya sistem acara atau sistem pesan. Sangat berguna untuk membiarkan kelas berkomunikasi tanpa ikatan yang kuat seperti agregasi atau komposisi, dan sebagainya.
Dengan manajer acara global, perusahaan
OptionsScreen
dapat secara global memecat acara redraw yangGame
telah terdaftar untuk didengarkan sebelumnya.Secara umum Anda dapat mengimplementasikan kelas manajer yang menyimpan acara dan panggilan balik mendengarkannya di peta hash. Kemudian Anda dapat membuat satu instance dari manajer itu dan meneruskan pointer ke komponen Anda. Menggunakan C ++ yang lebih baru cukup mudah karena Anda dapat menggunakan
std::unordered_map
sebagai peta hash danstd::function
untuk menyimpan panggilan balik. Ada beberapa pendekatan berbeda yang dapat Anda gunakan sebagai kunci. Misalnya, Anda bisa membuat string manajer acara berbasis yang membuat komponen lebih mandiri. Dalam hal ini Anda akan menggunakanstd::string
sebagai kunci di peta hash. Saya pribadi suka ini dan ini jelas bukan masalah kinerja, tetapi kebanyakan sistem acara tradisional bekerja dengan acara sebagai kelas.sumber
Nah, ini adalah beberapa kasus spesifik dari pola Observer.
Ada solusi yang melibatkan panggilan balik. Ini adalah cara terbaik untuk melakukan ini jika Anda ingin kopling longgar, dan saya pikir itu juga yang terbersih. Ini tidak akan melibatkan manajer global atau lajang.
Pada dasarnya, Anda harus memiliki semacam
SettingsStore
. Di sana Anda menyimpan pengaturan. Saat Anda membuat layar baru, mereka membutuhkan pointer ke toko. Dalam halOptionsScreen
ini akan memodifikasi beberapa nilai pengaturan itu sendiri. Dalam halGameScreen
ini hanya akan membacanya. Jadi, dalam gim Anda, Anda hanya akan membuat satu instance, yang akan diteruskan di semua layar yang membutuhkannya.Sekarang,
SettingsStore
kelas itu akan memiliki daftarnotifiables
. Mereka adalah kelas yang mengimplementasikanISettingChanged
antarmuka tertentu . Antarmuka akan menjadi sederhana yang berisi metode berikut:Kemudian di layar Anda, Anda akan menerapkan logika untuk setiap pengaturan yang Anda pedulikan. Kemudian, tambahkan diri Anda ke toko untuk diberitahu:
store->notifyOnChange(this);
. Ketika suatu pengaturan diubah, callback dipanggil dengan nama pengaturan. Nilai pengaturan baru kemudian dapat diambil dari menuSettingsStore
.Sekarang, ini dapat ditambah dengan ide-ide berikut:
SettingsStore
(string const) untuk mencegah string copy-paste di sekitar.sumber
Baca pengaturan Anda dari file menjadi variabel. Miliki track Screen Manager Anda jika layar itu baru saja muncul dari layar Options, dan jika ya, muat ulang pengaturan Anda dari variabel. Saat pengguna keluar dari game Anda, tulis pengaturan di variabel kembali ke file.
sumber