TeisL Skrevet 10. desember 2009 Del Skrevet 10. desember 2009 Hei, Jeg driver å lager et enkelt spill, hvor man skal ta noen sprites. De skal da forsvinne når figuren kommer over dem. Jeg har alle spritsene i en vector. Så har jeg da denne testen når de skal fjernes: void Game::doSprites(Player p) { //Function sp test about a sprite should be deleted or not... for(int i = 0; i < Sprites.size(); i++) { /*if(p.rect.x > this->Sprites[i]->rect.x && (p.rect.x+p.rect.w < (this->Sprites[i]->rect.x+this->Sprites[i]->rect.w)+10)){ std::cout << "Remove" << std::endl; }*/http://www.diskusjon.no/style_images/main_gfx/folder_editor_images/rte-code-button.png if(p.rect.x == this->Sprites[i]->rect.x) this->Sprites.erase(Sprites.begin() + i); } }//End doSprites() Jeg vet at jeg har bare sjekker på x, men skal bare ha det til å fungere på denne måten først. Problemet mitt er at det er kun på en sprite hvor det fungerer. Den spriten fjerner seg uten problemer. Men skjønner ikke helt hvorfor de andre ikke blir borte. Noen som ser hva som er feil? Setter pris på all hjelp. Lenke til kommentar
GeirGrusom Skrevet 10. desember 2009 Del Skrevet 10. desember 2009 (endret) Jeg ville brukt en list istedet for vektor, den er bedre egnet. Grunnen er at list er en doubly-linked list som det heter, og det å slette et element med en iterator (som du uansett bruker her) vil være lynraskt, siden det aldri er nødvendig med noen stor dataflytting. for(list<Sprite>::iterator it = Sprites.begin(); it != Sprites.end(); it++) { if(p.rect.x == it->rect.x) Sprites.erase(it); } edit: hva slags datatype er rect.x? for hvis det er float eller double, burde du ikke bruke == for å sammenligne. Endret 10. desember 2009 av GeirGrusom Lenke til kommentar
zotbar1234 Skrevet 11. desember 2009 Del Skrevet 11. desember 2009 (endret) Jeg har alle spritsene i en vector. Så har jeg da denne testen når de skal fjernes: void Game::doSprites(Player p) { //Function sp test about a sprite should be deleted or not... for(int i = 0; i < Sprites.size(); i++) { /* ... */ if(p.rect.x == this->Sprites[i]->rect.x) this->Sprites.erase(Sprites.begin() + i); } }//End doSprites() (...) Problemet mitt er at det er kun på en sprite hvor det fungerer. Den spriten fjerner seg uten problemer. Men skjønner ikke helt hvorfor de andre ikke blir borte. La oss si du har 10 elementer og fjerner element #0. i == 0 og du fjerner Sprites.begin(). Før neste neste iterasjon økes i med 1 (dvs i == 1). I neste iterasjon ønsker du å se på neste element. Dette elementet er nå under indeks 0 (du har slettet et element), men du ser på Sprites, dvs. Sprites[1] som er ett element "for langt" fram. Ellers misforstod jeg totalt hva koden gjorde? Endret 11. desember 2009 av zotbar1234 Lenke til kommentar
TeisL Skrevet 11. desember 2009 Forfatter Del Skrevet 11. desember 2009 (endret) edit: hva slags datatype er rect.x? for hvis det er float eller double, burde du ikke bruke == for å sammenligne. rect.x er en Sint16. Prøver ut å bruke list i stedet for vector, så får jeg se om det fungerer bedre. Jeg endret nå ut til en std::list<Sprite*> Sprites; Så laget jeg denne draw for-loopen: for(std::list<Sprite*>::iterator it = this->Sprites.begin(); it != this->Sprites.end(); it++) { it->draw(screen); } Men får feilmelding på at draw ikke er et member i std::list. Error 3 error C2039: 'draw' : is not a member of 'std::list<_Ty>::_Iterator<_Secure_validation>' game.cpp 61Error 2 error C2839: invalid return type 'Sprite **' for overloaded 'operator ->' game.cpp 61 Endret 11. desember 2009 av TeisL Lenke til kommentar
GeirGrusom Skrevet 11. desember 2009 Del Skrevet 11. desember 2009 Det er fordi du har Sprite* i listen. Du må enten legge Sprite i listen, eller dobbel-dereferere: (*it)->draw(screen); Lenke til kommentar
TeisL Skrevet 11. desember 2009 Forfatter Del Skrevet 11. desember 2009 (endret) Det er fordi du har Sprite* i listen.Du må enten legge Sprite i listen, eller dobbel-dereferere: (*it)->draw(screen); Takk så mye, da var feilmeldingen borte. Nå må jeg bare finne ut hvorfor det kræsjer når jeg paserer spritsene mine. Endret 11. desember 2009 av TeisL Lenke til kommentar
TeisL Skrevet 11. desember 2009 Forfatter Del Skrevet 11. desember 2009 Hei igjen, for(std::list<Sprite*>::iterator it = Sprites.begin(); it != Sprites.end(); it++) { if(p.rect.x == (*it)->rect.x) Sprites.erase(it); } Nå har jeg denne loopen for å slette, men den reagerer fortsatt bare på den samme spriten som på starten. Nå, så kræsjer den bare når jeg kommer til den aktuelle spriten. Noen som vet råd? Lenke til kommentar
GeirGrusom Skrevet 11. desember 2009 Del Skrevet 11. desember 2009 Hmmmm prøv dette: for(std::list<Sprite*>::iterator it = Sprites.begin(); it != Sprites.end();) { std::list<Sprite*>::iterator next = it + 1; if(p.rect.x == (*it)->rect.x) Sprites.erase(it); it = next; } Lenke til kommentar
TeisL Skrevet 11. desember 2009 Forfatter Del Skrevet 11. desember 2009 Hmmmm prøv dette: for(std::list<Sprite*>::iterator it = Sprites.begin(); it != Sprites.end();) { std::list<Sprite*>::iterator next = it + 1; if(p.rect.x == (*it)->rect.x) Sprites.erase(it); it = next; } Ser tankegangen, så prøvde det, men det kom historisk mange feilmeldinger. Men glemte å si hva som var feilmeldingen på den første: "List iterator not incrementable". Lenke til kommentar
GeirGrusom Skrevet 11. desember 2009 Del Skrevet 11. desember 2009 Ah I see... Hmmm, vel du må få tak i en iterator til neste element... men på en eller annen måte beholde den gamle... :S Det du kan gjøre, er å lage en vektor som du legger inn alle iteratorer som skal slettes i, for deretter å sletter dem etter du er ferdig med å iterere alle sprites. Lenke til kommentar
zotbar1234 Skrevet 11. desember 2009 Del Skrevet 11. desember 2009 for(std::list<Sprite*>::iterator it = Sprites.begin(); it != Sprites.end(); it++) { if(p.rect.x == (*it)->rect.x) Sprites.erase(it); } Nå har jeg denne loopen for å slette, men den reagerer fortsatt bare på den samme spriten som på starten. Nå, så kræsjer den bare når jeg kommer til den aktuelle spriten. erase() gjør iteratorne ugyldige. Dvs. etter en erase(it), kan du ikke lenger aksessere it (for å gå til neste element, f.eks.). last = it; ++it; if ( <condition> ) Sprites.erase(last); Lenke til kommentar
Dead_Rabbit Skrevet 11. desember 2009 Del Skrevet 11. desember 2009 (endret) Som zootbar1234 sier, blir ugyldige, men hvis ikke jeg tar helt feil returnerer erase en gyldig iterator til neste element etter det som ble sletta, så den løser problemet for deg. if(<condition>) it = Sprites.erase(it); Edit: Sjekka på cppreference.com, og det ser ut til å stemme: http://www.cppreference.com/wiki/stl/vector/erase Endret 11. desember 2009 av Dead_Rabbit Lenke til kommentar
TeisL Skrevet 11. desember 2009 Forfatter Del Skrevet 11. desember 2009 Som zootbar1234 sier, blir ugyldige, men hvis ikke jeg tar helt feil returnerer erase en gyldig iterator til neste element etter det som ble sletta, så den løser problemet for deg. if(<condition>) it = Sprites.erase(it); Edit: Sjekka på cppreference.com, og det ser ut til å stemme: http://www.cppreference.com/wiki/stl/vector/erase Det var riktig ja, for det fungerte. for(std::list<Sprite*>::iterator it = Sprites.begin(); it != Sprites.end(); it++) { if(p.rect.x == (*it)->rect.x) it = Sprites.erase(it); } Så dette fungerte, eller det vil si, det er bare en som den fjerner, når jeg går over resten, så vet jeg ikke hvorfor de ikke forsvinner. Lenke til kommentar
zotbar1234 Skrevet 12. desember 2009 Del Skrevet 12. desember 2009 Det var riktig ja, for det fungerte. for(std::list<Sprite*>::iterator it = Sprites.begin(); it != Sprites.end(); it++) { if(p.rect.x == (*it)->rect.x) it = Sprites.erase(it); } Hopper ikke du over 2 elementer når du sletter? (en med erase() og en med postinkrement (bruk preinkement, forresten) Lenke til kommentar
GeirGrusom Skrevet 12. desember 2009 Del Skrevet 12. desember 2009 Det er ingen forskjell på post- og preinkrementering i dette tilfellet. for(i = 0; i < 100; i++) 00AB1395 mov dword ptr [i],0 00AB139C jmp main+37h (0AB13A7h) 00AB139E mov eax,dword ptr [i] 00AB13A1 add eax,1 00AB13A4 mov dword ptr [i],eax 00AB13A7 cmp dword ptr [i],64h 00AB13AB jge main+3Fh (0AB13AFh) { } 00AB13AD jmp main+2Eh (0AB139Eh) for(i = 0; i < 100; ++i) 00AB13AF mov dword ptr [i],0 00AB13B6 jmp main+51h (0AB13C1h) 00AB13B8 mov eax,dword ptr [i] 00AB13BB add eax,1 00AB13BE mov dword ptr [i],eax 00AB13C1 cmp dword ptr [i],64h 00AB13C5 jge main+59h (0AB13C9h) { } 00AB13C7 jmp main+48h (0AB13B8h) ++i; 00AB13C9 mov eax,dword ptr [i] 00AB13CC add eax,1 00AB13CF mov dword ptr [i],eax i++; 00AB13D2 mov eax,dword ptr [i] 00AB13D5 add eax,1 00AB13D8 mov dword ptr [i],eax Lenke til kommentar
TeisL Skrevet 12. desember 2009 Forfatter Del Skrevet 12. desember 2009 Hm, at jeg hopper over en ville ikke forundre meg i alle fall, for den som blir slettet nå er den som ligger på plass 1 i lista (som nummer 2). Men hopper jeg over et element her når jeg bruker erase()? For hvis jeg skal slette element it, og bruker erase(it), så trodde jeg da ut ifra det som vi kom frem til tidligere at iteratoren it blir satt til neste pga. at erase() returnerte til neste element? Lenke til kommentar
GeirGrusom Skrevet 12. desember 2009 Del Skrevet 12. desember 2009 Grunnen er at iteratoren vil fortsette en gang for mye dersom du sletter et element. Løsningn er bare å fjerne it++ fra for løkken, og legge den inn i en else blokkk. for(std::list<Sprite*>::iterator it = Sprites.begin(); it != Sprites.end();) { if(p.rect.x == (*it)->rect.x) it = Sprites.erase(it); else it++; } Lenke til kommentar
zotbar1234 Skrevet 12. desember 2009 Del Skrevet 12. desember 2009 Det er ingen forskjell på post- og preinkrementering i dette tilfellet. Men denne versjonen av denne kompilatoren for iteratoren for denne containertypen. Preinkrement er i utgangspunktet billigere, fordi man ikke trenger å lage en kopi (semantikken til postinkrement krever en slik kopi, MEN den kan fjernes av kompilatoren, dersom forholdene tilsier det). Like greit å lære å bruke den rette operatoren. Lenke til kommentar
GeirGrusom Skrevet 12. desember 2009 Del Skrevet 12. desember 2009 Alle operatører skal ideelt returnere en kopi (noe du påpekte for noe kode jeg skrev som returnerte en referanse) Eneste forskjellen skal være verdien i kopien. ++2 = 3 2++ = 2 Lenke til kommentar
TeisL Skrevet 13. desember 2009 Forfatter Del Skrevet 13. desember 2009 (endret) Hei igjen, Jeg begynner å lure på om det at grunnen til at jeg bare får slettet en kan ha noe med måten jeg tegner spritesene på. For jeg har en funksjon run() i game som er den som blir kjørt når spillet starter. Der initialiserer jeg vectoren med alle sprites, slik at jeg får tegnet alle på begynnelsen av hvert spill. if(this->drawAll) { this->Sprites.push_back(new Sprite(this->spriteClass->GFX_SOPP,119,336)); this->Sprites.push_back(new Sprite(this->spriteClass->GFX_SOPP,230,415)); this->Sprites.push_back(new Sprite(this->spriteClass->GFX_SOPP,304,272)); this->Sprites.push_back(new Sprite(this->spriteClass->GFX_SOPP,458,240)); this->Sprites.push_back(new Sprite(this->spriteClass->GFX_SOPP,583,192)); this->Sprites.push_back(new Sprite(this->spriteClass->GFX_SOPP,282,109)); this->drawAll = false; } Så bruker jeg inne i game-loopen en for løkke tl å iterere over vectoren over da be som skal tegnes. for(std::list<Sprite*>::iterator it = this->Sprites.begin(); it != this->Sprites.end(); it++) (*it)->draw(screen); Hvis noen ser noen problemer i denne måten å gjøre det på så tar jeg i mot alle tilbakemeldinger. Edit: Selvfølgelig, nå kom jeg på hva som selvfølgelig er problemet... Når beveger figuren min øker jo jeg rect.x med 10... Så da var det bare en sprites som sto eksakt på posisjonen Endret 13. desember 2009 av TeisL Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå