Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » OOP Design and Resource Management

This thread is locked; no one can reply to it. rss feed Print
 1   2   3 
OOP Design and Resource Management
AMCerasoli
Member #11,955
May 2010
avatar

axilmar said:

In the real world, we should reuse as much code as possible.

Who is saying the contrary?. A resource manager is exactly the best way to reuse code.

Quote:

So if all a class does is change the images, why not have one class and load the images to the object externally using a function? it makes more sense.

Not in OOP. I made that just as an example, I would change more than just an image if I were creating a new class.

Quote:

I've yet to see an example of how a resource manager makes it easier. Anyone care to post one?

I can't believe that you're saying that... I'm definitively not going to take the time to explain you how a resource manager makes things easier, cleaner and if you are doing it in a different thread even faster, because:

  1. You haven't considered a game with more than 20 images and...

  2. You attitude seems very stubborn.

I can't believe that you, as a experienced programmer, haven't realize of the benefits of a resource manager. :-/

Audric
Member #907
January 2001

axilmar said:

Audric said:

Sharing code between bullet and another class is irrelevant

Reuse is irrelevant? since when?

It's irrelevant to the issue that was discussed so far.

axilmar said:

Audric said:

The point of a resource manager is to get a kind of cache, where the first demander of a resource causes the load, and any other demander will be given a reference to the same resource, avoiding a second disk access and uncompress.

A variable is good enough for this purpose. No need for a cache.

You don't seem to understand that the resource manager is generic and dynamic. You write it with for example a nice std::map<string, BITMAP *>, and you'll never have to modify one line of its code while you write the game and use more and more resources.

bamccaig
Member #7,536
July 2006
avatar

axilmar said:

That's not management, that's interactions based on rules.

What enforces the rules? A "manager" of some sort. Call it "God", call it the universe, call it whatever you want. In the real world we don't know what is responsible, but in your game you need something to be responsible. You can have a hundred different objects all enforcing little rules or you can have higher-level objects that enforce all (or all related) rules. These higher-level objects have the advantage of being able to see more of the big picture too, without violating any design principles.

axilmar said:

I didn't say otherwise. Still, a bitmap should use the image file internally to load itself from disk. That's proper OO.

A bitmap is a bitmap. It is a map of bits. ;) That's all it is. It doesn't need to know anything of files, file formats, file systems, file permissions, etc. It can, but that doesn't mean that it should. It should ideally do one thing and do it well. It's already a map of bits. It doesn't need to be a file reader/parser as well. :P

axilmar said:

That's what smart pointers are for. There is nothing awkward to it.

Compared to other languages, it is awkward. :)

axilmar said:

Then you would need a person object that knows everything. Not good OOP.

No, you wouldn't. You could have a higher-level class, lets call it God (for a laugh), that knows about both a Person and a Hammer. Person might know that it hits a Nail with a Hammer to pound it into Lumber, but its not the Person itself that repositions the Nail in the Lumber. :) It's the Game or the World or the God or the PhysicsEngine.

axilmar said:

And therefore a resource manager is redundant.

The idea behind a resource manager is that its a repository of resources that can be easily passed around the application, granting access to shared resources (potentially with restrictions or limitations). You haven't shown anything equivalent. Anything equivalent that you do propose will be a resource manager with a different name. Even if you inline the code, it's still a resource manager. Just a poorly organized one.

axilmar said:

...and the particular physics of the world belong to the Bullet subclass.

If that doesn't set off design alarm bells I don't know what will. :-/

axilmar
Member #1,204
April 2001

Not needing to keep track of duplicate bitmaps accross all yout program manually

That's sweet for GUIs, where bitmaps are defined externally, but not for games, where bitmaps are defined internally. You could do the same by a global variable, or a struct that contains a global variable. It does not seem that what you mention requires a resource manager.

Quote:

the resource manager automatically frees any resource that will not be used by the new map

Smart pointers handle this gracefully.

Quote:

How do you do this without a resource manager?

How about simple functions that load resources when required, plus smart pointers to resources? I see no need for a resource manager. The resource manager tests, at each request, if the resource is loaded, and if not, it loads the resource. I don't think that this is necessary for the simple games. Perhaps it is necessary for dynamically loaded games, where resources are loaded as the game runs. But then, the resource manager will do a lot more things, like keeping stats of video memory occupied, keeping important textures around etc.

jmasterx said:

