Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Werbeanzeige
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].
Ich würde die Ressourcenverwaltung (Grafiken, Sounds, Scriftarten, ...) unabhängig von der Internationalisierung halten, da es gänzlich unterschiedliche Dinge sind und die Verwaltung der einzelnen Ressourcen auch getrennt halten. (Getrennt in dem Sinne, dass am Ende nicht unterschiedliche Ressourcen von dem gleichen Manager(-Objekt) verwaltet werden.) Will man einen Sound laden, dann will man auch enen Sound laden und keine Grafik oder Schirftart.
Zusätzlich könnte es sinnvoll sein, den Manager dahingehend zu erweitern, dass von jeder Ressource (bspw. "Grastextur") mehrere Varianten vorhanden sein können (Grafiken: 512x512, 1024x1024; Schriftarten: 12pt, 14pt, 20pt; ...), wo abhängig vom Kontext die richtige gewählt wird. Ob diese Auswahl vom Ressourcenmanager durchgeführt werden kann ist aber abhängig vom Spiel. (Wenn bspw. beim Laden des Levels bereits bestimmt werden kann, welche Ressourcen nötig sind, wäre es möglich, allerdings dürfte das höchstens bei 2D Spielen der Fall sein.)
Ein "Wörterbuch" für die Internationalisierung (bzw. dessen Einträge für die Nationalisierung) braucht entweder etwas zur Identifizierung des Textes und etwas zur Identifizierung der verwendeten Sprache, damit einzelne Texte abgerufen werden können, oder nur etwas zur Identifizierung des Textes und ein Nachladen der übersetzten Texte, wenn die Sprache bspw. in den Optionen gewechselt wird. Will man zudem den Fall abfangen, dass eine bestimmte sprache unvollständig ist (sollte möglichst nicht der Fall sein, kann unter bestimmten Umständen aber passieren), muss man bspw. auf die "Standardsprache" zurückgreifen. Es ist egal, wie man es umsetzt, man muss die "Wörtbucheinträge" anders als die anderen Ressourcen handhaben.
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
template <typename Ident, typename Type> class ResourceManager { private: std::map<Ident, Type*> cache; std::map<Ident, std::uint32_t> counter; std::mutex mutex; protected: virtual Type* fetch(Ident const & identifier) = 0; virtual void free(Type* data) = 0; public: Type* load(Ident const & identifier) { Type* data = NULL; this->mutex.lock(); auto node = this->cache.find(identifier); if (node != this->cache.end()) { if (node->second != NULL) { data = node->second; } else { data = this->fetch(identifier); node->second = data; } this->counter[identifier] += 1; } else { data = this->fetch(identifier); this->cache[identifier] = data; this->counter[identifier] = 1; } this->mutex.unlock(); return data; } void unload(Ident const & identifier) { this->mutex.lock(); this->counter[identifier] -= 1; if (this->counter[identifier] == 0) { auto node = this->cache.find(identifier); if (node != this->cache.end()) { if (node->second != NULL) { this->free(node->second); } this->cache.erase(node); } } this->mutex.unlock(); } void clear() { this->mutex.lock(); for (auto node = this->cache.begin(); node != this->cache.end(); node++) { if (node->second != NULL) { this->free(node->second); } } this->mutex.unlock(); } }; |
Aber auch bei den Übersetzungstexten gilt:
Solange du es nicht jetzt gerade brauchst, kannst du es auch später noch implementieren, wenn du es auch wirklich brauchen wirst.
Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »dot« (31.01.2014, 17:23)
Ich hatte überlegt beim Ändern der Sprache den Language-Cache zu löschen und für die neue Sprache wieder aufzubauen, so dass myLanguage.translate(key) dann die Formulierung für die neue Sprache liefert.
Ist in diesem Fall aber nicht gegeben. (Ich denke, ich konnte aber dennoch verstehen, was dein Code machen soll.)[...], sollte für das geübte C++-Auge trotzdem recht verständlich sein
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].
Wieso fetch() und free() als virtuelle Methoden implementieren, wenn das Ding eh schon ein template ist? Sollte man in der map nicht besser smartpointer speichern? Der Code ist nicht exception-safe. Wenn der Destruktor deines ResourceManager aufgerufen wird, ohne dass vorher explizit clear() aufgerufen wurde, dann leaked alles. Wenn fetch() oder free() oder sonst was eine exception wirf, bleibt das Mutex gelocked. http://en.cppreference.com/w/cpp/thread/lock_guard
Diese beiden Aspekte sollten einfach nur den Unterschied zu den anderen Ressourcen aufzeigen, da du ohnehin zwischen den verschiednen Arten an Ressourcen unterscheidest, dürften sich für dich aber keine Änderungen ergeben.
Ist in diesem Fall aber nicht gegeben. (Ich denke, ich konnte aber dennoch verstehen, was dein Code machen soll.)
Werbeanzeige