Jump to content
  • Advertisement
Sign in to follow this  
Riddle

Design problem: Abstract method needs access to "outer" data.

This topic is 4881 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello guys! I have a little design problem. Let me show you a little example. Here a simple font class that allows to load the font into memory with a definiton file:

abstract class Font
{
   public abstract void LoadFromDefFile( string fileNameAndPath );
}




Now I have a BitmapFont class which needs Textures to render itself. And that is the problem! - see code -

class BitMapFont : Font
{
   public void LoadFromDefFile( string fileNameAndPath )
   {
      // But now I need a texture manager. What is the best way to access one?
      // a) Singleton TextureManager ? Would make it easier... but no!
      // b) have a reference to the texture manager inside the BitMapFont class - hmm I need the manager only once here!
      // c) Haha! Just make a global texturemanager! No! Same as singleton! I don't even have a single global in my entire lib!
      // d) ...

      // How would you do it?

   }
}




Thank you, Riddle! PS.: Yes, this isn't the full font class-graph! It's: abstact Resource -> abstract Font -> abstract BitMapFont -> GLBitMapFont / D3D9BitMapFont I may drop the abstract BitMapFont. Im not sure what data I could share over the D3D9 and Gl BitMapFont. [Edited by - Riddle on March 10, 2005 2:00:01 AM]

Share this post


Link to post
Share on other sites
Advertisement
Is it necessary that BitMapFont derive from Font?
I mean, do you need the Font class at all?

Share this post


Link to post
Share on other sites
Well, yes!

Because the font definition files itself support more than one format and the code above was just an example.
I had this problem in more than one case.

Thanks,
Riddle.

Share this post


Link to post
Share on other sites
A global.

But since you're so deadset against them, perhaps some sort of registered callback or thread spawn to fetch the texture?

Share this post


Link to post
Share on other sites
I see two more options that you may have overlooked:

1) Pass in a reference to the texture manager as a parameter to the method.

2) Rather than passing in the filename and path as a parameter maybe you could just pass some sort of texture handle used by your texture manager to identify resources. This could work similarly to how OpenGL gives you handles to resources.

Apart from choosing a solution that you feel is the most elegant, you also need to consider your requirements in terms of how you plan to extend or alter your application in the future.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You could pass any info like texture managers as parameters to the constructor if you really insist on having texture managers separate.

I would just have a single texture manager for basic projects, and probably even for advanced ones :P

Share this post


Link to post
Share on other sites
Quote:
Original post by SmooJ
I see two more options that you may have overlooked:

1) Pass in a reference to the texture manager as a parameter to the method.

2) Rather than passing in the filename and path as a parameter maybe you could just pass some sort of texture handle used by your texture manager to identify resources. This could work similarly to how OpenGL gives you handles to resources.



1.) That will not work because it would break the abstract system. A TfT font doesn't need a texture!

2.) Same.



Quote:

Apart from choosing a solution that you feel is the most elegant, you also need to consider your requirements in terms of how you plan to extend or alter your application in the future.

I think my requirements are too high sometimes. But oh well.. better than too low!



Quote:

But since you're so deadset against them, perhaps some sort of registered callback or thread spawn to fetch the texture?

Yes, I don't like them :)!
Thread spawn? Umm.. could you explain that please. (:




Thank you for your help!
Riddle

[Edited by - Riddle on March 10, 2005 3:36:01 AM]

Share this post


Link to post
Share on other sites
Hi,
Here is my own design. I have:
- a system class: it stores all managers
- a texture manager class: name says it all.
- a task class: this was inspired from Game Programming Gems 1. This class stores references to AudiVideo Layers and Logic Layers. This class handles the game loop and delegates to the AVLayer the rendering process and to the LLayer the logic process (user Input, IA, ...).
- a Font manager: this font manager stores references to a generic font class. It also doubles as a font constructor. The font manager is initiated with a reference to the the texture manager by the system class.
- a generic Font class: base font class like you
- a bitmap Font class: derived one.

Here is what happens at game initiation:
- The system class creates all managers (singleton) according to the system specs (OpenGL/Windows, DirectX/Windows, else ...).
- The system class initiates the task manager with references to managers (font manager for example).
- The system class initiates the task manager with the game task.
- The game task creates the AVLayers and LLayers and initiates them. This creation is done through calling the add_layer method from the task manager. The task manager initiates the layers with references to needed managers (AVLayer gets a reference to the font manager).
- The AVLayer then loads in the font file through the font manager and is all set. The font manager manages to load in the texture through its own reference to the texture manager.
- At each update, the AVLayer selects the Font ID and calls the print method from the font manager.

Now, a little pseudo-code to make everything clearer about how the manager works:

class BaseFont:
public:
Font_Description
Texture_ID
Texture_FileName
virtual void Init(void) //this is overloaded to provide proper font initiation
virtual void Print(x,y,string) //this is overloaded to provide proper font printing
.
class FontManager
public:
void Init(TextureManager)
bool Select(FontID): search for the font ID. If exists, stores the reference into currentfont
void Print(x,y, string): call TextureManager->Select(currentFont->TextureID) then call currentFont->Print method
void Load(FontID, FontFileName): Loads a font into CurrentFont then add CurrentFont to the font list. Doubles as a font constructor
Calls TextureManager->Load(currentFont->TextureID, currentFont->TextureFileName)
private:
BaseFont* CurrentFont
std::list<BaseFont*> Fonts
.
class FontAudioVideoLayer
public:
void Init(FontManager*): setup the FntMgr reference then the user can call FntMgr->Load(155,"Myownfontfile.fnt")
void Update(elapsed_time): if(FntMgr->Select(155)) FntMgr->Print(10,100,"Hello World !")
void Close(void): FntMgr->Unload(155) //I remove the font loaded
private:
FontManager* FntMgr


Hope that helps.
Ghostly yours,
Red.

Share this post


Link to post
Share on other sites
Here's how I'd do it (using C++, sorry):

class BitmapFont : public Font
{
private:
TextureManager & m_TextureManager;
public:
BitmapFont( TextureManager & tm )
: m_TextureManager( tm )
{
}
void LoadFromDefFile( const std::string & fileNameAndPath )
{
m_TextureManager.load_new_texture( fileNameAndPath );
//...
}
};

//...

TextureManager my_manager; //create a new texture manager
BitmapFont my_font( my_manager ); //create a new bitmap font that will use my manager
my_font.LoadDefFromFile( "..." ); //load the new font



This borrows from the same method used by the C++ STL containers when invoking the manually specified allocators in their construction (for an example of this, see this thread where I create a rather ugly stack allocator which I wouldn't recommend using as it's not very optimized or anything - it's meant as a proof of concept :P). This situation is pretty much the same, only instead of allocating memory, you're allocating textures.

Share this post


Link to post
Share on other sites
Factory pattern perhaps?

The goal here is to seperate special case creation logic from the interface. You want to be dealing with behavior, not oddball prerequisites like "if I want a bitmap I need a texture manager". So, encapsulate that weird stuff into its own little factory and then spend your time dealing with what your true concern is: what a font does and how it will influence your system.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!