Sto scrivendo un gioco in C ++ e qualcosa che ho notato è che ho molti file di risorse che devono essere caricati dopo un particolare punto di inizializzazione.
Ad esempio, le trame OpenGL e i VAO non possono essere creati finché non c'è un contesto OpenGL corrente. Una volta caricati, non saranno mai modificati, quindi è più conveniente renderli globali.
Se questi oggetti potessero essere creati senza un contesto OpenGL corrente, sarebbe banale da fare:
const texture ground_texture = load_texture("ground.png");
const texture robot_texture = load_texture("robot.png");
const model robot_model = load_model("robot.obj");
dove texture
e model
sono semplici strutture POD contenenti (tra le altre cose) ID oggetto OpenGL.
Invece, posso farlo:
texture ground_texture;
texture robot_texture;
model robot_model;
void load_resources() {
ground_texture = load_texture("ground.png");
robot_texture = load_texture("robot.png");
robot_model = load_model("robot.obj");
}
e quindi chiama load_resources
dopo l'inizializzazione del contesto OpenGL. Ma questo richiede circa il doppio del codice (tre volte se anche questi globali vengono dichiarati anche in un file di intestazione) e perde il modificatore const
.
Si, concettualmente, potrebbe essere prodotta da un semplice script per ridurre la duplicazione - allora l'unico aspetto negativo rispetto al codice non-lavoro originale è che le variabili globali non sono const
C'è anche questo:
class texture_loader;
class model_loader;
static std::vector<const texture_loader*> tex_loaders;
static std::vector<const model_loader*> model_loaders;
class texture_loader {
mutable texture tex;
mutable bool initialized;
const char *filename;
public:
texture_loader(const char *filename)
: initialized(false), filename(filename)
{
tex_loaders.push_back(this);
}
void load() const {
tex = load_texture(filename);
initialized = true;
}
operator texture() const {
assert(initialized);
return tex;
}
};
// similarly for model_loader
const texture_loader ground_texture("ground.png");
const texture_loader robot_texture("robot.png");
const model_loader robot_model("robot.obj");
void load_textures() {
for(texture_loader *t : tex_loaders) t->load();
for(model_loader *m : model_loaders) m->load();
}
ma sembra abbastanza complessa per qualcosa che è concettualmente semplice. Inoltre, texture_loader
e model_loader
(e anything_else_loader
) dovrebbero essere esposti all'esterno del modulo di caricamento delle risorse in modo che l'altro codice possa essere in grado di utilizzare i globali.
Si tratta di un caso comune? Come è in genere risolto?