This way each class that might need a Bitmap just requests it from the RM and the class calls releaseBitmap() once it is destroyed and so resources are never duplicated and only freed when they are no longer needed.

Why request the bitmap from the resource manager and not simply access it from a struct? when the bitmap is needed, it is usually already loaded in another point in the code.

Who is saying the contrary?. A resource manager is exactly the best way to reuse code.

A resource manager is not related to code reuse at all, unless the same requests are meaningful in different games, which is a very rare case.

Quote:

You haven't considered a game with more than 20 images and...
I can't believe that you, as a experienced programmer, haven't realize of the benefits of a resource manager.

The first thing I coded for my GUI was the resource manager. However, a find a resource manager for a game a strange idea.

I prefer not to do this:

class Bullet {
public:
    Bullet(ResourceManager &rm) {
        m_bitmap = rm.getBitmap("explosion");
    }
};

I prefer this:

Resources res;
res.m_explosion_bitmap = load_bitmap("explosion.png");
class Bullet {
public:
    Bullet(Resources &res) {
        m_bitmap = res.m_explosion_bitmap;
    }
};

In other words, I prefer resources loaded in a step prior to game objects being constructed, for various reasons (which I can explain, if you wish).

Audric said:

It's irrelevant to the issue that was discussed so far.

Reuse is not irrelevant. We are essentially discussing good design, and reuse is one part of good design.

Quote:

You don't seem to understand that the resource manager is generic and dynamic. You write it with for example a nice std::map<string, BITMAP *>, and you'll never have to modify one line of its code while you write the game and use more and more resources.

You may not have to modify the resource manager code, but you certainly have to modify the loading resources code. So, if you have to modify the loading resources code, then you don't need a resource manager.

Do you, in your games, load bitmaps dynamically, when first requested? I don't, and I can't imagine anyone doing so in a game, unless you do a game so heavily textured that you need to load textures from disk dynamically, ala Rage. But then, your resource manager code is not a simple std::map<string, BITMAP *>, it's a lot more complicated.

bamccaig said:

What enforces the rules?

The program itself.

Quote:

These higher-level objects have the advantage of being able to see more of the big picture too, without violating any design principles.

And then you complicate the design to the degree that your code doesn't make sense and cannot be reused or modified a few weeks later.

Quote:

It can, but that doesn't mean that it should. It should ideally do one thing and do it well. It's already a map of bits. It doesn't need to be a file reader/parser as well. :P

I didn't say that. I agree, a bitmap doesn't need to be a file reader/parser. However, a bitmap shall internally use a file object that is a file reader/parser. It's important be able to tell the bitmap "bitmap, load yourself from this resource". If you can't do that, the responsibility of supplying an appropriate resource falls onto you, and suddenly you must know two things instead of one.

Quote:

Compared to other languages, it is awkward.

No, these other languages are the awkward ones. Assuming that you are talking about languages with garbage collection and non-deterministic resource management.

Quote:

No, you wouldn't. You could have a higher-level class, lets call it God (for a laugh), that knows about both a Person and a Hammer. Person might know that it hits a Nail with a Hammer to pound it into Lumber, but its not the Person itself that repositions the Nail in the Lumber. :) It's the Game or the World or the God or the PhysicsEngine.

Absolutely wrong design, and very distant from the OO theory.

Quote:

The idea behind a resource manager is that its a repository of resources that can be easily passed around the application, granting access to shared resources (potentially with restrictions or limitations).

As I said above, a resource manager makes sense for the GUI, but not for a game.

Quote:

You haven't shown anything equivalent.

I did. See above.

Quote:

Anything equivalent that you do propose will be a resource manager with a different name. Even if you inline the code, it's still a resource manager. Just a poorly organized one.

What I propose is not equivalent, and therefore not a resource manager ;-).

Quote:

If that doesn't set off design alarm bells I don't know what will.

That's proper OO: new behaviors are introduced by subclassing, honoring the is-a relationship.

Where and how did you learn OOP?

SiegeLord
Member #7,827
October 2006
avatar

axilmar said:

I prefer this:

Resources res;
res.m_explosion_bitmap = load_bitmap("explosion.png");
class Bullet {
public:
    Bullet(Resources &res) {
        m_bitmap = res.m_explosion_bitmap;
    }
};

I'm sure others will tear you apart on most of your other nonsense, but this I just had to address myself. Do you seriously suggest a Resources class with thousands of members, one for each object type? What if your game is extensible via configuration files (like any game should be)?

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

