Aloha,
I was trying to show a little GUI on my game:
And I realize that is time to make the next step, I need a way to use Linked List to "centralize" all my objects, and have a drawing order.
I read an Evert's post and knew that is the way I want to do my game, a Linked List is very powerful and hopefully my final step about the basic concepts of game programming.
As you can see in the video the drawing order is failing, I hope with linked list I can solve this and another problems that I currently have.
But I have a question... How can I pass different types of "data types" to my linked list?
I think I understand it, I modified a piece of code and came up with this, but before I even try it (isn't going to work), I would like to know if this could work, because I saw other examples but they tend to over complicate everything.
How can I achieve this in a simple way?
Well, I know that I still need to read a lot, but what I would want is a simple way to pass different types of data (made by me) to a linked list
Thanks in advance.
One classic method is to make "data" a pointer to a base class instead of void*, and have all your elements derive from this class.
The good part is that if this base class has a method draw(), you will be able to call (some_node)->data->draw() : it will call the "right method" for each class.
How can I achieve this in a simple way?
Use std::list. Specifically, use templates and then use polymorphism (if you want different types of objects in the list). Specialize the template on the parent class of all your objects.
The STL is your friend.
The STL library that comes with C++ has a linked list implementation. What data type you store in the linked list is the real question. If you already have an inheritance model with your GUI elements, you could store pointers to them in the list. (You probably don't want to store plain pointers into a list, you will want some sort of smart pointer, so the elements free themselves on removal.)
Edit
A link to an STL container reference probably wouldn't hurt.
http://www.cplusplus.com/reference/stl/
Thank you very much, I didn't know about that STL (list). I have object that draw themselves, do you think with the std::list I can call functions of each object?
I'm not using inheritance so far, each window of the game is going to do a very different task, so I'm simplifying the process by just creating a new class with its corresponding object.
When I create similar objects a usually use arrays, you know:
PLAYER player[30]; for(int i=0; i<30; i++) player[i].Draw(); for(int i=0; i<30; i++) player[i].Logic(); for(int i=0; i<30; i++) player[i].input(mouseX, mouseY);
I wish I could use that, but so far I haven't had the chance since each object in my game is completely different... So for that reason I want to use list.
but, can I call member functions using std::list?
So for that reason I want to use list.
You don't need a list for that. You need to learn some basic C++ OOP.
EDIT: Similarly with a list:
std::list<BaseObject*> Objects; Objects.push_back(new Dog()); Objects.push_back(new Cat()); for(std::list<BaseObject*>::iterator it = Objects.begin(); it != Objects.end(); it++) (*it)->Logic(); //will call the methods appropriately depending whether
hmm.. I know about inheritance, what I did know was that I can create a vector based on the "BaseObject" and then add other objects derived from it.
But I don't like the inheritance way, I prefer having objects completely independent, I know that each objects is going to have a logic and draw functions, but not all objects need a input function... I don't know I really prefer a lot, not using inheritance in this case...
So, I know this sounds pedant, but there is a way to do what I do using inheritance and vectors, but using lists instead?
I would like to have different loops cheeking for different lists...
{"name":"604116","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/2\/c2bd9b4c857d8dec656f2cf7fdef4782.jpg","w":666,"h":583,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/2\/c2bd9b4c857d8dec656f2cf7fdef4782"}
The circles are objects which have different member functions and since I think I can't check them in the same list I create two list to check objects which doesn't have drawing functions and other list for those which have drawing functions... Sounds logic?
You don't need to put Input in the BaseObject. Have three base classes, one called BaseObject, one called Drawable, and one called InputSink, and do something like:
class BaseObject { /* common methods and properties */ }; class Drawable { public: virtual void Draw() { } }; class InputSink { public: virtual void Input() { } }; class MyObject1 : public BaseObject, public Drawable { public: void Draw() { } }; class MyObject2 : public BaseObject, public InputSink { public: void Input() { } }; std::list<BaseObject *> objects; for(std::list<BaseObject*>::iterator it = objects(); it != objects(); it++) { InputSink *input_sink = dynamic_cast<InputSink *>(*it); if(input_sink) input_sink->Input(); Drawable *drawable = dynamic_cast<Drawable *>(*it); if(drawable) drawable->Draw(); }
append: and if you want to separate lists based on if they have logic, or whatnot, you can, and you can skip the dynamic_cast (which can be slow).
Thanks man!!! I'm seeing "->Input()" and "->Draw()" so certainly this is what I need, I'm going to be studding your code for the next 5 years... It's because I have no time, of course... of course... 
Edit: Ok ok... A little one just to be sure. I'm sending pointers to the list, so when I erase an object (a pointer to an object) I'm not calling the destructor since it's a pointer... So... If I want to really destroy an object using list::erase I should create a list of objects instead of a list of pointers to objects right? sounds logic, just to be sure...
PS: Yves Rizoud, really sorry for give you no credits, you was talking about the exact same thing... I didn't realize by that time... I was so stupid.
If I want to really destroy an object using list::erase I should create a list of objects instead of a list of pointers to objects right?
If you want to use polymorphism you must use pointers (or references, iirc). To delete all objects from a list of pointers you'd do:
for(std::list<BaseObject*>::iterator it = Objects.begin(); it != Objects.end(); it++) delete *it; Objects.clear();
If you want to delete a specific object:
for(std::list<BaseObject*>::iterator it = Objects.begin(); it != Objects.end(); it++) { if((*it)->Dead) { delete *it; it = Objects.erase(it); } }
Man... I love you... Will you merry me?
Ok ok... A little one just to be sure. I'm sending pointers to the list, so when I erase an object (a pointer to an object) I'm not calling the destructor since it's a pointer... So... If I want to really destroy an object using list::erase I should create a list of objects instead of a list of pointers to objects right? sounds logic, just to be sure...
calling delete on the pointer will call the object's destructor.
That's fine Thomas, but I'm not going to marry you... I already ask it to SiegeLord...
That's fine Thomas, but I'm not going to marry you... I already ask it to SiegeLord...
I was just trying to help, not get in your pants
hahahaha Sure Thomas, Sure...
I think no one mentioned this: for the deletion to work correctly (call the proper destructors), you should declare the destructor of the base(s) class(es) as virtual (even if they do nothing).
class BaseObject { public: virtual ~BaseObject() {} // This is mandatory, even if the body in the base class is empty. /* common methods and properties */ };
class InheritedObject { public: ~InheritedObject() {std::cout << "InheritedObject destructor called!" << std::endl;} };
This way this will work as intended:
BaseObject *obj = new InheritedObject; ... delete obj;
If BaseObject didn't have a virtual destructor, the line delete obj would only call BaseObject's destructor, and InheritedObject's destructor wouldn't be called. With the base virtual destructor both destructors will be called appropriately.
I have check that and it's true!, thank you!... you have just avoid another thread... Damn, I need to find an English forum, I'm taking my English to the top...
PS: Now I understand why Code::Blocks create always a new class with a virtual destructor.
Oh, and here's a bit that I think hasn't been stressed enough:
So, I know this sounds pedant, but there is a way to do what I do using inheritance and vectors, but using lists instead?
Interface-wise, lists and vectors are almost equivalent. Everything a list can do can also be done with a vector, and a few things more. Which one you choose depends on what you will be doing with it, and the general rule of thumb is:
lots of random insertions and deletions (that is, anywhere other than beginning and end), but no random access: list
front and back insertions, random access: deque
everything else: vector
And here's why: vector and deque outperform list in everything except random insertion / removal, and severely so; especially random access is really really slow with lists (O(n)), which is why STL doesn't even bother implementing it.
So, rule of thumb boiled down:
use vector for everything, until you're seeing performance problems.
If you look at BSP trees on Wikipedia they explain how it is used for the painters algorithm. Heres an example B-tree in C++, I modified the one on this page.
B_tree_class.h
node.h
Yhea I could use vectors too, but I don't need random access to my objects, I'm taking OOP to the top, I'm already thinking in how to implement an engine, you know send packages to the engine and retrieve them, and a list is perfect.
Lists perform generally better in inserting, extracting and moving elements in any position within the container, and therefore also in algorithms that make intensive use of these, like sorting algorithms.
I think this is perfect for any video game which is using extensively OOP, where objects draw themselves and send packages of data to an engine and vice verse.
Obvisuly I don't need this to my trivia game
, I just can't avoid thinking in all this already... I'm even sending the events directly to the objects and they will produce a package of info about their position etc, to perform collision detection and things like that. I think sending event to objects isn't a bad idea. And objects which make use of the keyboard (a character) can use it, another object which needs to only know when to draw and do the logic, is going to do just that.
{"name":"604126","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/7\/679791794e4beadfea7ec752c3c6f12d.jpg","w":470,"h":338,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/7\/679791794e4beadfea7ec752c3c6f12d"}
That way I don't need to call a lot of functions from outside the objects. I want to only call one function ((*)->logic(DATA)) which is going to return a DATA package which is going to be used by the engine and at the same time is going to send the DATA package modified to the object with the info already processed by the engine... I don't know something like that. Probably I will need to call two functions
instead of one...
So I send the DATA to the object with the previous state, the object do its logic which involves drawing input etc... and send its current state to the engine again.
Anyway, thank you guys to open my mind, I have learned a lot of thing in these 3 days about C++ I was just learning Allegro Allegro and more Allegro... Actually I already knew them I have study them, but it's like you don't know what to do whit them. It's like yhea I have all this knowledge but then what I do with all this? hahaha it's weird...
I have see the examples but I don't like the way they're done, they use C, and even when C++ is not so different in its syntax, it's very different at the moment of creating a game or a program. Well, at least that I think...
I have see the haiku example it's incredible how in that game al_draw_tinted_scaled_rotated_bitmap() is just called once... in ALL the game, and that is the only drawing call. There are structs inside structs, incredible... but I prefer C++. hohhho