0
\$\begingroup\$

Im making a Breakout clone game and im stuck with deleting objects after they are hit. There are 3 rows. Each contains 12 blocks.

I'm trying to delete a pair in the array of pairs. The array contains coordinates of an object (texture) displayed, and if that object is hit with a ball I want to delete it and then my ball changes direction.

for each(pair<int, int> par in koordinateBlokova) {

    if (provjeraKolizijeBloka(par.first, par.second, rectLoptica) == true) {
        lopticaTrenutniY = -lopticaTrenutniY;       

    }
}

Array and SDL_Rects are defined like:

pair<int, int> koordinateBlokova[36];
SDL_Rect rectBlock01;
SDL_Rect rectBlock02;
SDL_Rect rectBlock03;

Their definition is:

for (int j = 0; j < brojBlokovaRed; j++) {

    rectBlock01 = initRectBlock(j*sirinaBloka + j*razmakRedova, gornjiOdstoj, sirinaBloka, visinaBloka);
    rectBlock02 = initRectBlock(j*sirinaBloka + j*razmakRedova, gornjiOdstoj + visinaBloka + razmakStupaca, sirinaBloka, visinaBloka);
    rectBlock03 = initRectBlock(j*sirinaBloka + j*razmakRedova, gornjiOdstoj + 2 * visinaBloka + 2 * razmakStupaca, sirinaBloka, visinaBloka);

    SDL_RenderCopy(renderer, block01, NULL, &rectBlock01);
    SDL_SetRenderTarget(renderer, block01);
    koordinateBlokova[j] = make_pair(rectBlock01.x, rectBlock01.y);


    if ((j + 1) % 3 == 0) { // if its 3rd block, make it a impenetrable (not implemented yet, just drawn)
        SDL_RenderCopy(renderer, blockNeprobojni, NULL, &rectBlock02); 
        SDL_SetRenderTarget(renderer, blockNeprobojni);
        koordinateBlokova[j+12] = make_pair(rectBlock02.x, rectBlock02.y); 
    }
    else {
        SDL_RenderCopy(renderer, block02, NULL, &rectBlock02); 
        SDL_SetRenderTarget(renderer, block02);
        koordinateBlokova[j+12] = make_pair(rectBlock02.x, rectBlock02.y); 
    }

    SDL_RenderCopy(renderer, block01, NULL, &rectBlock03); 
    SDL_SetRenderTarget(renderer, block01);     
    koordinateBlokova[j+24] = make_pair(rectBlock03.x, rectBlock03.y);
}
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderPresent(renderer);

To make it easier to understand:

brojBlokovaRed = number of blocks in a row
sirinaBloka= block width
visinaBloka= block height
razmakRedova = space between rows
razmakStupaca = space between columns
gornjiOdstoj = space from top of the screen to first row of blocks

My question is how to delete that current pair from array?

\$\endgroup\$
2
\$\begingroup\$

pair<int, int> koordinateBlokova[36];

This is an actual C++ array, which is a fixed-size structure. Elements cannot be added to or removed from such an array. It has 36 items and it will always have 36 items.

Instead, you probably want to store your pairs in a std::vector, which is C++'s standard library container implementing a resizable array. It would look like this:

std::vector<pair<int,int>> koordinateBlokova(36);

You can then use the member function erase to remove elements based on iterators; since vector's iterators are random-access you can erase an element at some arbitrary index i using koordinateBlokova.erase(koordinateBlokova.begin() + i).


That said, as noted in Garrett Gutierrez's answer, this may not be what you ultimately want to do (although it will directly address your question). Erasing from a vector invalidates (most) outstanding iterators referring to the vector and causes all elements above the erased one to be copied down. If you're going to erase many times from a vector at effectively-random interior indices, there are other broader solutions you can explore that won't have that overhead.

Garrett Gutierrez's suggests a linked list. Another option, if the order of your items is irrelevant, is to simply move the "dead" elements to the end of the array, swapping them with the first live element, and either erase them all there using remove or simply keeping a "live index" that refers to the last live element in your array. This has the advantage of keeping all your elements contiguous in memory (which you don't get with a linked list, per se) and also avoiding heap allocation/free operations when adding or removing elements.