axilmar
Member #1,204
April 2001

SiegeLord said:

I'm sure others will tear you apart on most of your other nonsense, but this I just had to address myself. Do you seriously suggest a Resources class with thousands of members, one for each object type?

"Nonsense"...please. Hear me out first.

I do seriously suggest a Resources class with thousands of members. Here are the advantages of this solution:

  • type safety. If you user a resource manager, and have thousands of resources, type errors will not be caught until you run the game and test each and every resource. With my solution, type errors will be limited to the resource loading code.


  • name safety. If you user a resource manager, and have thousands of resources, managing thousands of resource name strings scattered all over the code quickly becomes a liability. With my solution, if you misspell a resource name, expressed as a variable identifier, the code will not compile.


  • CPU and ram performance. With the resource manager, searching a map by using a string as a key can seriously hurt performance, especially if this action is repeated at every frame. With my solution, none of this happens, and the CPU cycles and memory can be used for other purposes.


  • GPU and vram performance. If bitmaps are not loaded all together in one phase, i.e. if bitmaps are loaded the first time they are needed, and if there are many many bitmaps, then there is the danger of the video ram being exhausted, and perhaps important bitmaps may be loaded in ram instead of vram. Creating a system where textures are loaded quickly from disk requires extremely fast disks, otherwise the video performance will be problematic. See the recently released game "Rage" for such an example: its megatexture solution failed spectacularly on PCs with slow disks. When the player turned around quickly, the textures could not be loaded as fast as needed, resulting in very bad graphics that were slowly and visibly replaced with good graphics.


  • player convenience. If bitmaps are loaded as they needed from the disk, there might be a case of slowdown during the action, i.e. the framerate dropping because of I/O. I don't like that in games, and most other people wouldn't like that either. So, as a programmer, I prefer to load all the appropriate files before engaging on the action. But loading all the files at one place defeats the purpose of a resource manager.

Now that I've said all this, I think that it is valid to say that there is no point in a resource manager in a video game, when a resource manager can have all the above-mentioned disadvantages.

A Resources class may not be a monolithic class, if you are worried over built times.

Quote:

What if your game is extensible via configuration files (like any game should be)?

Extensible with what? new graphics and sounds? my approach still uses configuration files to load the resources, so I fail to see where is the problem.

Except if you mean other extensions via configuration files that I am unaware of.

Oscar Giner
Member #2,207
April 2002
avatar

axilmar said:

That's sweet for GUIs, where bitmaps are defined externally, but not for games, where bitmaps are defined internally.

What!? Any medium sized game will have the bitmaps defined externally... For very small games it's ok to have the resources hardcoded into the code, but you don't want to do that for anything bigger.

Quote:

Smart pointers handle this gracefully.

Not in the scenario of bitmaps defined externally.

Quote:

A resource manager is not related to code reuse at all, unless the same requests are meaningful in different games, which is a very rare case.

A resource manager is just that, and it can be easily reused for different games.

Quote:

In other words, I prefer resources loaded in a step prior to game objects being constructed, for various reasons (which I can explain, if you wish).

And I agree with that, and I don't see how that has anything to do with using or not a resource manager :o.

<edit>

axilmar said:

type safety. If you user a resource manager, and have thousands of resources, type errors will not be caught until you run the game and test each and every resource. With my solution, type errors will be limited to the resource loading code.

name safety. If you user a resource manager, and have thousands of resources, managing thousands of resource name strings scattered all over the code quickly becomes a liability. With my solution, if you misspell a resource name, expressed as a variable identifier, the code will not compile.

But then resources must be hardcoded into the game code. You want to separate code from level dessign and art. What you say is only useful for small games.

Quote:

CPU and ram performance. With the resource manager, searching a map by using a string as a key can seriously hurt performance, especially if this action is repeated at every frame. With my solution, none of this happens, and the CPU cycles and memory can be used for other purposes.

You can perfectly store a pointer to the resource once, so you don't need to access the map each frame.

Quote:

See the recently released game "Rage" for such an example: its megatexture solution failed spectacularly on PCs with slow disks.

