Cara terbaik untuk menyimpan variabel game-wide

23

Saya memiliki layar opsi untuk hal-hal seperti kesulitan, resolusi, layar penuh, dll., Tetapi saya berjuang untuk menemukan cara "terbaik" untuk menyimpan / mendapatkan variabel-variabel ini saat run-time.

Saat ini, saya telah mengimplementasikan Constantskelas yang berisi semua GameOptionenum, tetapi bagaimana cara saya memilih default untuk semua opsi ini? Juga, bagaimana saya mendapatkan enum yang saat ini dipilih?

Mengenai resolusi, khususnya, saya telah memutuskan untuk menyimpan nilai-nilai, tetapi saya tidak yakin bagaimana cara mendapatkan nilai-nilai default, atau saat ini disimpan. Arah apa pun akan bagus; Terima kasih! :)

namespace V1.test.RPG
{
  public class GameOptions
  {
    public enum Difficulty { EASY, MEDIUM, HARD }
    public enum Sound { ON, QUIET, OFF }
    public enum Music { ON, QUIET, OFF }
    public enum ResolutionWidth
    {
        SMALL      = 1280,
        MEDIUM     = 1366,
        LARGE      = 1920,
        WIDESCREEN = 2560
    }
    public enum ResolutionHeight
    {
        SMALL      = 800,
        MEDIUM     = 768,
        LARGE      = 1080,
        WIDESCREEN = 1080
    }
    public Boolean fullScreen = false;
  }
}

NB: Saya bertanya pada SO dan mereka menunjuk saya ke tempat ini. Ada komentar di sana, tetapi saya ingin mendengar berbagai cara melakukannya / cara yang paling sering digunakan.

R-nold
sumber
1
Anda bertanya di tempat yang tepat; siapa pun yang mengirim Anda ke sini salah. Saya menjawab pertanyaan itu untuk membantu Anda, tetapi ini bukan pertanyaan khusus pengembangan game, ini adalah pertanyaan pemrograman umum.
jhocking
Saya baru saja membaca utas SO; Saya suka jawaban Scott Chamberlin.
jhocking
@jhocking Saya menunjuknya dengan cara ini kalau-kalau ada aspek yang khusus untuk pengembangan game yang mungkin berbeda dari aplikasi biasa. Saya juga mengira kalian mungkin sudah memiliki T&J kanonik tentang topik ini karena sudah umum.
Chris Hayes
Bersinggungan dengan pertanyaan aktual tentang global, tolong jangan menganggap ada set resolusi tetap di luar sana.
Lars Viklund

Jawaban:

32

Perencanaan untuk tumbuh:
Konstanta hard-coded baik untuk proyek-proyek kecil tetapi, pada akhirnya, ketika ukuran perangkat lunak Anda bertambah, Anda akan berharap Anda dapat mengubah pengaturan tersebut tanpa harus mengkompilasi ulang semuanya. Ada banyak kali Anda ingin mengubah pengaturan saat permainan sedang berjalan dan Anda tidak dapat melakukannya dengan konstanta yang dikodekan.

CVars:
Setelah proyek Anda tumbuh, Anda mungkin ingin melihat CVAR . CVAR adalah "variabel cerdas", sehingga dapat dikatakan, bahwa Anda dapat memodifikasi selama waktu berjalan melalui konsol, terminal, atau UI. CVAR biasanya diimplementasikan dalam hal objek yang membungkus nilai yang mendasarinya. Objek dapat, kemudian, melacak nilai serta menyimpan / memuatnya ke / dari file. Anda dapat menyimpan objek CVAR ke peta untuk mengaksesnya dengan nama atau pengenal unik lainnya.

Untuk menggambarkan konsep sedikit lebih jauh, pseudo-code berikut adalah contoh sederhana dari tipe CVAR yang membungkus intnilai:

// just some flags to exemplify:
enum CVarFlags {
    CVAR_PERSISTENT, // saved to file once app exits
    CVAR_VOLATILE    // never saved to file
};

class CVar {
public:
    // the constructor registers this variable with the global list of CVars
    CVar(string name, int value, int defaultValue, int flags);

    int getValue();
    void setValue(int v);
    void reset(); // reset to the default value

    // etcetera...

private:
    int flags; // flags like: save-to-file, etc.
    int value; // the actual value
    int defaultValue; // the default value to reset the variable to
};

// global list of all CVars:
map<string, CVar> g_cvars;

Akses global:
Pada contoh di atas, saya berasumsi bahwa konstruktor CVarselalu mendaftarkan variabel dengan cvarspeta global ; ini cukup berguna, karena memungkinkan Anda untuk mendeklarasikan variabel seperti:

CVar my_var = new CVar("my_var", 0, 42, CVAR_PERSISTENT);

Variabel itu secara otomatis tersedia di peta global dan Anda dapat mengaksesnya dari tempat lain dengan mengindeks peta dengan nama variabel:

CVar v = g_cvars.find("my_var");

Kegigihan:
Ketika game dimatikan, beralih peta dan simpan semua variabel yang ditandai CVAR_PERSISTENT, ke file. Lain kali gim dimulai, muat ulang.

Hukum kasus:
Untuk contoh yang lebih spesifik dari sistem CVAR yang kuat, lihat implementasi yang ditampilkan di Doom 3 .

Glampert
sumber
4

Pertama-tama enum mendefinisikan nilai apa yang bisa , bukan nilai apa itu . Dengan demikian Anda masih perlu mendeklarasikan variabel lain setelah Anda mendeklarasikan enum. Sebagai contoh:

public enum Sound
{
    ON,
    QUIET,
    OFF
}

public Sound soundValue;

Dalam contoh ini, Anda sekarang dapat mengatur soundValueke ON, QUIET, atau OFF.


Maka Anda masih perlu menyusun kode Anda sehingga bagian lain dari kode Anda dapat mengakses objek "pengaturan" ini. Saya tidak tahu apakah Anda perlu bantuan dengan bagian itu juga, tetapi pola umum untuk mengatasi masalah ini termasuk lajang (yang disukai saat ini) atau pelacak layanan atau injeksi ketergantungan.

jhocking
sumber
1

solusi glampert sangat lengkap, tetapi saya akan menambahkan pengalaman pribadi saya.

Saya mengalami masalah yang sama, dan solusi saya adalah menggunakan kelas Variabel statis.

Kelas Variabel secara internal menyimpan peta dari string ke string (sejauh ini semua variabel saya hanya string) dan diakses melalui getter dan setter.

Intinya adalah bahwa mendapatkan akses ke variabel global dapat memperkenalkan semua jenis kesalahan halus karena bagian kode yang sama sekali tidak terkait tiba-tiba mengganggu satu sama lain.

Untuk menghindari ini, saya memberlakukan semantik berikut: menggunakan setmetode melempar pengecualian jika variabel dengan nama itu sudah ada di kamus, danget menghapus variabel dari kamus sebelum mengembalikannya.

Dua metode tambahan memberikan apa yang Anda harapkan, setAndOverwritedangetAndKeep . Maksud dari semantik dari metode lain adalah Anda dapat dengan mudah menemukan kesalahan dari jenis "metode ini seharusnya menginisialisasi variabel ini, tetapi metode lain melakukannya sebelumnya".

Untuk menginisialisasi kamus, variabel awal disimpan dalam file json, dan kemudian dibaca saat permainan dimulai.

Sayangnya saya belum terlalu jauh dengan permainan saya, jadi saya tidak bisa bersaksi untuk kekokohan pendekatan ini. Meski begitu, mungkin bisa memberikan sesuatu yang menarik di atas CVAR.

angarg12
sumber