It's a touch "less obvious" than a linked list, though, so if you do not need those criteria, that's also a viable path.

\$\endgroup\$
  • \$\begingroup\$ I'll try it with a vectors, if that doesnt suit me i'll change my way of storing. I would ask you could you be so kind to show me how to add an element to that vector array? \$\endgroup\$ – Marko Petričević Oct 9 '18 at 20:28
  • \$\begingroup\$ push_back (or its cousin, emplace_back) are typically what you'd use. The snippet I posted in the answer itself uses the constructor that resizes the vector initially to have 36 default-constructed pairs in it. \$\endgroup\$ – Josh Oct 9 '18 at 20:30
  • \$\begingroup\$ call me dumb but I dont get it: koordinateBlokovaVektor.push_back(rectBlock01.x, rectBlock01.y); doesnt work, neither does koordinateBlokovaVektor(j).push_back(rectBlock01.x, rectBlock01.y);. Definition is: vector<pair<int, int>> koordinateBlokovaVektor(36); \$\endgroup\$ – Marko Petričević Oct 9 '18 at 20:37
  • \$\begingroup\$ What you're trying to do there is call a function "push_back(int, int)" which doesn't exist. The function is "push_back(pair<int, int>)", in your case, basically. So you need to do something like "push_back(std::make_pair(block.x, block.y))." \$\endgroup\$ – Josh Oct 9 '18 at 20:43
  • \$\begingroup\$ If you have further issues with the syntax involved in using std::vector or any other C++ container, I recommend you post separate questions or ask about them in Game Development Chat. Comments aren't really suited for that kind of back-and-forth dialog. \$\endgroup\$ – Josh Oct 9 '18 at 20:44
-1
\$\begingroup\$

First of all, in general, you do not want to modify a vector in C++ while iterating through it. Even if you did take the trouble to write your loop such that it permitted this, this would make your collision detection something like a O(n^2) operation, in other words it would be quadratic with respect to the number of elements in the vector, and so it would grow to be prohibitively slow relatively quickly as you added more elements into the array.

What you should do is either consider a linked list structure (list) or do something like mark the elements in the vector for later deletion and then, after you have done all the collision detection, move only the objects not marked for deletion into a new vector that you replace the old vector with. This could be done by making the vector a vector of structs/classes that contain the pair as a member but also a bool for keeping track of if the object is deleted or not.

In the latter case you would have to decide: do you want multiple balls to be able to bounce off the same object in a single frame, or do you want only one to be able to do that, and then for the object to be deleted immediately and no other balls be able to bounce off if it in the same frame? If you are okay with multiple, then just do your collision detection as normal and delete the objects afterward. If you want the object to be deleted "immediately", then make your collision detection conditioned upon neither of the objects being marked for deletion.

\$\endgroup\$
  • \$\begingroup\$ Well to make things clear, i'm making a Breakout clone game. The whole point of storing coordinates is to remove blocks if they are hit with a ball. Im trying to find a way to just "remove" an index in the array (doesnt have to delete it) so the next time I use my function for drawing/rendering, it excludes that index because the object has been hit, if that makes sense. \$\endgroup\$ – Marko Petričević Oct 9 '18 at 19:48
  • \$\begingroup\$ If you don't want to actually remove the object from the vector, and instead simply do not want to draw it, this might be as simple as making a struct/class like I mentioned before with a bool but instead of being a mark for deletion it is a mark for draw. If false, the block is not drawn. You probably want to condition collision detection on this being true too (you don't want the ball to collide with a block you aren't drawing). This is an acceptable solution if the number of blocks is soft-capped. Otherwise you waste memory with unused junk blocks sitting around. \$\endgroup\$ – Garrett Gutierrez Oct 9 '18 at 19:52
  • 1
    \$\begingroup\$ I'd appreciate constructive criticism from whoever down voted my answer! \$\endgroup\$ – Garrett Gutierrez Oct 9 '18 at 20:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.