Nope, the problem was elsewhere (there was a bug that affected 2 core CPU's, and also bad video drivers). After the updates I get constant 60 fps on my 3 years old CPU and HD. The slowdown wasn't because of the HD (it works fine on XBOX360 and PS3, and I don't think their HD's are that fast), it was because of way too high CPU usage that Id solved in the first patch (and also to workaround a bug in ATI drivers that lead to a very big CPU usage by the driver when streaming the textures).

Quote:

player convenience. If bitmaps are loaded as they needed from the disk, there might be a case of slowdown during the action, i.e. the framerate dropping because of I/O. I don't like that in games, and most other people wouldn't like that either. So, as a programmer, I prefer to load all the appropriate files before engaging on the action. But loading all the files at one place defeats the purpose of a resource manager.

You can force loading/unloading resources only at level change or when you want. And no, that doesn't defeat the purpose of a resource manager.

SiegeLord
Member #7,827
October 2006
avatar

axilmar said:

Extensible with what? new graphics and sounds? my approach still uses configuration files to load the resources, so I fail to see where is the problem.

Except if you mean other extensions via configuration files that I am unaware of.

A concrete example. In my game I have an objects folder where you define new game objects, like so:

File: slime.obj

class = land_creature
sprite = slime

File: slime_colossus.obj

class = land_creature
sprite = colossus

Internally there's just one class (LandCreature), but the configuration files control the sprite + behaviour of the specific type of the object.

How would you handle that in your hard-coded Resource class?

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Edgar Reynaldo
Member #8,592
May 2007
avatar

Oscar already covered this, but I thought I would point it out as well - using a resource manager doesn't mean you can't load all your resources at the same time.

You can preload everything you want to, and then just get references to it later, as well as use an UnloadAll method to clear levels.

axilmar
Member #1,204
April 2001

What!? Any medium sized game will have the bitmaps defined externally... For very small games it's ok to have the resources hardcoded into the code, but you don't want to do that for anything bigger.

Yes, bitmaps will be defined externally. But you will need to address those bitmaps somehow from your code. So, you don't get away with hardcoding some references in the code anyway.

Quote:

Not in the scenario of bitmaps defined externally.

Please elaborate. In my opinion, an std::shared_ptr<BITMAP *> will successfully keep a bitmap around until no longer needed. Why do you think otherwise?

Quote:

A resource manager is just that, and it can be easily reused for different games.

I repeat: the resource manager class can be reused, but the code that uses the resource manager cannot be reused, as it is custom per game.

Quote:

And I agree with that, and I don't see how that has anything to do with using or not a resource manager

Someone suggested earlier that a resource manager is used in cases like this:

class Bullet {
public:
    BITMAP *bmp1;
    Bullet(ResourceManager &rm) {
        bmp1 = rm.getBitmap("bmp1");
    }
};

I disagree with the above, i.e. loading graphics dynamically, when game objects are created, for the reasons I explain in my previous post.

Quote:

But then resources must be hardcoded into the game code. You want to separate code from level dessign and art. What you say is only useful for small games.

Some kind of hardcoded reference is required at code level. It cannot be avoided. The resources will not be magically loaded.

Quote:

You can perfectly store a pointer to the resource once, so you don't need to access the map each frame.

But that's what I said and people told me it was nonsense.

Quote:

Nope, the problem was elsewhere

Ok. Thanks for the info.

Quote:

You can force loading/unloading resources only at level change or when you want. And no, that doesn't defeat the purpose of a resource manager.

But if you don't need dynamic loading of resources, and if you want type and name safety that the resource manager doesn't provide, then why do you need a resource manager? I don't see any reason for it.

SiegeLord said:

How would you handle that in your hard-coded Resource class?

Where did I say that in my code, resources will be hardcoded? I never said that.

Anyway, I'd load the objects from the config file. But, somewhere in the code, there would be a reference to the slime object, like this:

LandCreature slime = resourceManager.loadObject("slime");

So the above can be happily replaced with:

LandCreature slime = Object::load("slime");

If I had a config file, I'd do this:

LandCreature slime = Object::load(al_get_config_value("slime"));

You probably are talking about a configuration file, not a resource manager.

Oscar already covered this, but I thought I would point it out as well - using a resource manager doesn't mean you can't load all your resources at the same time.You can preload everything you want to, and then just get references to it later, as well as use an UnloadAll method to clear levels.

So why do you need a resource manager, if you don't load your resources dynamically?

SiegeLord
Member #7,827
October 2006
avatar

???

Ok, let me make my configuration files a bit more clear...

File: slime.obj

class = land_creature
sprite = slime.png

File: slime_colossus.obj

class = land_creature
sprite = colossus.png

And inside the constructor of the land creature:

{
  Bitmap = ResourceManager.GetBitmap(Config.GetString("sprite"));
}

Or to put it another way, how are you implementing:

LandCreature slime = Object::load("slime");

Because to me all you've done is created a resource manager where the resource is now objects.

EDIT: Oh, and let me make this perfectly clear. At no point anywhere in the source code is there any mention of such a thing as a "slime" or a "slime_colossus". There's no mention of "slime.png" and "colossus.png" anywhere either. All those things are loaded at runtime.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

taronĀ 
Member #10,584
January 2009
avatar

Resource managers seems to make many things easier for me.

It becomes easier to share the same resource without loading the same resource multiple times by mistake.

Loading resources from script/data files also becomes easier, without again, having to worry about duplicating resources in memory.

axilmar
Member #1,204
April 2001

SiegeLord said:

Oh, and let me make this perfectly clear. At no point anywhere in the source code is there any mention of such a thing as a "slime" or a "slime_colossus". There's no mention of "slime.png" and "colossus.png" anywhere either. All those things are loaded at runtime.

So, you are not talking about a resource manager actually, you are simply talking about creating instances of objects from configuration files. That's hardly the same as what we have been discussing.

taronĀ  said:

Resource managers seems to make many things easier for me.It becomes easier to share the same resource without loading the same resource multiple times by mistake.Loading resources from script/data files also becomes easier, without again, having to worry about duplicating resources in memory.

Ok. How is that more helpful than having a variable to the resource?

SiegeLord
Member #7,827
October 2006
avatar

axilmar said:

So, you are not talking about a resource manager actually, you are simply talking about creating instances of objects from configuration files. That's hardly the same as what we have been discussing.

What? Seriously... what?

Objects use resources. It doesn't matter how they are created, they need resources. I manage those resources using a resource manager. How will you manage resources using your technique in my case? I've shown you an implementation of a constructor that uses a resource manager. Please show me one that uses your technique.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

axilmar
Member #1,204
April 2001

SiegeLord said:

What? Seriously... what?Objects use resources. It doesn't matter how they are created, they need resources. I manage those resources using a resource manager.

The resource manager discussed in this thread is one about loading resources dynamically, on a need basis, by name of the resource.

Your resource manager is a facility that allows you to instantiate game objects from configuration files.

Can't you see the difference?

Quote:

How will you manage resources using your technique in my case? I've shown you an implementation of a constructor that uses a resource manager. Please show me one that uses your technique.

Already shown it to you:

Object slime = Object::load("slime");

The above is not a resource manager, it's a simple function that loads a slime object.

SiegeLord
Member #7,827
October 2006
avatar

axilmar said:

The resource manager discussed in this thread is one about loading resources dynamically, on a need basis, by name of the resource.

How does my constructor not fit that description? The game might instantiate a slime at any point during the runtime, then it would need the slime.png resource loaded, which would be taken care of by the resource manager. Slime might be deleted, or the level might be unloaded and then the slime.png resource should be unloaded too. The ability to create objects based on the description in a configuration file is not resource management per se, but it is a use case that requires a resource manager.

EDIT: Or how about this. Forget objects and take your description:

Quote:

The resource manager discussed in this thread is one about loading resources dynamically, on a need basis, by name of the resource.

And now answer me, how do you handle the case where the name of the resource is a dynamic value, unknown at compile time.

I don't see where this confusion is coming from, I think I'm being very clear in what I am asking.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Matthew Leverton
Supreme Loser
January 1999
avatar

Have you not yet realized that axilmar will politely argue semantics on any given topic until Jesus' second coming? Even if you fundamentally agree on something, it's doubtful you'd ever come to that conclusion...

Anyway, if your method works without any major problems, it's silly to argue it's wrong because it introduces an extraterrestrial object. Programming is about getting things done, not creating a model of the Real World(TM).

axilmar
Member #1,204
April 2001

SiegeLord said:

The ability to create objects based on the description in a configuration file is not resource management per se

Cool, that's what I meant.

Quote:

but it is a use case that requires a resource manager.

Does it really require a resource manager? given that 1) resources are loaded before the game begins, 2) careful management of vram is required and 3) using tree maps or hash maps may cause performance problems during the game, are you sure that a resource manager like the one we discuss is required?

