   dynamic_cast & Limiting Function Calls?
  Here is my class hierarchy:<br /><br />I'm using dynamic_cast like this:if(GetComponent("Model") == 0) {AddComponent(Factory.MakeComponent("Model"));mModel = dynamic_cast<Model*>(GetComponent("Model"));mModel->AddImage("Logo","RPG 17 Logo.png");This is just converting a Component to a Model. What if I wanted to convert a Movable to a Component(see class hierarchy)?AndIs there a better way of doing this? I obviously don't want to put AddImage into the component class. I hate casting so any neat design trick would be awesome. I was using function pointers to call the function but that required casting and custom functions for each return type.The Movement class has the basic query functions(setX, getX, etc).The Movable class has more query functions(setEndX, getEndX, etc).I want the UnMovable class to only be able to use the setX function once. How would I do that? I know a singleton method but that's not going to help me much.Thanks   
Quote:Original post by rpg gamer 17I want the UnMovable class to only be able to use the setX function once. How would I do that? I know a singleton method but that's not going to help me much.I'm not an expert on casting through the inheritance tree, but I can see that the UnMovable's class' problem of only allowing setX has a very simple solution.Simply give UnMovable a member variable called m_bAlreadyMoved, initialize it to false in the constructor, and set it to true when setX is called for the first time.Just to make sure that something doesn't call setX and expect something to be moved after setX has already been called, just return false if its already been called and true if its the first time.Sorry if I can't help you with the casting, but I'm not confident enough to give you a solution that might screw you over lol   ;  Wow... That seems... simple...Thanks! It works!EDIT:(about dynamic_cast)I had a naming error in the tests I ran so when GetComponent tried to retrieve the component it was blank. I got the casting working correctly.   ;  What is the purpose of those classes? What exactly are you using them for? Judging by your previous thread, I'd say you are strongly overengineering things. How much of those classes really actually do something useful? And why do you have to use a dynamic cast there? Why do you work with string identifiers instead of actual type information? What's the benefit of that?I'd start by writing down the requirements. Once those are known, I'd design something that's to-the-point. A design is only beautiful if it achieves it's purpose, design for the sake of it is just wasted effort.EDIT: I mean, this little class here also has 'components' that take care of specific pieces of functionality, no need to write a fancy ComponentManagerFactorySystem for that:class Npc{public:   Npc();   void update();private:   Sprite sprite;   CollisionBox box;   Behaviour* behaviour;}The point here is that a Sprite object/component can be used by other code as well - for your menu background, for your buttons, and so on. That CollisionBox can be used for the player, too. And that Behaviour class could make it easier to swap different kinds of behaviour - at run-time even. Whatever your game needs.   ;  The Window class only has two components and that is Model and WindowBehavior. It is set up like you have there. I designed this class hierarchy so that I can keep track of what has what and delete/run all entities and components with EntityManager.My main function:#include "headers.h"#include "Factory.h"#include "Entity.h"EMain::Factory Factory; //can be embedded in Add function I refused not to. I might later but this makes since to me.EMain::EM_Data* Data = EMain::EM_Data::GetSingleton(); //updated by WindowBehaviorEMain::EntityManager* EM = EMain::EntityManager::GetSingleton();int main(int argc, char* argv[]){//Create the MainTree.EM->AddTree(Factory.MakeEntityTree("MainTree"));//Create the 'Component Communicator'.EM->AddEntity("MainTree",Factory.MakeEntity("Window"));do{EM->RunManager(); //Run All EntityTreesData->EM_FlipVideo(); //Flip the vidoe} while(Data->Run);delete EM;delete Data;return 0;};It's really just a handle based manager. Then only difference between what your doing and what I'm doing is that when I create my pointers to components I don't have to delete them. The ComponentManager does that for me.Here are more details:Components:Model holds all animations, images, and text as well as there x and y coordinates(which can be edited). This will obviously be used by several Entities.Movement will handle pathfinding and collision detection of all movable objects.Behavior will handle the AI of the entity's such as the one mentioned below.WindowBehavior class is used to create the window and handle window events.Entities:Window is basically the creator of all things. This is the class that will be used to add 'game objects' to the EntityManager that then handles the objects separately. This is to simplify game state changes. This Entity can basically create a completely different tree and delete the one it is in.   ;Quote:Original post by rpg gamer 17Is there a better way of doing this?1) Are all those relationships inheritance relationships, as they appear to be? If so, you really, really should re-think that.2) Why does "Unmoveable" inherit from "Movement"? That seems contradictory.3) The natural way to make it only possible to "do something once" to an object is to use the constructor to do it.4) The way you talk so casually about setX, getX etc. suggests that you're in the habit of writing get/set pairs for every data member. This is exactly what you're not supposed to do. Writing code this way doesn't actually gain you any "encapsulation" or other nice happy OO benefits; it just makes more work for yourself while allowing you to lie to yourself about these things.As for avoiding the cast in your factory implementation, the curiously recurring template pattern might help you.   ;Quote:Original post by rpg gamer 17The Window class only has two components and that is Model and WindowBehavior. It is set up like you have there. I designed this class hierarchy so that I can keep track of what has what and delete/run all entities and components with EntityManager.If each entity cleans up it's own content (components), as it should, then the entity manager only has to clean up the entities it contains - not the components that they themselves contain.Quote:It's really just a handle based manager. Then only difference between what your doing and what I'm doing is that when I create my pointers to components I don't have to delete them. The ComponentManager does that for me.Instead of using naked pointers, use smart pointers (which I didn't do to keep the example simple). Problem solved, no need for a component manager. As for handles, using strings as handles means you loose type information. If a npc needs a handle to an item, give it an Item pointer or reference. That's much more to the point than giving it a "sword" string and relying on the fact that the component manager always returns an Item instance for "sword". You're using C++ - so why not use the compile-time type checking? :)Quote:Model holds all animations, images, and text as well as there x and y coordinates(which can be edited). This will obviously be used by several Entities.If you're thinking MVC, then images and text are not the model - they're a view. The model would be the game object states and the controller would be the game logic. So I'd suggest using a better name here. As for the design itself, from what I've seen in your thread about it, it's somewhat odd. It seems there is no distinction between image data and sprites (that is, the actual bitmap, and an instance of it on-screen). It also seems that the only way that calling code can use an image or animation is by it's name - why not just return a reference or pointer to the Image (or whatever object it is that handles the sprite state)?Quote:Movement will handle pathfinding and collision detection of all movable objects.May I suggest splitting pathfinding and collision detection into separate classes - and to let the Movement object handle the movement based on the information it gets from the pathfinding and collision modules?Quote:Behavior will handle the AI of the entity's such as the one mentioned below.Makes sense - although you might as well put this logic into the actual entity class (that is, the Npc class contains the Npc AI - only using classes for that if certain behaviour and state needs to be reused for other entities).Quote:Window is basically the creator of all things. This is the class that will be used to add 'game objects' to the EntityManager that then handles the objects separately. This is to simplify game state changes. This Entity can basically create a completely different tree and delete the one it is in.I wouldn't make a single point the 'creator' of everything, but storing things in a tree-like structure makes sense. I'm not sure if I would make the window the entry point for adding entities - you could just keep that functionality in the entity manager itself.Either way, what kind of game are you planning to build? How complex will it be? Something's telling me you've greatly overengineered this.   ;  I am going to convert back to my original design.This was just this:EntityManagerEntityTreeEntityComponent(just holds virtual functions(Init, Update) and the state of the object(INIT,UPDATE,KILL))The ComponentManager part required casting in order to use the component and because of:@Captain P"If each entity cleans up it's own content (components), as it should, then the entity manager only has to clean up the entities it contains"You just destroyed my feature!I hate smart pointers(Boost). This is an unknown hate. I don't know why I hate them. I just do. I'll probably like them if I try them. I'll still hate them though.I'm not using MVC. Model is just used to collect the animations, and animate them. A single Image/Text doesn't need a handle to be used by Model. It can be loaded and shown with a few functionsAnimations:AddText/AddImage adds the text/image to the animation map using the handle given.Single:LoadText/LoadImage loads the text/image into a IM_Surface and then returns that surface."May I suggest splitting pathfinding and collision detection into separate classes"Theses subjects are relatively new to me. Path-finding is anyways. Any advice offer on this is acceptable. I am going to be using A* and a grid system. So collision is probably going to be easy."you might as well put this logic into the actual entity class"Yeah I'm moving WindowBehavior into Window."I'm not sure if I would make the window the entry point for adding entities"The Window creates the window that shows the game. I took this to mean that it should add the objects to the game using the window. I'm putting them through the window... I'll try and put the window class functionality into the EntityManager.@ZahlmanThe template would of worked but... El Captain deleted the need for them.SetX is virtual so I can make UnMovable do nothing when it's called. I think I could move the start values into the constructor and get rid of UnMovable while still letting the Movement class change the x and y value.EDIT: I see what you mean by templates.[Edited by - rpg gamer 17 on November 19, 2009 6:23:18 PM];Quote:Original post by rpg gamer 17I hate smart pointers(Boost). This is an unknown hate. I don't know why I hate them. I just do. I'll probably like them if I try them. I'll still hate them though.I agree they look strange at first, but just read up on what they're used for and give them a try.Quote:I'm not using MVC. Model is just used to collect the animations, and animate them. A single Image/Text doesn't need a handle to be used by Model. It can be loaded and shown with a few functionsAnimations:AddText/AddImage adds the text/image to the animation map using the handle given.Single:LoadText/LoadImage loads the text/image into a IM_Surface and then returns that surface.Wouldn't that give you too little control over your visualization? What if you need to change the text on a single label, or animate a specific sprite? In many systems it's common to provide access to these individual objects, even though they're often put in some kind of hierarchy (scene graph, parent objects, etc.).As for animating sprites, how about this (pseudo-code)?class Image{   // Contains the actual bitmap data   SDL_Surface* surface;};class ImageCache{   std::map<std::string, Image*> cache;   // Checks if the cache map contains the filename key.   // If not, it loads the image and stores it in the cache map.   // After that, it returns the image.   Image* getImage(const std::string& filename);};class Animation{   // Let's say that each frame is stored in a different image file,   // so a vector of Image pointers/references will suffice.   // You can also decide to pick specific rectangles from an image,   // if you're using sprite sheets.   std::vector<Image*> frames;   // There are various ways to store animation speed - this is just   // an example. You may want to give each frame a time of it's own,   // for added flexibility, and add support for playing animations   // faster or slower.   float frame_time;   // You may want to store animation data in files - it's a form of   // data after all, much like how images are a kind of data.   bool loadFromFile(const std::string& filename);};class ScreenObject{   // Position - it makes sense to use or write a class for this too,   // with some overloaded operators to make working with them a little easier.   int x;   int y;   virtual void draw();};class Sprite : public ScreenObject{   // We're referencing existing animation objects, so animation and image data   // can be shared by multiple sprites.   // Thinking about it, it could be useful to write an animation cache as well.   Animation* animation;   int current_frame;   float time_until_next_frame;   // Type-specific implementation of ScreenObject::draw(),   // also makes sure the animation moves on to the next frame.   // (you may want to add an update function for that instead,   // that takes a time delta or something).   void draw();};class TextLabel : public ScreenObject{   std::string text;   // Type-specific implementation of ScreenObject::draw()   void draw();};// We might as well call this 'ScreenObjectContainer',// and make it derive from ScreenObject itself. That allows// us to create trees of screen objects. Could be useful for// parenting sprites. Designs like that are used in several 3D// engines and 2D GUI systems.class Screen{   std::vector<ScreenObject*> objects;   // Add a screen object as a child   void addChild(ScreenObject* child);   // You may want to give these objects a pointer to their parent,   // so they can automatically remove themselves when they are being   // destroyed. Makes it a little easier and safer to use and all that.   void removeChild(ScreenObject* child);   // Draw all child objects   void draw();};Usage:class GameScene{   Screen* screen;   ImageCache* cache;   TextLabel title;   Sprite logo;   GameScene(Screen* screen, ImageCache* cache)   { // We may need this later on, to add or remove sprites to/from: this->screen = screen; this->cache = cache; title = TextLabel("Title"); logo = Sprite(cache.getImage("RPG 17 Logo.png")); // Or load an animation from a file, depending exactly on what // approach works best for your needs. screen.addChild(&title); screen.addChild(&logo);   }   ~GameScene()   { // This could be automated, see the Screen class comments. screen.removeChild(&title); screen.removeChild(&logo);   }   void update()   { sprite.move(1, 0);   }   void onKeyPressed(Key keycode)   { sprite.move(-20, 0); title.setText("Key pressed!");   }   // I'll assume that screen.draw() is called   // somewhere up-high, every frame.};I hope the above code gives you some inspiration, or at least an idea of how this can be done. I'm using a similar approach and so far I'm quite happy with it (granted, I refactored and tweaked it several times over the course of two years, so yeah ;) ).Quote:Theses subjects are relatively new to me. Path-finding is anyways. Any advice offer on this is acceptable. I am going to be using A* and a grid system. So collision is probably going to be easy.For pathfinding, you'll need some kind of map data. If you store that in a class, and give the class some functions that allow other code to check for routes between point A and B, then all that's left is writing some pathfinding code inside that class and voila. Same goes for collision detection. Hide the data and provide an easy-to-use service.   ;  I do need a cache system. I'll look into it. Right now I'm loading the logo over and over again. I mean the previous image is deleted and released but then I load it again on the next menu.I have the Model class loading basic images and returning the IM_Surface. I then have to keep track of them outside the Model class. It's a little bit of a pain.I think all I'd have to change is Model and EM_Data(handles rendering).   