Advertisement

Is there a better way to store game concept data types?

Started by January 15, 2022 08:18 PM
2 comments, last by AngleWyrm6 2 years, 9 months ago

So I have a lot of stuff I need to load for my project that is a static set of data that is assigned an id, name, and image, I think basically the kind of thing you'd assign const to.

For instance “Aptitudes” which are the skills of a character in a magical discipline. So it has an ID, but most importantly a name like Summoning, and an image for the icon that goes in the UI.

Then the character has an “AptitudeValue” that is the type plus their malleable personal capability stored in an int.

Similarly I have some interaction details that are CommitmentType, which is connected to a Commitment. So something might be a promise or a vow or an oath. These have distinct meanings in the game logic. So a CommitmentType might be an “Oath Of Allegiance”.

Both of these inherit from Identity which holds the ID, name("Oath Of Allegiance"), and image. The CommitmentType class holds a string, that will be one of the types(oath, vow, promise, etc).

I have a primary object, the WorldManager that holds mostly pointers to stuff. For the purposes of this thread it has Managers, this may not be the proper jargon usage, for different Types. For instance CommitmentTypesManager. That looks like this:

//=============================================

// CommitmentTypesManager

//=============================================

class CommitmentTypesManager {

private:

std::vector<CommitmentType*> commitmentTypes;

public:

int getCommitmentTypeCount() {return commitmentTypes.size();}

CommitmentType *getCommitmentType(int i) {return commitmentTypes[i];}

CommitmentType *getCommitmentTypeById(int id);

CommitmentType *getCommitmentTypeByName(std::string name);

CommitmentType *addCommitmentType(int id, std::string name);

};

The actual commitment instances will have variable data that will be set during gameplay:

//=============================================

// Commitment

//=============================================

class Commitment {

private:

CommitmentType *type;

int duration;

int deadline;

Character *maker;

Character *recipient;

public:

std::string description();

CommitmentType *getType() {return type;}

void setType(CommitmentType *newType) {type = newType;}

};

Is there a more useful way to store the non-variable data for AptitudeTypes or CommitmentTypes and similar classes? Will it matter for performance at all? Is there a more generally known specific term for these types of constructs rather than Manager? I know it has a jargon meaning but I can't recall if it is appropriate in this context.

AoS said:
So I have a lot of stuff I need to load for my project that is a static set of data that is assigned an id, name, and image, I think basically the kind of thing you'd assign const to.

There are several approaches, and the one you're following is okay for small projects and small groups of programmers. Hard-coded values can work well for programmers who are rebuilding the game each time they want to modify something, and are comfortable making the changes. As projects grow you'll want those values to come from data instead. It adds some complexity to the systems, but enables designers, producers, artists, and other teammates to make changes without rebuilding the game. It's a tradeoff because it requires more work to support, much more work if you're building nice tools, but if it enables more people to work on the project or to make changes with a simple editor rather than a long rebuild, it saves time overall.

AoS said:
std::vector<CommitmentType*> commitmentTypes;

Is there a more useful way to store the non-variable data for AptitudeTypes or CommitmentTypes and similar classes?

You can store the items as you did, but it feels weird to me to store it that way. Usually it's better to let the container manage the memory rather than you having pointers to objects where you manage the memory yourself. Ultimately you need to figure out the life cycle of objects, and the thing that owns them needs to be aware of it, and everything else rely on pointers or smart pointers to it.

I'd be tempted to use a std::unordered_map using the ID as the key and your data about it (not a pointer to it) as the value, since with that container the objects don't move around as items are added and removed, and lookup is quite fast.

If you don't have many of them, you could also just use a flat array of structures. Less elegant for growth, but for a single person or hobby project the developer time and simplicity is more important than flexibility. I'd also be tempted to put the IDs into an enum for basically the same reason. Adding to the enum causes a recompile, but the rules are enforced by the compiler. It doesn't enable tools or other people to modify values, but as a solo project the convenience and personal performance are generally more important.

AoS said:
Will it matter for performance at all?

Not at the scale you're talking here. Once you start talking about thousands or tens of thousands performance begins to matter. When you start to reach that point you need to think about access patterns, data locality, and cache effects.

AoS said:
Is there a more generally known specific term for these types of constructs rather than Manager?

Beware of ‘manager’ because it tends to be too generic as a catch-all. It is better if you can break out specific functionality when possible, store, cache, pool, collection, mediator, etc. Sometimes “Manager”, really is the best term. A connection manager might have a connection pool, various states of connected in use, connected unused, disconnected, connecting and disconnecting, might contain tools for sorting and prioritizing, might contain mappings for connections with other systems, and in that scenario “ConnectionManager” is as good a name as any.

If it were ONLY me, or only a handful of programmers, I'd go with enums and static const arrays for data tables. If you're making something for a larger team I'd start with unordered_map collections with values loaded from files and be thoughtful of at what point you'd need to extend the functionality beyond what the standard library gives you for free.

Advertisement

Here's a Java method to load data in from a CSV file. The data is maintained in a spreadsheet, and the code reads the CSV file into records (beans) in an in-game list.

This topic is closed to new replies.

Advertisement