Quote:

And now answer me, how do you handle the case where the name of the resource is a dynamic value, unknown at compile time.

In a use case you describe, tree/hash maps are only required when the resources are loaded and passed to the created objects. Even if you don't create all the objects at the start of a game's level, you can create the stubs that will create the game objects, and thus solving the problems I mentioned above.

Can you now answer me how would you handle the problems I described earlier?

Quote:

I don't see where this confusion is coming from, I think I'm being very clear in what I am asking.

You formed the question in such a way that it was not clear (at least to me) what was the use case.

Have you not yet realized that axilmar will politely argue semantics on any given topic until Jesus' second coming? Even if you fundamentally agree on something, it's doubtful you'd ever come to that conclusion...

I apologize for being too analytical, but I believe that the devil is in the details, as they say. Cases like these need a deep analysis, they are not easy.

For example, imagine making a game for the PC using Allegro 5. There is no problem with using a resource manager, since a modern PC has plenty of RAM and CPU power.

But if you transfer the game to an iPhone or a console, the game may not run properly, due to severe CPU and RAM limitations.

There might be a case that a level that loads bitmaps dynamically, as suggested, starts smoothly on an iDevice or console, but then it hungs up or slows down when a certain bitmap is loaded while the game is running.

I have seen such an example on the iPhone games developed by the company I work for. The game run smoothly on the simulator, which run on a Mac, and also run smoothly on the iPad and latest iPhone, but slowed down on an earlier iPhone. It was a case of resource management detail that caused a massive code restructuring and set us back more than a month.

