sebox Temat założony przez niniejszego użytkownika |
Kontener struktur vector, usuwanie » 2017-01-02 15:21:17 Zmagam się z dość, wydawało by się prostą sprawą. Mam vector w którym mieszczą się struktury bullet. I chciałbym móc zwyczajnie usunąć jeden z elementów kontenera. struct BULLET { std::string name; sf::Sprite sprite; Vector2f coordinates; };
std::vector < BULLET > bullet;
Próbowałem standardowym sposobem czyli: bullet.erase( bullet.begin() + i );
ale dostaje komunikat: Expression: vector subscript out of range
Próbowałem również tak: bullet.erase( std::remove( std::begin( bullet ), std::end( bullet ), i ), std::end( bullet ) );
ale miałem już błąd na poziomie kompilacji: Error 10 error C2678: binary '==' : no operator found which takes a left-hand operand of type 'BULLET' (or there is no acceptable conversion)
|
|
michal11 |
» 2017-01-02 15:49:05 Robisz to w pętli? Pokaż więcej kodu.
W pierwszym przypadku dostajesz wyjątek po pewnie nie uwzględniasz tego, że rozmiar vectora ci się zmniejsza. W drugim brakuje operatora do porównywania dla twojej struktury, funkcja nie wie jakie ma wybrać do usunięcia. |
|
sebox Temat założony przez niniejszego użytkownika |
» 2017-01-02 15:52:31 for( int i = 0; i < bullet.size(); i++ ) { }
Hmm, jeżeli chodzi o ten 1 sposób, to w jaki sposób mam to uwzględnić ? |
|
michal11 |
» 2017-01-02 16:08:24 Widzę, że dalej mam zgadywać co robisz i jak robisz, ok, z vectora można usuwać obiekty na przykład tak for( size_t i = 0; i < vec.size(); ++i ) { if( rand() % 2 ) { vec.erese( vec.begin() + i ); --i; }
można tez to zrobić tak for( auto it = vec.end() - 1; it != vec.begin(); ) { if( rand() % 2 ) { it = vec.erase( it ); } else { --it; } }
albo tak vec.erase( std::remove_if( vec.begin(), vec.end(),[]( const YourStruct & s ) { return s.SomeProperty == Param::ToDestroy; } ), vec.end() );
|
|
sebox Temat założony przez niniejszego użytkownika |
» 2017-01-02 16:19:56 void Server::updateBullet() { for( int i = 0; i < bullet.size(); i++ ) { for( int j = 0; j < 50; j++ ) { bullet[ i ].sprite.move( bullet[ i ].coordinates.x * 1, bullet[ i ].coordinates.y * 1 ); for( int k = 0; k < players.size(); k++ ) { FloatRect box( players[ k ].position.x, players[ k ].position.y, 135, 200 ); FloatRect box2( bullet[ i ].sprite.getPosition().x, bullet[ i ].sprite.getPosition().y, 30, 11 ); if( box.intersects( box2 ) ) { if( bullet[ i ].name != players[ k ].nick ) { players[ k ].hp = players[ k ].hp - 10; cout << "Gracz " << players[ k ].nick << " ma: " << players[ k ].hp << "hp" << endl; bullet.erase( bullet.begin() + i ); } } } } } }
Myślałem, że ten kod się nie przyda dlatego go nie wklejałem, ale faktycznie może i mam tu jakiś błąd. Generalnie przesuwam o 1 pixel pocisk i sprawdzam z każdym z graczy czy zachodzi kolizja, jeżeli tak to -10hp i tak z każdym pociskiem. |
|
michal11 |
» 2017-01-02 16:33:10 No to skorzystaj z 3 sposobu, dodaj pole do struktury czy pocisk został zniszczony czy nie i usuń wszystkie oznaczone na sam koniec, tak będzie najwydajniej. pro tip do kolizji możesz skorzystać z GetBoundingBox(), nie musisz go ręcznie wyliczać. I jeszcze jakiś schematyczny kod struct Bullet { float Damage; bool IsDestroyed; void OnCollision( Player & player ) { player.ApplyDamage( Damage ); IsDestroyed = true; } };
std::vector < Bullet > Bullets;
for( Bullet & bullet: Bullets ) { for( Player & player: Players ) { if( CheckCollisions( bullet, player ) ) { bullet.OnCollision( player ); player.OnCollision( bullet ); } } Bullets.erase( std::remove_if( Bullets.begin(), Bullets.end(),[]( const Bullet & b ) { return b.IsDestroyed; } ), Bullets.end() );
jakoś tak mniej więcej bym to zrobił. |
|
mokrowski |
» 2017-01-02 16:44:20 W vector jeśli naruszysz jego ciągłość usuwając element, następuje utrata aktualności wszelkich iteratorów oraz indeksów. Radzę skorzystać z rady @michal11 i na koniec wszystko usunąć z użyciem idiomu erase-remove. Tu masz opis dlaczego to będzie efektywne i jak to zrobić: https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom |
|
sebox Temat założony przez niniejszego użytkownika |
» 2017-01-02 18:40:10 Wszystko działa, dzięki bardzo za pomoc, ale jak już jesteśmy przy temacie, to może powiecie mi, dlaczego np: w vectorze std::vector < Vector2f > coordinates; działa mi bez zarzutu coordinates.erase( coordinates.begin() + j ); a w vectorze struktur już trzeba kombinować z erase-remove ? |
|
« 1 » 2 |