# Associate a texture to an object (from a data-model, not graphical point of view)

I'm writing a roguelike where objects and floor can be made of different materials. For instance, let's say we can have a wooden chair, an iron chair, a golden chair, and so on.

I've got an Object class (I know, the name is terrible), which is more or less using a composite pattern, and a Material class. Material have different important properties (noise, color...). For the time being, there are 5 different instances of materials, created at the initialization of the game.

How would connect an instance of Object with one of the 5 instances of materials ? I see three simple solutions :

• Using a pointer. Simple and brutal.
• Using an integer material-id, then get the materials out of a table when engine manipulates the object for various purposes (display, attack analysis, etc.). Not very beautiful, I think, and not very flexible.
• Using an integer material-id, then get the materials out of a std::map. A bit more flexible, but still not perfect.

Do you see other possibilities ? If not, what would you choose (and why) ? Thanks in advance !

• This needs a different title but I can't think of one... Mar 1 '11 at 18:58
• Associate a tactile texture? Mar 1 '11 at 19:46
• @Ricket : I agree, but I can't find it either :) Mar 2 '11 at 9:40

It seems you want new types of Materials to be able to be created at runtime. Then I don't see the problem with having a pointer to the Material of the object; it's how I would do it. Perhaps elsewhere in the program (e.g. in the factory class which creates these Object instances) you would have an array of all the Materials, to keep track of them and allow for choosing between them. Also you would need to either never delete a Material once it's created, or keep track of the references to a material so that if you want to delete the material then you reassign new materials onto all the objects which were previously using that material. You certainly don't want to delete a Material in memory, only to have Objects still pointing to that memory location which is now invalid!

The problem with the integer ID which is a position of an array, for example, is if that array is manipulated, for example if a material is deleted, then you need to either put a 'null' in that position and never use it again, or you need to loop among the objects and change their material ID when you change the array. So for example if you have three materials, and an object points to material 1, then if you delete material 1 you need to either put a null in that place, or change the object id to e.g. -1 before you allocate a new material in position 1 (or else the object is magically given a new material!).

Also an std::map seems like unnecessary overhead in this case. It seems to me that you don't really need the map when you could use a pointer and reference counting as mentioned above. You could certainly use it though, keeping in mind similar downfalls such as mentioned in the previous paragraph; e.g. you still need to make sure the IDs are unique among all materials deleted or not, or else you could get objects whose materials get reassigned just because the material gets deleted and a new one gets put in with the same ID as the old one.

If however Materials can't change at runtime, you could of course make an enum with the material type, and the object would have an element of that enum (or a pointer to that element; my c++ is rusty).

• Thanks for a long and well-thought answer. I want to load dynamically the materials (so I can't go with enum), but only at the beginning of the program. After that, they won't change. I'm going to go with a pointer, and a factory. Mar 2 '11 at 9:42
• That eliminates some of the runtime problems then, such as making sure the pointers stay valid and such (since you won't delete Materials at runtime). Do make sure and consider, however, what happens when you save an object to disk, and then you improve the game, develop new materials and add them to the list which is loaded on startup. Plan your materials carefully and make sure that when you change the list, don't reorder them or else objects loaded from disk will load with the wrong material (assuming they only store an integer index into the materials array). Mar 2 '11 at 14:49

Use the pointer. You haven't identified any requirements of the system beyond that you should be able to go from Object to Material, and the pointer is the simplest and most direct approach by some way.

From my point of view, array indices and pointers are two flavors of the same thing -- and both are simple and direct, which is good for a game.

You could introduce an abstraction layer, and make this more complicated, but you have not identified any requirements to help design such a layer.

In fact, as near as I can tell, you only have 5 materials, and they will not change.

Anyways, I see nothing wrong with using a pointer, and I see nothing wrong with using an array index. If you do see something wrong with either of those, I think that that means you have requirements which you have not expressed here.

The OO way to do it is to create each new object with a material and colour as properties by instance passing. For example in Python:

class Chair(Object):
def __init__(self, colour, material, position):
self.colour = colour
self.material = material
self.position = position
...


You would then create the object with those properties:

chairmaterial = Material("wood")
mychair = Chair(COLOUR_GREEN, chairmaterial, (0,0))


Rendering could then just be dependent on the Chair class for shape, and the material and colour for colour and texture.