wdr at September 3rd, 2013 15:35 — #1
Hello... So, I've been developing a 2D game in SFML 2.0 in C++. I got to the part where there is a collision between the player laser and the enemies. Both, the lasers and the enemies are declared as lists. When the laser hits the enemy, the collision check must be performed and if there is a collision, the laser and the enemy are erased from the list. I managed to find what is causing the problem in the collision code, but I am not able to find a solution for it. Here's my code.
std::list<sf::Sprite>::iterator enemyit = enemy.begin(), next;
std::list<sf::Sprite>::iterator greenlaserit = greenlaser.begin(), reload;
while(enemyit != enemy.end())
next = enemyit;
while(greenlaserit != greenlaser.end())
reload = greenlaserit;
greenlaserit = reload;
enemyit = next;
Here, there are two while loops and what I am doing is I am using the inner loop to check for collision and if collision occurs, I am erasing the enemy iterator. And after doing that, the inner loop will keep looping until the while condition stops being satisfied. It won't enter the outer loop until it finishes that. Problem is, the enemy iterator is being erased in the inner loop and I am not incrementing it until the program goes back to the outer loop. How do I do that so that the enemy iterator is incremented in the inner loop as soon as it is erased. I've tweaked around a lot moving code around inside and outside the loops, adding new variables, still nothing. Please help me. Thanks.
reedbeta at September 3rd, 2013 15:46 — #2
You could just use a bool flag to keep track of whether you've incremented the enemy iterator. It would be initialized to false in the outer loop, then in the inner loop, if you erase an enemy you increment the iterator and set the flag to true. After the inner loop exits, you would increment the iterator only if the flag was still set to false.
BTW, you also need to reset greenlaserit to the beginning of the laser list each time you start the inner loop. Currently it will iterate all the way through the laser list on the first enemy, then it will skip all the lasers for each subsequent enemy, as greenlaserit is still at the end of the list.
wdr at September 3rd, 2013 16:14 — #3
OK... Now I get it. I think it'll work with the boolean flag. Thanks, Reedbeta.
One thing though... Should I reset the greenlaserit to the begin of the laser list? Because, the laser list is of indefinite size. As long as I keep the shoot key pressed, the laser sprite will be pushed back to the list to create new lasers. The laser list keeps on expanding as long as I shoot. Just clear this one thing for me, please. Thank you.
reedbeta at September 3rd, 2013 19:24 — #4
Yes, you should still reset it to the beginning of the laser list, because you still want to check all existing lasers against all enemies in case there are multiple collisions in one frame. Like I said, the way you have it now, only the first enemy will be tested against all lasers, then no more enemies will be tested in that frame. So you can currently only kill one enemy per frame.
It may appear to work correctly despite this problem if you don't have too many enemies and the lasers don't move too fast, because if a collision is missed on one frame it may be detected the next frame, or a few frames later. But if you have too many enemies or the lasers move too fast, you will see problems.
wdr at September 4th, 2013 14:42 — #5
OK, OK... Now I understood the problem. I modified the code as you suggested and it worked perfectly. Thank you very much.
By the way, did I tell you...
YOU... ARE... AWESOME... Period! Seriously, is there anything you don't know about C++ game programming? I racked my brains on this for weeks. Couldn't find a solution with all the source material I have. I wish I had your innovative thinking and problem solving skills. Thanks a lot, bro!
P. S. : You don't know this, but you actually saved me from losing 40 marks. Well... Now you know!