See, I don't argue for the sake of arguing :-).

Oscar Giner
Member #2,207
April 2002
avatar

axilmar said:

using tree maps or hash maps may cause performance problems during the game,

You only use search trees or hash maps in your editors (for ease of use, being able to give things a name). But once you "compile" the resources into a format for use by the game itself, all accesses are by index.

Quote:

careful management of vram is required

That's a thing a resource manager can do pretty well. For example resources can have a priority, so in case of low vram, resources with low priority are moved to system RAM.

axilmar
Member #1,204
April 2001

You only use search trees or hash maps in your editors (for ease of use, being able to give things a name). But once you "compile" the resources into a format for use by the game itself, all accesses are by index.

So, if I am to use an index, which must be known at compile time, why not use a simple variable? what's the pros of an index over a variable?

Quote:

That's a thing a resource manager can do pretty well. For example resources can have a priority, so in case of low vram, resources with low priority are moved to system RAM.

What about resources that are already requested from the resource manager? if I have a pointer to a bitmap, and then the resource manager moves my bitmap to the system memory, then my bitmap will be invalid.

Furthermore, in order for the resource manager to do this, it will have to process every resource it currently has, and therefore the game will probably pause, even for a few seconds (because determining the best possible way to lay out different sized bitmaps in memory is not a trivial task). Which is not acceptable, I think.

Oscar Giner
Member #2,207
April 2002
avatar

axilmar said:

So, if I am to use an index, which must be known at compile time

No, it's not known at compile time. Where did I say that?

Quote:

What about resources that are already requested from the resource manager? if I have a pointer to a bitmap, and then the resource manager moves my bitmap to the system memory, then my bitmap will be invalid.

If you want to allow that, you'll need a Bitmap class that takes care of this scenario, and the program always interfaces through this, never directly accessing allegro bitmaps.

axilmar
Member #1,204
April 2001

No, it's not known at compile time. Where did I say that?

You said earlier (quote):

But once you "compile" the resources into a format for use by the game itself, all accesses are by index.

So, I imagine you are talking about something like Allegro 4's resource files, aren't you? so, you are talking about index constants produced by the tools.

If you want to allow that, you'll need a Bitmap class that takes care of this scenario, and the program always interfaces through this, never directly accessing allegro bitmaps.

But it's not possible to solve it, even with a Bitmap class: once the Bitmap class obtains the pointer, the bitmap must not be moved, otherwise the pointer will be invalid.

SiegeLord
Member #7,827
October 2006
avatar

axilmar said:

1) resources are loaded before the game begins

As many people have pointed out, this is orthogonal to using a resource manager or not.

Quote:

2) careful management of vram is required

I think you overstate the care needed. You get many benefits of a resource manager (the simple std::map<string, ALLEGRO_BITMAP*> variety) even with infinite VRAM simply because resource manager avoids loading identical files multiple times.

Quote:

3) using tree maps or hash maps may cause performance problems during the game

As many people have pointed out, you can cache the lookup in a member variable of the class. This is a straw-man argument.

Quote:

In a use case you describe, tree/hash maps are only required when the resources are loaded and passed to the created objects.

