-
|
|
About base class that is drawableGameComponent and it's children that are not.
|
Hi,
I made a abstract base class for my movable objects that all things that move inherit from it and it contains all my movement code and collision detection.
So I was wandering in my code in these cold days that I realized, heck, why I'm calling my Draw method for each of those guys? Isn't DrawableGemeComponent supposed to call Draw automatically? So I made my base class to inherit from DrawableGemeComponent (and believe me, it was not easy (since I had to pass Game reference from the inherited class)) and when my other classes inherit from it, they would automatically be DrawableGemeComponent too.
It was just to my surprise that it didn't work. So my question is, was my approach wrong? Is a child of a DrawableGemeComponent , will be one?
If yes (and for Jack's sake it better be) what causes my inherited classes's Draw methods not to be called automatically?
If no, how can I force (or maybe remind them (by casting somehow)) my children to remember their roots that they are DrawableGemeComponent too, since their father was.
Try not. Do, or do not. There is no try.
|
|
-
-
- (4226)
-
premium membership
-
Posts
1,612
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
Assuming you have the hierarchy
DrawableGameComponent > YourBaseClass > YourChildClass
the Draw method of your child class should be called. The obvious question is are you adding your child components to your Game.Components collection?
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
1. Your design is just fine and that must work like a charm
2. Add the concrete class instances to the game components (as dadoo said)
3. Initialize
But still...sooner or later you will overgrow such a design though and will decide to build your own Scene Graph Manager. So you might just do it from the start and have a single drawable component (the manager) and add all movable (and other) objects to the manager. Inside managers Draw override handle all the child objects Draw() invocations.
Just think about culling, custom sorting the rendering order and stuff like that and you will see why it is easier to handle Draw() and Update() from one single place - the scene manager.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
Yeah, I second ERiba, it's better to have your component call update and draw methods for each object it works with than to have all the objects the component works with be components too. Your component (which is sounding like a scene manager) can have more fine grained control on when update and draw are called, rather than having to deal with Update and Draw order properties in the game's component collection.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
ERiba:1. Your design is just fine and that must work like a charm
2. Add the concrete class instances to the game components (as dadoo said)
3. Initialize
But still...sooner or later you will overgrow such a design though and will decide to build your own Scene Graph Manager. So you might just do it from the start and have a single drawable component (the manager) and add all movable (and other) objects to the manager. Inside managers Draw override handle all the child objects Draw() invocations.
Just think about culling, custom sorting the rendering order and stuff like that and you will see why it is easier to handle Draw() and Update() from one single place - the scene manager.
1- Oh, I didn't know that I have to add my component to Game.Components! It all really seemed to good to be true!
Where do you suggest doing so, in my child classes constructors or in their Initialize method or outside where I created an object of this component?
2- About your SceneGraph and stuff (Are you referring to OGRE's design? I'm familiar with it), Do you think I need it since my game is 2D?
Try not. Do, or do not. There is no try.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
1. You must add your components to the game objects components collection in order to get the Initialize, update and draw calls.
Whether you add them from the component itself or from outside is not important though it seems a bit odd if the DrawableComponents add themself to the game.
Note that the order of game initialize and adding the components is important! If you add them later you must initialize them manually ( just invoke Initialize() )
2. I wouldn't know about OGRE's design. I know what it is but never did anything with OGRE. If you need it depends on you. For a simple playground or small demo for sure not. However if you plan to make something more you will need that. Even if your SceneManager for start is just a DrawableComponent with a List<MovableObjects> and inside Draw has a for each MovableObject in list... BTW I would create a new common base component for your MovableObject though, tomorrow you will need a StaticObject a PickableObject a PhysicsObject etc :-)
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
ERiba:1. You must add your components to the game objects components collection in order to get the Initialize, update and draw calls.
Whether you add them from the component itself or from outside is not important though it seems a bit odd if the DrawableComponents add themself to the game.
Note that the order of game initialize and adding the components is important! If you add them later you must initialize them manually ( just invoke Initialize() )
2. I wouldn't know about OGRE's design. I know what it is but never did anything with OGRE. If you need it depends on you. For a simple playground or small demo for sure not. However if you plan to make something more you will need that. Even if your SceneManager for start is just a DrawableComponent with a List<MovableObjects> and inside Draw has a for each MovableObject in list... BTW I would create a new common base component for your MovableObject though, tomorrow you will need a StaticObject a PickableObject a PhysicsObject etc :-)
1- In which order should I add them? I thought I have to mange what is in front of what by using the layer (between 0 and 1) and not the order of them.
What happens if you add them arbitrary?
2- I meant that do I have to create SceneManager even if my game is a 2D platformer?
Thanks.
Try not. Do, or do not. There is no try.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
3- I added my character after I created it to Components with game.Components.add(hero); but it doesn't still get a draw call.
Try not. Do, or do not. There is no try.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
You first create your objects, then add them to the game components, and at then call Game.initialize().
Further if you override Initialize in your MovableObject you have to call base.Initialize() or else the LoadContent() will not fire.
I don't have a link but I know there where some posts here which explain in details the game components internals.
Regarding the Scene Manager it is up to you, 2D/3D doesnt matter - its the features you plan to implement.
Starting right away with a SceneManager is cheap. You only need a storage for your abstract base class (list, array, queue whatever), two overrides (draw and update) where you invoke for each stored object the corresponding method.
[edit] OK I found the link from a Nicks post: http://nickgravelyn.com/2008/11/life-of-an-xna-game/
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
1-
I tried for hours, read lots of posts about this, no luck.
I think what I'm doing is different from what people normally do with DrawableGameComponent.
Let me clarify myself:
I create my tiles and characters after reading their placement from my map file, which I read from a text file. So whenever I reach that I have to create an enemy, I call game.Components.Add(tempEnemy); to add that component to the collection, but obviously they don't get a draw call.
I've read that I have to call base.Initizalize() to make it go through all my components Draw/Update calls but there are several places that I add components to game.Components collection and I don't want to call base.Initialize() several times, it feels so wrong.
2- For my tiles, I want them to automatically get Draw method but I manage the scrolling in another class that calls their Draw method. How can I make them work together, i.e. tile's draw method gets called automatically and compatible with scrolling.
Try not. Do, or do not. There is no try.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
Exactly as I said in my first mail: you need a SceneManager!
For havens sake its a simple class with one private collection<yourbaseClass>, Add(yourBaseclass), Remove(yourBaseClass), override Draw(), Update() and Initialize(). You get that up & running in two minutes.
Once you have that you don't care where and who is creating your components (they wannt need to inherit from DrawableGComp. anymore but who cares even if the do). You just add the to your SceneManager. The scene manager must inside the Add() add them to your collection, call the components Initialize() and thats it. Inside the scm.Draw() you will itterate through all the components in the collection and invoke their Draw(), same for Update().
Note that you shouldn't partially decide whether to render something or if its not changed (e.g tiles) you MUST render everything inside the Draw(). Later on should implement some culling if your level is large so that only visible parts get rendered but you still can not decide upon the fact if something has changed or scrolled or moved to render or not. Even static objects must be rendered each frame.
Did you read the Nicks post on the link? It explaines what gets executed in which order and what happens if you add components to the game after the game is initialized.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
test84:I create my tiles and characters after reading their placement from my map file, which I read from a text file. So whenever I reach that I have to create an enemy, I call game.Components.Add(tempEnemy); to add that component to the collection, but obviously they don't get a draw call.
What do you mean they don't get a Draw call? You mean the Game object isn't automatically calling their Draw method during the game loop? If they are added to the Game.Components collection, their Draw methods will be called during the game loop.
test84:I've read that I have to call base.Initizalize() to make it go through all my components Draw/Update calls but there are several places that I add components to game.Components collection and I don't want to call base.Initialize() several times, it feels so wrong.
You should only ever call base.Initialize() once. And afaik you must create your components from code within (or executed by) the Game Constructor or the Game.Initialize() method, but I'm not sure. So to be safe, make sure your tile/character creation is in there.
test84:2- For my tiles, I want them to automatically get Draw method but I manage the scrolling in another class that calls their Draw method. How can I make them work together, i.e. tile's draw method gets called automatically and compatible with scrolling.
Your scrolling manager class should not call their Draw method. If you want the Game class to auto call their Draw methods, then no other code should manually call their Draw methods.
You just need to setup the Tiles Draw method so that it draws the tile based on an offset. Then your scrolling manager class just needs to set these offsets correctly, and the Tile will draw itself in the right position. The scrolling manager should be called and set the offsets during Game.Update, not Game.Draw.
Game hobbyist hell-bent on coding a diabolical Matrix
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
Here is what ERiba is talking about, and I agree, it is a better way because you have control.
[Edited]
| class Tile : DrawableGameComponent |
| { |
| public Tile(Game game) |
| : base(game) |
| { |
| } |
| } |
| |
| class Character : DrawableGameComponent |
| { |
| public Character(Game game) |
| : base(game) |
| { |
| } |
| } |
| |
| class SceneManager |
| { |
| public List<DrawableGameComponent> Components = new List<DrawableGameComponent>(); |
| |
| public void Update(GameTime gameTime) |
| { |
| foreach (DrawableGameComponent component in Components) |
| { |
| if (component.Enabled) |
| { |
| component.Update(gameTime); |
| } |
| } |
| } |
| |
| public void Draw(GameTime gameTime) |
| { |
| foreach (DrawableGameComponent component in Components) |
| { |
| if (component.Visible) |
| { |
| component.Draw(gameTime); |
| } |
| } |
| } |
| } |
| |
| class MyGame : Game |
| { |
| SceneManager sceneManager; |
| |
| protected override void LoadContent() |
| { |
| base.LoadContent(); |
| |
| sceneManager = new SceneManager(); |
| |
| LoadScene(); |
| } |
| |
| void LoadScene() |
| { |
| // read text file, and add components to sceneManager.Components |
| // make sure you call the component.Initialize() method |
| } |
| |
| protected override void Update(GameTime gameTime) |
| { |
| base.Update(gameTime); |
| |
| sceneManager.Update(gameTime); |
| } |
| |
| protected override void Draw(GameTime gameTime) |
| { |
| sceneManager.Draw(gameTime); |
| |
base.Draw(gameTime);
|
| } |
| } |
| |
Game hobbyist hell-bent on coding a diabolical Matrix
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
Except I wouldn't use the Drawable G.C. but his abstract base class and I wouldn't post something so simple he could code in 1-2 minutes. Cmon how long did it take you to do that? :-)
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
ERiba:Except I wouldn't use the Drawable G.C. but his abstract base class and I wouldn't post something so simple he could code in 1-2 minutes. Cmon how long did it take you to do that? :-)
It took me 5 minutes, but the OP is learning, and seems to be struggling, so it might help.
Game hobbyist hell-bent on coding a diabolical Matrix
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
1-Ok, I was not getting calls to my Draw methods because their signature was changed, I added srpiteBatch to them. That raises a question, how to have a SpriteBatch global to the whole program? I can think of making a singleton, what else do you suggest? What about a "service" ?
2- Craig, why do you call base first and then write your own code? I always thought it should be the opposite.
3- So if I have to call all my draw methods and update methods myself, what's the reason inheriting from DrawableGameComponent?
4- I DO have a class and until now that I figured out why I couldn't get automatic draw and update calls from the game, I was calling my draw and update methods myself but it was not like how Craig and "angry" ERiba suggest. I don't register anything for drawing in how you coded, I draw everything in my LevelManger class since I have access to almost everything there. I have a collection of BaseEnemy that I traverse to draw (I fill it whenever I create one enemy) and same thing for my hero and tiles but let me think about Craig's code more thoroughly.
Thanks ERiba and Thanks Craig for being patient and supportive with me.
Try not. Do, or do not. There is no try.
|
|
-
|
|
Re: About base class that is drawableGameComponent and it's children that are not.
|
test84:1-Ok, I was not getting calls to my Draw methods because their signature was changed, I added srpiteBatch to them. That raises a question, how to have a SpriteBatch global to the whole program? I can think of making a singleton, what else do you suggest? What about a "service" ?
Singleton = yuck. Service = sounds good. Both will work - personal preference really. Or put it on your LevelManager class.
test84:2- Craig, why do you call base first and then write your own code? I always thought it should be the opposite.
In most cases this is just personal preference - it depends on what the base call actually does. Ideally it shouldn't matter either way - but sometimes it does. Like in the Game.Draw() - that should be calling base.Draw at the end - I've edited the post.
test84:3- So if I have to call all my draw methods and update methods myself, what's the reason inheriting from DrawableGameComponent?
It supplies some implementation for you - a couple of boolean flags to say if the component is enabled and visible - a draw order - a couple of events you can hook into if you need to know is something has changed. But if you have your own implementation, you might aswell use it.
test84:4- I DO have a class and until now that I figured out why I couldn't get automatic draw and update calls from the game, I was calling my draw and update methods myself but it was not like how Craig and "angry" ERiba suggest. I don't register anything for drawing in how you coded, I draw everything in my LevelManger class since I have access to almost everything there. I have a collection of BaseEnemy that I traverse to draw (I fill it whenever I create one enemy) and same thing for my hero and tiles but let me think about Craig's code more thoroughly.
This is ok. In this case your LevelManager is effectively the SceneManager, so just use it to Update and Draw, rather than the SceneManager I posted.
Game hobbyist hell-bent on coding a diabolical Matrix
|
|
|