Hi guys. I've started to adopt this way of designing my Graphical applications. I have a Screen class (which is a singleton) which has an std::vector of Element pointers. I have an Element class which has four virtual methods. So it's like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
class Element
{
public:
virtual void events()=0;
virtual void logic()=0;
virtual bool dead()=0;
virtual void draw()=0;
};
class Screen
{
private:
std::vector<Element*> elements;
public:
void events();
void logic();
void check_dead();
void draw();
//The above methods just iterate through the vector calling each element's respective methods. The check_dead method does some sort of tricky stuff to check if an element is dead and removes it if necessary.
void add(const Element * e); //This adds the argument to the vector.
};
|
So then I have stuff inherit from Element. For instance:
1 2 3 4 5 6 7 8 9 10 11
|
class HealthBar : public Element
{
//...
};
class Enemy : public Element
{
//...
};
//etc...
|
Then what I do is I make an instance of Screen and add the elements (like the player's health bar and enemies that appear on screen as well as background images and stuff) using the add() method. Then in the main game loop I simply call the screen's events(), logic(), check_dead(), and draw() methods.
The only hangup that makes me feel like this set up is not really very good is the difficulty with preserving Elements that I pass into the vector. By that a I mean, say that whenever the user clicks I want an Explosion to occur at the place that they clicked. The explosion is to last 32 frames. So I have:
1 2 3 4 5 6 7 8 9 10
|
class Explosion : public Element
{
private:
//...
int framecounter; //<- gets incremented in every logic() call
public:
//...
bool dead() {return framecounter > 32;}
//...
};
|
and then in my main loop:
1 2 3 4 5
|
if (detect_click())
{
Explosion e(mouse.x, mouse.y);
screen.add(&e);
}
|
This SEEMS to work okay even when I run the program but the issue happens when I try to click more than once and hope for more than one explosion to occur. It's simple enough to deduce that the issue arrises because the pointer in the Screen's vector points to the object that is created in the
if (detect_click())
block. Thus, when this block is executed subsequent to the previous execution, the old Explosion, e, gets destructed (because it gets overwritten, essentially) even if its framecounter is not greater than 16.
so my solution for this is to use dynamic allocation. That way the object will persist through multiple clicks.
1 2 3 4
|
if (detect_click())
{
screen.add(new Explosion(mouse.x, mouse.y));
}
|
the difficulty with this is that eventually the Explosion object needs to get deleted so that its data can be freed... Obviously this should happen when the explosion's dead() method returns true. So it's not too complicated, really, to do some fancy stuff in the check_dead() method that, not only removes the pointer from the vector, but also frees the data that it points to.
The only issue with this is that, by implementing that functionality in the Screen class, we're requiring that every pointer in the vector points to a dynamically allocated object. This isn't the worst thing in the word... but objects like background images or menu buttons or something don't need to be dynamically allocated to function properly.
So, herein lies the snag. I feel like I need to make every pointer in the Screen::elements vector point to a dynamically allocated object, but on the other hand, I don't need every object to be dynamically allocated for objects such as Background images or Menu buttons.
Sooo what do you guys think? I mean I CAN just go ahead and
Screen.add(new BGImage("bg.png"))
and everything will work fine but I feel a bit odd about using so much dynamic memory allocation when it feels unnecessary... I mean let's not forget that the vector has to dynamically allocated for every pointer as well... so that's quite a lot of memory that our program is asking for and I don't much like that idea...
Soo, yeah... what do you guys think of the design? Is this a good idea, having a Screen object and all our objects that we intend to draw on the screen inheriting from an Element base class? Or... is this just a bad idea that will result in many more dynamic memory allocations than we can afford to make?
Thanks!