• Multiple instances of a single object?
    97 replies, posted
So I'm making a Danmaku game and obviously, it's gonna have a lot of bullets. My main question is basically: how do I handle them all? I'm currently using an array+struct (so in my code it's like: bullet_instance[id].x), but when bullets go off-screen I don't know how I can "erase" them. Subtracting from the main bullet counter makes all the bullets created after the one off-screen disappear, and I'm not leaving off-screen bullets still active, because with all the bullets that get created during the level, the engine [b]will[/b] crash. I'm using Microsoft Visual C++ 2008 Express and SFML if that matters. So Facepunch, any help?
[cpp]swap(bullet_instance[id], bullet_instance[last]); --last;[/cpp] Or you could consider using a linked list, which will allow you to easily (and still effective when iterating) remove objects at any place.
[code] if (bullet_instance[i].x < 0 || bullet_instance[i].x > WINDOW_WIDTH || bullet_instance[i].y < 0 || bullet_instance[i].y > WINDOW_HEIGHT) { // This bullet went off-screen! Let's erase it! swap(bullet_instance[i], bullet_instance[bullet_count]); --bullet_count; }[/code] Am I doing it right? Because if so, it doesn't work. Not all but a few bullets get erased when a bullet goes offscreen.
The detection code should work Try outputting the ids of the bullets into a text file inside the if to check it actually works
[QUOTE=Icedshot;25813405]The detection code should work Try outputting the ids of the bullets into a text file inside the if to check it actually works[/QUOTE] ...what? Yes, the checking works, I'm having trouble deleting the bullets.
[QUOTE=Samuka97;25813349][code] if (bullet_instance[i].x < 0 || bullet_instance[i].x > WINDOW_WIDTH || bullet_instance[i].y < 0 || bullet_instance[i].y > WINDOW_HEIGHT) { // This bullet went off-screen! Let's erase it! swap(bullet_instance[i], bullet_instance[bullet_count]); --bullet_count; }[/code] Am I doing it right? Because if so, it doesn't work. Not all but a few bullets get erased when a bullet goes offscreen.[/QUOTE] That will make your game stop iterating trough the bullets that have gone off screen (in theory), but not remove them from memory, afaik. That is a problem due to memory consumption. Besides, what happens when you need to add new bullets? You could: -recycle the new bullets. Raises problems if you have no inactive bullet -add new bullets to the end, swap all the inactive ones to the bottom and add 1 to the counter. O(n) time, n being the number of inactive bullets Either seems iffy to me. On the other hand, you could use linked lists which allow for O(1) (I think) access time to random items, are easy to delete elements from and are still easy to iterate trough.
I was trying to make a system that everytime I called create_bullet, it'd find the lowest-numbered non-used bullet. Everytime a bullet goes offscreen, I set it's X to 0 and Y to -100, then on bullet_create I check if the current ID for creation has those properties. However, it doesn't work for some reason. [code]int create_bullet(int bullet_count, int x, int y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { int create_id = 0; //bullet_count; // Position of the bullet while (bullet_instance[create_id].x != 0 && bullet_instance[create_id].x != -100) { create_id += 1; } bullet_instance[create_id].x = x; bullet_instance[create_id].y = y; bullet_instance[create_id].speed = speed; bullet_instance[create_id].direction = direction; bullet_instance[create_id].color_r = color_r; bullet_instance[create_id].color_g = color_g; bullet_instance[create_id].color_b = color_b; bullet_instance[create_id].color_a = color_a; // We've got one extra bullet now, // don't forget to add 1 extra after creation! // Create suceful! return 1; }[/code] So... how do I use an linked list?
I'm confused, since that kind of swap-function would only work in C++, though the rest of your code looks like C. Anyways, you should set create_id to bullet_count and ++bullet_count;. Make sure not to iterate over the arrays end though! And about linked lists... well in C++ you could just use the standard std::list, while in C there is no standard struct afaik, though there are probably millions of implementations out on the Internets.
...what? My code is in C++, or so I think. I'm new to C++, have been learning for 5 days now. Am I doing something wrong?
Change [cpp]while (bullet_instance[create_id].x != 0 && bullet_instance[create_id].x != -100)[/cpp] to [cpp]while (bullet_instance[create_id].x != 0 && bullet_instance[create_id].y != -100)[/cpp] (Second co-ord should be y, not x.)
Whoops, I re-wrote the code as it was in my head since VS2008 was closed and it came out wrong. Well that doesn't matter, I'm trying to understand this "linked list" stuff, but it's blowing my head. Currently reading [url=http://www.functionx.com/cpp/articles/linkedlist.htm]this[/url] and [url=http://www.functionx.com/cpp/articles/arraybasedlist.htm]this[/url]. Could anyone give an example of how I would integrate it into a drawing loop or something, please?
[QUOTE=Samuka97;25814343]...what? My code is in C++, or so I think. I'm new to C++, have been learning for 5 days now. Am I doing something wrong?[/QUOTE] Well, that would explain it ;) It will run perfectly fine in C++, but it just looks more like C code. For example, you could return a boolean from the create_bullet function. Instead of having all those parameters and just forwarding it to the struct, why not pass in a bullet (you could actually also do that in C). And you could provide a convenience function to check for out-of-bounds bullets, i.e. [cpp]struct rect2D { public: static rect2D createWithSize(pos_type x, pos_type y, offset_type width, offset_type height){ return createWithCoords(x, y, x + width, y + height); } static rect2D createWithCoords(pos_type x1, pos_type y1, pos_type x2, pos_type y2){ return rect2D(x1, y1, x2, y2); pos_type getSmallX() const{ return x1; } pos_type getLargeX() const{ return x2; } pos_type getSmallY() const{ return y1; } pos_type getLargeY() const{ return y2; } private: rect2D(pos_type x1, pos_type y1, pos_type x2, pos_type y2):x1(x1), y1(y1), x2(x2), y2(y2){} //you might not be familiar with this, read up on initializer lists or just do the this->x1 = x1; and so on like you know it private: pos_type x1, y1, x2, y2; }; struct bullet { //... stuff public: bool isWithin(const rect2D &bounds) const{ return x > bounds.getSmallX() && x < bounds.getLargeX() && y > bounds.getSmallY() && bounds.getLargeY(); } }; //usage: bullet.isWithin(rect2D::createFromCoords(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT));[/cpp] [editline]2nd November 2010[/editline] [QUOTE=Samuka97;25814916]Whoops, I re-wrote the code as it was in my head since VS2008 was closed and it came out wrong. Well that doesn't matter, I'm trying to understand this "linked list" stuff, but it's blowing my head. Currently reading [url=http://www.functionx.com/cpp/articles/linkedlist.htm]this[/url] and [url=http://www.functionx.com/cpp/articles/arraybasedlist.htm]this[/url]. Could anyone give an example of how I would integrate it into a drawing loop or something, please?[/QUOTE] Since you're on C++, just search for std::list.
Huh. This just confused me even more. What's that code for? It seems much more convenient (at least in my head) to just use the check that I am using already instead of shoving the code you supplied. Any benefits exactly in putting it in?
IMO it looks nicer. But if it confuses you it'll be better not to use it.
If it was all "to look nicer", wouldn't a nice function that has that if statement inside it work just as well?
Or you could ask what stuff confuses you and I (or others) will (try to) explain. Though I am going offline now since I need to get some sleep to be woken up in just 6h by my alarm clock. [editline]3rd November 2010[/editline] It does have the if-statement. I simply provided another struct, rect2D, which takes care of representing a 2D rect.
No, I mean like, couldn't I just do something like this? [cpp]bool is_bullet_onscreen(int i) { if (bullet_instance[i].x < 0 || bullet_instance[i].x > WINDOW_WIDTH || bullet_instance[i].y < 0 || bullet_instance[i].y > WINDOW_HEIGHT) { return 0; } else { return 1; } }[/cpp] [b]Edit:[/b] Also... any help with the std::string thing? [url=http://www.cplusplus.com/reference/stl/list/]Google's results[/url] don't help a newbie too much =\
I don't see why you wouldn't want it as a member functions, but apart from that - and returning a bool instead of an int - my function essentially does the same while being a bit more flexible (since the size is taken by parameter instead of being hardcoded). std::string? Don't you mean std::list? ;) [cpp]int main() { std::list<int> intlist; intlist.push_back(5); intlist.push_back(6); intlist.push_front(4); for(std::list<int>::iterator iter = intlist.begin(); iter != intlist.end(); ++iter) //an iterator is for .. iterating over the elements :) { std::cout << *iter << '\n'; //using the unary * on an iterator 'dereferences' it, meaning that it returns the value of the current place we are iterating over //if you already know pointers, an iterator has some similarities to that } std::cout << std::endl; std::list<float> floatlist; for(int i = 0; i < 100; ++i) floatlist.push_back(i); std::cout << "Size before sorting out the even numbers: " << floatlist.size() << '\n'; for(std::list<float>::iterator iter = floatlist.begin(); iter != floatlist.end(); ++iter) if(*iter % 2 == 0) //sort out the even ones floatlist.erase(iter); //removes the element std::cout << "Size after sorting out the even numbers: " << floatlist.size() << '\n'; for(std::list<float>::iterator iter = floatlist.begin(); iter != floatlist.end(); ++iter) std::cout << *iter << '\n'; std::cout << std::endl; }[/cpp] output: [code]4 5 6 Size before sorting out the even numbers: 100 Size after sorting out the even numbers: 50 1 3 5 7 [and all the following uneven numbers till 100][/code] That shows some of the lists functions and shows you how to iterate over each element of a list as well as instancing lists of different objects (intlist is a list of ints whereas floatlist is a list of floats).
But then would I have to use an separate list for x, y, speed, direction, r, g, b and alpha?
[QUOTE=Samuka97;25836762]But then would I have to use an separate list for x, y, speed, direction, r, g, b and alpha?[/QUOTE] Use a list of bullet structs.
[QUOTE=jA_cOp;25836800]Use a list of bullet structs.[/QUOTE] Oh my. I should have been able to do this myself, but uh... [cpp]std::list<int> bullet_properties[10000];[/cpp]?
More like [cpp]std::list<Bullet> bullets;[/cpp] or [cpp]std::list<Bullet> bullets(10000);[/cpp] Assuming Bullet is the name of the class. I think. I tend to use vectors rather than lists, so I'm not sure. You'd then push_back() bullets as needed.
I only have a struct so far, no class. Do I need to make one or can I use my struct? [editline]4th November 2010[/editline] asking that because I don't really understand how classes work, but I can learn I guess. [editline]4th November 2010[/editline] [cpp]class Bullet { double x, y, speed, direction; int color_r, color_g, color_b, color_a; } bullet_instance;[/cpp] Is this right? Gosh, I ask a lot...
[QUOTE=Samuka97;25839282]I only have a struct so far, no class. Do I need to make one or can I use my struct? [editline]4th November 2010[/editline] asking that because I don't really understand how classes work, but I can learn I guess. [editline]4th November 2010[/editline] [cpp]class Bullet { double x, y, speed, direction; int color_r, color_g, color_b, color_a; } bullet_instance;[/cpp] Is this right? Gosh, I ask a lot...[/QUOTE] Classes and objects are pretty damn important in game programming, so you should really get a nice tutorial on them or something, there is far too much to them than can be discussed in a forum post.
[b]Edit:[/b] (to post above) After seeing a little tutorial of classes, I see that they're as simple as an struct, except with functions. Next up is objects I guess... [cpp]std::list<Bullet> bullets; int create_bullet(int bullet_count, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { bullet_instance.x = x; bullet_instance.y = y; bullet_instance.speed = speed; bullet_instance.direction = direction; bullet_instance.color_r = color_r; bullet_instance.color_g = color_g; bullet_instance.color_b = color_b; bullet_instance.color_a = color_a; bullets.push_back(bullet_instance); // Create suceful! return 1; }[/cpp] And when I started doing the game loop, I got lost. How do I retrieve the variables from the bullets now? =|
[QUOTE=Liquid Helium;25839786]Classes and objects are pretty damn important in game programming, so you should really get a nice tutorial on them or something, there is far too much to them than can be discussed in a forum post.[/QUOTE] That being said, though, there's no difference in how they're stored in a list. You can make a std::list of a struct type just like you can make one of a class type.
[QUOTE=Samuka97;25839863][b]Edit:[/b] (to post above) After seeing a little tutorial of classes, I see that they're as simple as an struct, except with functions. Next up is objects I guess... [cpp]std::list<Bullet> bullets; int create_bullet(int bullet_count, double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { bullet_instance.x = x; bullet_instance.y = y; bullet_instance.speed = speed; bullet_instance.direction = direction; bullet_instance.color_r = color_r; bullet_instance.color_g = color_g; bullet_instance.color_b = color_b; bullet_instance.color_a = color_a; bullets.push_back(bullet_instance); // Create suceful! return 1; }[/cpp] And when I started doing the game loop, I got lost. How do I retrieve the variables from the bullets now? =|[/QUOTE] This is the kind of stuff you want to put in a constructor.
[QUOTE=BlkDucky;25839987]This is the kind of stuff you want to put in a constructor.[/QUOTE] Like this? [cpp]Bullet::Bullet (double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { x = x; y = y; speed = speed; direction = direction; color_r = color_r; color_g = color_g; color_b = color_b; color_a = color_a; } //--------------------------------------------------------------------------- Bullet::~Bullet () { delete x; delete y; delete speed; delete direction; delete color_r; delete color_g; delete color_b; delete color_a; }[/cpp]
[QUOTE=Samuka97;25840085]Like this? [cpp]Bullet::Bullet (double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { x = x; y = y; speed = speed; direction = direction; color_r = color_r; color_g = color_g; color_b = color_b; color_a = color_a; } //--------------------------------------------------------------------------- Bullet::~Bullet () { delete x; delete y; delete speed; delete direction; delete color_r; delete color_g; delete color_b; delete color_a; }[/cpp][/QUOTE] Yes, although there is no need for the deconstructor as the garbage collector will do all that for you. It's worth also noting that you should have a separate file called Bullet.h that has the [code] class Bullet { double x, y, speed, direction; int color_r, color_g, color_b, color_a; } [/code] in it, but you should also add permission settings and the new methods so it will look like [code] class Bullet { public: Bullet(double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a); ~Bullet(void); private: double x, y, speed, direction; int color_r, color_g, color_b, color_a; } [/code] and then you should have another file called Bullet.cpp that should have the previous file (called the header) included, and have the method definitions you posted, so it will look like [code] #inlcude "Bullet.h" Bullet::Bullet (double x, double y, double speed, double direction, int color_r, int color_g, int color_b, int color_a) { x = x; y = y; speed = speed; direction = direction; color_r = color_r; color_g = color_g; color_b = color_b; color_a = color_a; } Bullet::~Bullet () { } [/code] now all you need to do is put "#include Bullet.h" in every cpp file that you want bullets in.
Okay... so what now? I'm still lost on how I can create, update and delete bullets without using an array. [editline]4th November 2010[/editline] Already got bullet.h, had bullet.cpp but it didn't have anything in it. Going to do this tomorrow, got some school work now.
Sorry, you need to Log In to post a reply to this thread.