I still don't understand how I am being misunderstood. That's the entire point. Resource managers are needed when dynamic objects are created that use resources.

Seriously... this is ridiculous. I am going to write up a fully functioning resource manager example, and ask you to modify the code with your technique. Then it'll be clear exactly what I and you mean.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Edgar Reynaldo
Member #8,592
May 2007
avatar

axilmar said:

But it's not possible to solve it, even with a Bitmap class: once the Bitmap class obtains the pointer, the bitmap must not be moved, otherwise the pointer will be invalid.

class Bitmap {
//...

   operator BITMAP* () {return bitmap;}
};

Problem solved. Every time you need your BITMAP* you get it from your Bitmap. Then it will never be invalid.

SiegeLord
Member #7,827
October 2006
avatar

Alright, here it is:

main.cpp#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_image.h> 3#include <map> 4#include <string> 5#include <vector> 6#include <iostream> 7 8using std::cout; 9using std::map; 10using std::string; 11using std::pair; 12using std::vector; 13 14ALLEGRO_BITMAP* verbose_load(const char* filename) 15{ 16 cout << "Loading: " << filename << std::endl; 17 return al_load_bitmap(filename); 18} 19 20struct SResourceManager 21{ 22 ALLEGRO_BITMAP* Load(string filename) 23 { 24 BitmapsIt it = Bitmaps.find(filename); 25 if(it == Bitmaps.end()) 26 { 27 ALLEGRO_BITMAP* bmp = verbose_load(filename.c_str()); 28 if(!bmp) 29 cout << "Couldn't load: " << filename << std::endl; 30 assert(bmp); 31 Bitmaps.insert(pair<string, ALLEGRO_BITMAP*>(filename, bmp)); 32 return bmp; 33 } 34 else 35 { 36 return it->second; 37 } 38 } 39 40private: 41 typedef map<string, ALLEGRO_BITMAP*>::iterator BitmapsIt; 42 map<string, ALLEGRO_BITMAP*> Bitmaps; 43}; 44 45struct SObject 46{ 47 SObject(SResourceManager& manager, string name, ALLEGRO_CONFIG* config) 48 { 49 const char* bitmap_name = al_get_config_value(config, name.c_str(), "bitmap"); 50 assert(bitmap_name); 51 Bitmap = manager.Load(bitmap_name); 52 cout << "Created object: " << name << std::endl; 53 } 54private: 55 ALLEGRO_BITMAP* Bitmap; 56}; 57 58int main() 59{ 60 al_init(); 61 al_init_image_addon(); 62 63 SResourceManager manager; 64 vector<SObject*> objects; 65 66 ALLEGRO_CONFIG* objects_config = al_load_config_file("objects.ini"); 67 assert(objects_config); 68 69 ALLEGRO_CONFIG_SECTION* it; 70 const char* section = al_get_first_config_section(objects_config, &it); 71 72 while(section != NULL) 73 { 74 string section_name(section); 75 if(section_name != "") 76 { 77 objects.push_back(new SObject(manager, section_name, objects_config)); 78 } 79 80 section = al_get_next_config_section(&it); 81 } 82 83 al_destroy_config(objects_config); 84 85 return 0; 86}

There is very limited error detection and cleanup, but those things are separate from the question at hand. The code opens up an objects.ini file, which contains object names followed by bitmaps that represent an object, like so:

objects.ini#SelectExpand
1[apple] 2bitmap = apple.bmp 3 4[pear] 5bitmap = pear.bmp 6 7[poisoned_apple] 8bitmap = apple.bmp

The task of the code is to create each object and load its associated bitmap. Note that two of the objects share the same bitmap. However, if you run the code you get this output:

Loading: apple.bmp
Created object: apple
Loading: pear.bmp
Created object: pear
Created object: poisoned_apple

Although three objects were created, only two bitmaps were loaded.

So yeah... please show me how you'd solve this issue in your code. I've attached the current versions of the files to this post. The code expects the objects.ini file to be in the same directory, and the bitmap paths to be specified relative to the working directory. Keep in mind that I'll be testing your code with a different objects.ini file and different bitmaps. My code can handle such case, can yours?

EDIT:

And before you claim that my code doesn't do the pre-loading bit you want... think of the code in question as the pre-loading code. It's a bit inefficient in the sense that you'll have to delete the objects after you're done, but it gets the job done.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

 1   2   3 


Go to: