Sain vihdoin melkein ilmeisesti ampumisen toimimaan..
Ongelma on, että en tiedä miten saan vectorista x,y akselin ulos..
systeemi on tälläinen:
namespace peli { class Omaluokka{ private: int x; int y; public: Omaluokka(int x, int y){ this->x = x; this->y = y; } int anna_x(){ return x; } int anna_y(){ return y; } }; } Oliot.push_back(peli::Omaluokka(200, 300)); Oliot.push_back(peli::Omaluokka(300, 200)); std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); std::vector<peli::Omaluokka>::iterator lopussa = Oliot.end(); while(selaaja != lopussa){ std::cout << "x = " << selaaja->anna_x() << " y = " << selaaja->anna_y() << std::endl; PiirraKuva(hahmo, naytto, selaaja->anna_x(), selaaja->anna_y()); ++selaaja; } SDL_Flip(naytto);
Miten voin muuttaa systeemin niin, että saan nuo oliot liikkumaan ja poistettua jomman kumman välistä tiettyjen ehtojen täyttyessä?
Mitähän ihmettä yrität kysyä? Saat ne liikkumaan, kun muutat x- ja y-arvoja, ja voit poistaa niitä näin:
selaaja = Oliot.erase(selaaja);
Poiston jälkeen selaaja osoittaa seuraavaan kohtaan, joten jos poistat jotain kesken selailun, se pitää tehdä tuon ++selaaja-rivin sijaan:
if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { ++selaaja; }
Ahaaa! Nyt käsitin! Eiku en noita vectoreita ole koskaan kunnolla sisäistänyt, mutta nyt taisin saada ensimmäisen kunnon askeleen sen sisäistämiseen. Kiitos! :D
E: Tai sitten en ymmärtänyt, koska..
while(selaaja != lopussa){ std::cout << "x = " << selaaja->anna_x() << " y = " << selaaja->anna_y() << std::endl; PiirraKuva(hahmo, naytto, selaaja->anna_x(), selaaja->anna_y()); if (panos_x >= 500) { selaaja = Oliot.erase(selaaja); --selaaja; } else { ++selaaja; } }
tuo koodi palauttaa errorin 3.. eli peli kaatuu. en nyt muista mitä errori 3 tarkoitti olisiko ollut jonkun asian puuttuminen? Mutta miksi? Tein luultavasti jotain väärin.
E2: ja toinen on se, että jos poistan --selaaja; rivin panos menee kohtaan johon sen pitää ja jää jumiin. Siis koko peli jää jumiin.
Eihän tuossa koodissasi ole mitään järkeä. Jos panos_x asetetaan vain silmukan ulkopuolella (kuten tuossa ilmeisesti on), if-lauseen tulos on sama joka kierroksella, joten voisit yhtä hyvin tehdä vertailun vasta silmukan jälkeen ja poistaa kaiken kerralla (Oliot.clear()).
Rivi --selaaja on väärin, silloin käsittelet poiston jälkeen edellisen kohdan uudestaan. (Miksi aina menet muuttamaan asioita, jotka sinulle on ihan selvästi ja suoraan neuvottu ja selitettykin?)
no nyt se on suurin piirtein niin kuin koodin annoit, mutta peli jumittuu edelleen:
Siis nämä kaikki ovat ikuisessa while silmukassa mikä tarkistaa koska peli loppuu:
bool poistetaan=false; //Tästä eteenpäin kaikki on while silmukassa: Oliot.push_back(peli::Omaluokka(panos_x, panos_y)); std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); std::vector<peli::Omaluokka>::iterator lopussa = Oliot.end(); if (panos_x >= 500) { poistetaan=true; } while(selaaja != lopussa){ std::cout << "x = " << selaaja->anna_x() << " y = " << selaaja->anna_y() << std::endl; PiirraKuva(panos, naytto, selaaja->anna_x(), selaaja->anna_y()); if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { ++selaaja; } } poistetaan=false;
Niin, no minusta tuossa koodissa ei ole mitään vikaa. Luultavasti vain et itse ymmärrä, mitä teet. Kerrataanpa varmuuden vuoksi:
Lisäät vektoriin uuden Omaluokka-olion, joka on kohdassa panos_x, panos_y.
Tarkistat, onko panos_x suurempi kuin 500.
Käyt kaikki vektorin oliot:
Mietipä hetki, onko tuossa viimeisessä kohdassa mitään järkeä. Miksi ihmeessä kaikki panokset pitää poistaa, jos yksi (juuri äsken lisätty) on ruudun ulkopuolella?
Millä tavalla peli jumittuu? Tapahtuuko siinä jotain, vai jääkö se täysin paikalleen? Selvitä ylimääräisillä tulostuksilla, mihin kohti koodissa peli jumittuu.
Peli jumittuu siihen kohtaa kun olio pitäisi poistaa. Tarkalleen ja se jää täysin paikalleen. Ei tee mitään koko peli eikä anna virheraportteja.
Suosittelen tutustumaan semmoiseen hommaan kuin debuggaus.
Eli tässä tapauksessa voisit esimerkiksi laittaa breaklinen riville "poistetaan=true;" ja sitten siitä debuggerissa edetä rivi kerrallaan eteenpäin ja katsoa mitä se tekee.
Yhden virheen huomasinkin: Et voi hakea lopussa-muuttujaan valmiiksi end-arvoa, koska se voi muuttua poiston yhteydessä. Laita while-silmukan ehtoon muuttujan tilalle suoraan Oliot.end().
Ymmärsin, että tarkoitit näin:
selaaja = Oliot.erase(Oliot.end());
näyttäisi ainakin nyt poistavan tuon panoksen. Kiitos paljon! :D
En todellakaan tarkoittanut noin. Olen erittäin hämmästynyt, jos ohjelmasi oikeasti tuon muutoksen jälkeen toimii: kaiken järjen mukaan sen pitäisi kaatua tai vähintäänkin jättää panos poistamatta.
Puhuin while-silmukan ehdosta ja muuttujasta nimeltä lopussa. Minusta tämän selvemmin on vaikea selittää, mistä kohdasta on kyse, mutta sinulle näköjään pitää jokainen sana vääntää rautalangasta:
// MUUTA TÄLTÄ RIVILTÄ MUUTTUJAN lopussa TILALLE Oliot.end()! while(selaaja != lopussa)
Jäikö jotain vielä epäselväksi?
Noh enää se ei poista mitään..
while(selaaja != Oliot.end()){ std::cout << "x = " << selaaja->anna_x() << " y = " << selaaja->anna_y() << std::endl; PiirraKuva(panos, naytto, selaaja->anna_x(), selaaja->anna_y()); if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { ++selaaja; } }
Noh se varmaan johtuu siitä, että panos_x on alle 500. Kysyin tätä jo aiemmin: onko mitään järkeä siinä, että tutkit vain äsken lisätyn panoksen sijaintia, vai pitäisikö ehkä kuitenkin tarkistaa silmukan if-lauseessa tuo selaaja->anna_x()?
mitenkäs vectorissa olevan olion tietojen muokkaus sitten käy?
Yritin:
selaaja.x++; selaaja->anna_x()++; //no ok tän tiesinki et se ei toimi..
muutta ei tunnu onnistuvan. Koitin lisäks heittää tonne while silmukkaan mis noita olioita tarkastetaan tämän:
int uusi_x = selaaja->anna_x(); int uusi_y = selaaja->anna_y(); int uusi_x++; int uusi_y++; Oliot.push_back(peli::Omaluokka(uusi_x, uusi_y));
mutta peli jumiutuu..
mika132 kirjoitti:
mitenkäs vectorissa olevan olion tietojen muokkaus sitten käy?
Lisää luokkaan metodi, jolle annetaan parametreina x:n ja y:n uudet arvot, samaan tapaan kuin konstruktorissa.
lainaus:
muutta ei tunnu onnistuvan. Koitin lisäks heittää tonne while silmukkaan mis noita olioita tarkastetaan tämän:
int uusi_x = selaaja->anna_x(); int uusi_y = selaaja->anna_y(); int uusi_x++; int uusi_y++; Oliot.push_back(peli::Omaluokka(uusi_x, uusi_y));mutta peli jumiutuu..
Jumiutuu miten? Tuo ei voi mitenkään mennä edes kääntäjästä läpi.
En ymmärrä tuota konsruktio käsitettä? Mitä se meinaa? Ja kyllä se läpi meni. En tiedä sitten miten, mutta meni ainakin.
mika123 kirjoitti:
En ymmärrä tuota konsruktio käsitettä?
Konstruktori (josta hunajavohveli puhui) on luokan metodi, joka suoritetaan kun olio luodaan. Eli konstruktorin idea on rakentaa luokka käyttövalmiiksi.
Konstruktio on hieman eri asia ja "konsruktio" tuskin tarkoittaa mitään.
Kiinnostavaa sinänsä, että vaikka et tiedä, mitä konstruktori tarkoittaa, koodissasi on (ainakin) yksi sellainen. Tekisit viisaasti, jos et käyttäisi koodissasi asioita, joita et itse ymmärrä. Oikea järjestys on ensin selvittää perusteellisesti, mitä jokin asia tekee, ja vasta sitten soveltaa sitä omaan koodiin (ei kopioida!).
Hei sain ne liikkumaan, mutta peli kaatuu kun ammun kolmannen kerran..
Tässä koodi mitä tein:
namespace peli { class Omaluokka{ public: //Eli muutin nämä julkisiksi tiedoiksi int x; int y; public: Omaluokka(int x, int y){ this->x = x; this->y = y; } int anna_x(){ return x; } int anna_y(){ return y; } }; } if(hiiri & SDL_BUTTON(1)) { panos_x=hahmo_sijainti_x+50; panos_y=hahmo_sijainti_y+20; Oliot.push_back(peli::Omaluokka(panos_x, panos_y)); } std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); std::vector<peli::Omaluokka>::iterator lopussa = Oliot.end(); while(selaaja != Oliot.end()){ std::cout << "x = " << selaaja->anna_x() << " y = " << selaaja->anna_y() << std::endl; PiirraKuva(panos, naytto, selaaja->anna_x(), selaaja->anna_y()); if (selaaja->anna_x() >= 500) { poistetaan=true; } int x_arvo = selaaja->anna_x(); if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { ++selaaja; selaaja->x++; //pistin tähän näin. } }
mika132 kirjoitti:
Hei sain ne liikkumaan, mutta peli kaatuu kun ammun kolmannen kerran..
Mietihän, mitä lisäämäsi rivi tekee silmukan viimeisellä kierroksella. Vinkki: Katso edeltävää riviä.
sain toimimaan.. en tiedä kyllä onko yhtään oikea tapa, mutta tekee kuten pitää.. poistaa panoksen yksi kerrallaan ja antaa ampua niin kauan kun jaksaa..
while(selaaja != Oliot.end()){ std::cout << "x = " << selaaja->anna_x() << " y = " << selaaja->anna_y() << std::endl; PiirraKuva(panos, naytto, selaaja->anna_x(), selaaja->anna_y()); if (selaaja->anna_x() >= 500) { poistetaan=true; } if (poistetaan) { selaaja = Oliot.erase(selaaja); poistetaan=false; } else { selaaja->x++; ++selaaja; } }
kaikki tuntuisi olevan suht hyvin kasassa, mutta osumista en saa tehtyä.. että jos panos osuu niin tuhotaan vectori vihu..
Tässä yksi toteutus yritys monista:
while(selaaja != Oliot.end()){ //std::cout << "x = " << selaaja->anna_x() << " y = " << selaaja->anna_y() << std::endl; Game::PiirraKuva(Game::Photos::panos, selaaja->anna_x(), selaaja->anna_y(), false); if (selaaja->anna_x() >= 639) { poistetaan=true; } if (selaaja->anna_x() <= 0) { poistetaan=true; } if (selaaja->anna_y() >= 439) { poistetaan=true; } if (selaaja->anna_y() <= 0) { poistetaan=true; } while(vihut != zompie.end()){ std::cout << "selaajan x = " << selaaja->anna_x() << " vihun x = " << vihut->x << std::endl; Game::PiirraKuva(Game::Photos::zompii, vihut->x, vihut->y, true); if (selaaja->anna_x() == vihut->x) { poistetaan=true; } if (poistetaan) { vihut = zompie.erase(vihut); poistetaan=false; } } if (poistetaan) { selaaja = Oliot.erase(selaaja); poistetaan=false; } else { selaaja->x-=std::cos(selaaja->meno_kulma) * 12; selaaja->y+=std::sin(selaaja->meno_kulma) * 12; ++selaaja; } }
vihut on tehty siis myös vectoriin niistä vain otetaan hieman enemmän tietoa pihalle.. saan kyllä tulostettua vihut näytölle jos en laita tuota while selaajan whilen sisäpuolelle, mutta jos se ei ole siellä en pysty käyttämään selaaja->anna-x() funktiota tarkistuksessa.. Mikäs neuvoksi?
poistetaan-muuttujan käyttö on epäselvä. Kokeile laittaa rivin
while(selaaja != Oliot.end()){
jälkeen vain kerran (eikä enää missään vaiheessa toista kertaa)
poistetaan=false;
ja sitten katsot ehdot läpi mihin jää poistetaan=true;
Eli oletuksena ei poisteta mutta jos törmää niin silloin.
Toiseks vihut muuttuja pitää alustaa joka kerta ennen tuota toista while:a ja kasvattaa sitä silmukassa.
Kun et tahdo saada lyhyttäkään koodia oikein pysymään kasassa, kannattaisi yrittää tehdä kerralla mahdollisimman vähän. Tee erilliset silmukat ruudun reunojen tarkistukseen, osumisen tarkistukseen, liikuttamiseen ja piirtämiseen. (Muutenkin piirtämisen pitäisi olla ihan eri paikassa kuin noiden muiden. Muistatko matopeliopasta?)
silmukka (panokset) { jos ulkona ruudulta { poista panos; } muuten { seuraava panos; } } silmukka (panokset) { merkitse, että ei ole osunut; silmukka (viholliset) { jos osuu { merkitse, että osui; tapa vihollinen; break; } } jos osui { poista panos; } muuten { seuraava panos; } } silmukka (panokset) { liikuta panosta; } silmukka (viholliset) { liikuta vihollista; }
silmukka (panokset) { piirrä panos; } silmukka (viholliset) { piirrä vihollinen; }
hmm.. Tein sen matopeli oppaan mukaan.. eli liikkumiset yms pelinkellon tarkistuksen while silmukkaan ja loput piirtoon. Eli:
if (Game::panoksia >= 1) { if(hiiri & SDL_BUTTON(1)) { if (TimeLeft() == 0) { panos_x=hahmo_sijainti_x+50; panos_y=hahmo_sijainti_y+20; Oliot.push_back(peli::Omaluokka(panos_x, panos_y, kulma)); SDL_FreeSurface(Game::Tekstit::text_2); Game::panoksia--; Game::Tekstit::text_2 = Game::Tekstit::LoadText(" ", true, Game::panoksia, Game::Fontit::font, 255, 0, 0); } } } std::vector<peli::Zompi>::iterator vihut = zompie.begin(); std::vector<peli::Zompi>::iterator vihut_lopussa = zompie.end(); std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); std::vector<peli::Omaluokka>::iterator lopussa = Oliot.end(); int ge=0; int aksat[4]; while (pelin_kello + ajan_muutos <= Game::sekunnit()) { pelin_kello += ajan_muutos; piirretty = false; Huone_2_toiminnot(button); while(selaaja != Oliot.end()){ if (selaaja->anna_x() >= 639) { selaaja = Oliot.erase(selaaja); } if (selaaja->anna_x() <= 0) { selaaja = Oliot.erase(selaaja); } if (selaaja->anna_y() >= 439) { selaaja = Oliot.erase(selaaja); } if (selaaja->anna_y() <= 0) { selaaja = Oliot.erase(selaaja); } } while(selaaja != Oliot.end()){ poistetaan=false; while(vihut != zompie.end()){ if (selaaja->x >= vihut->x + 50 && selaaja->x <= vihut->x + 100) { poistetaan=true; vihut = zompie.erase(vihut); break; } else { ++vihut; } } if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { selaaja->x-=std::cos(selaaja->meno_kulma) * 12; selaaja->y+=std::sin(selaaja->meno_kulma) * 12; ++selaaja; } } } if (piirretty) { Game::odota(); } else { while(selaaja != Oliot.end()){ Game::PiirraKuva(Game::Photos::panos, selaaja->anna_x(), selaaja->anna_y(), false); ++selaaja; } while(vihut != zompie.end()){ Game::PiirraKuva(Game::Photos::zompii, vihut->x, vihut->y, true); ++vihut; } Game::Photos::temp = rotozoomSurface(Game::Photos::hahmo, rad2deg(kulma), 1, 1); Game::PiirraKuva(Game::Photos::temp, hahmo_sijainti_x, hahmo_sijainti_y, true); SDL_FreeSurface(Game::Photos::temp); Game::DrawText(Game::Tekstit::text_2, 500, 10); piirretty = false; } SDL_Flip(Game::ruutu); }
Tuon koodin kuitenkin mennessään läpi on efekti se, että ampuessani panos menee noin 20 pikseliä eteenpäin ja sen jälkeen peli menee jumiin.
Mitä ensimmäisessä silmukassa nyt tapahtuu, jos panos ei törmää? Entä mikä on selaajan arvo silmukan jälkeen ja mitä siis kaikissa lopuissa silmukoissa tapahtuu?
Muutin hieman koko järjestelmää, koska mietein, että miksi tehdä niin monta silmukkaa liittyen panokseen (selaaja) koska kaiken voi hoitaa yhdessäkin.
mutta tämän hetken koodissa käy niin, että panoksen osuessa yhteen viholliseen kuolee kaikki viholliset jonka jälkeen peli kaatuu ja palauttaa arvon 3.
while (pelin_kello + ajan_muutos <= Game::sekunnit()) { pelin_kello += ajan_muutos; piirretty = false; Huone_2_toiminnot(button); while(selaaja != Oliot.end()){ poistetaan=false; if (selaaja->anna_x() >= 639) { poistetaan=true; } else if (selaaja->anna_x() <= 0) { poistetaan=true; } else if (selaaja->anna_y() >= 439) { poistetaan=true; } else if (selaaja->anna_y() <= 0) { poistetaan=true; } while(vihut != zompie.end()){ if (selaaja->x >= vihut->x + 20 && selaaja->x <= vihut->x + 40) { poistetaan=true; vihut = zompie.erase(vihut); } else { ++vihut; } } if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { selaaja->x-=std::cos(selaaja->meno_kulma) * 12; selaaja->y+=std::sin(selaaja->meno_kulma) * 12; ++selaaja; } } } if (piirretty) { Game::odota(); } else { while(selaaja != Oliot.end()){ Game::PiirraKuva(Game::Photos::panos, selaaja->anna_x(), selaaja->anna_y(), false); ++selaaja; } while(vihut != zompie.end()){ Game::PiirraKuva(Game::Photos::zompii, vihut->x, vihut->y, true); ++vihut; } Game::Photos::temp = rotozoomSurface(Game::Photos::hahmo, rad2deg(kulma), 1, 1); Game::PiirraKuva(Game::Photos::temp, hahmo_sijainti_x, hahmo_sijainti_y, true); SDL_FreeSurface(Game::Photos::temp); Game::DrawText(Game::Tekstit::text_2, 500, 10); piirretty = false; } SDL_Flip(Game::ruutu);
Mietipä seuraavaa koodia:
int i = 0; int j = 0; int k = 0; while (k < 3) { std::cout << "kierros " << k << ":" << std::endl; std::cout << " ylempi i-silmukka:" << std::endl; while (i < 4) { std::cout << " i = " << i << std::endl; std::cout << " j-silmukka:" << std::endl; while (j < 4) { std::cout << " i, j = " << i << ", " << j << std::endl; ++j; } std::cout << " j-silmukka loppui" << std::endl; ++i; } std::cout << " ylempi i-silmukka loppui" << std::endl; std::cout << " alempi i-silmukka:" << std::endl; while (i < 4) { std::cout << " i = " << i << std::endl; ++i; } std::cout << " alempi i-silmukka loppui" << std::endl; ++k; }
Mitä tapahtuu ja miksi? Oma koodisi toimii tällä hetkellä juuri näin. Korjauksen pitäisi olla itsestään selvä; jos ei ole, hautaa peliprojektisi ja rupea koodaamaan noita tekstimuotoisia kertotauluja ym. perusharjoituksia (kuten PHP-haasteessa on).
Juu tajusin tuon koodin.. Ei se voi suorittaa noita kolmea muuta whilea koska ensimmäinen while toteutuu vain niin kauan, kun k on vähemmän kuin 3.
mutta jos toteutan tuon kohdan näin:
std::vector<peli::Zompi>::iterator vihut = zompie.begin(); std::vector<peli::Zompi>::iterator vihut_lopussa = zompie.end(); std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); std::vector<peli::Omaluokka>::iterator lopussa = Oliot.end(); while (pelin_kello + ajan_muutos <= Game::sekunnit()) { pelin_kello += ajan_muutos; piirretty = false; Huone_2_toiminnot(button); while(vihut != zompie.end()){ while(selaaja != Oliot.end()){ poistetaan=false; if (selaaja->anna_x() >= 639) { poistetaan=true; } else if (selaaja->anna_x() <= 0) { poistetaan=true; } else if (selaaja->anna_y() >= 439) { poistetaan=true; } else if (selaaja->anna_y() <= 0) { poistetaan=true; } if (selaaja->x >= vihut->x + 20 && selaaja->x <= vihut->x + 40) { poistetaan=true; vihut = zompie.erase(vihut); } else { ++vihut; } if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { selaaja->x-=std::cos(selaaja->meno_kulma) * 12; selaaja->y+=std::sin(selaaja->meno_kulma) * 12; ++selaaja; } } } }
Peli on jumissa. Ei anna ampua eikä liikkua. Ei tehdä yhtään mitään.
ja jos kohta:
if (selaaja->x >= vihut->x + 20 && selaaja->x <= vihut->x + 40) { poistetaan=true; vihut = zompie.erase(vihut); } else { ++vihut; }
ei ole selaaja != Oliot.end() silmukan sisällä palautuu pelistä arvo 3.
Mikä on vihut-muuttujan arvo kun koodi saapuu:
while(vihut != zompie.end()){
Entä seuraavalla kierroksella? Eikö tarkoituksena ollut käydä kaikki vihut läpi jokaista oliota kohti?
Tarkoitatko jotain näistä:
zompie.push_back(peli::Zompi(640, 20, 180, 30, 10)); zompie.push_back(peli::Zompi(640, 100, 180, 40, 10)); zompie.push_back(peli::Zompi(640, 180, 180, 20, 10)); zompie.push_back(peli::Zompi(640, 260, 180, 80, 10)); std::vector<peli::Zompi>::iterator vihut = zompie.begin(); std::vector<peli::Zompi>::iterator vihut_lopussa = zompie.end(); std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); std::vector<peli::Omaluokka>::iterator lopussa = Oliot.end();
vai tarkoitatko että jos tulostan konsoliin vihut arvon niin mitä sieltä tulee.. nimittäin tuntuu olevan mahdotonta se..
std::clog << "Vihut arvo: " << vihut << std::endl;
error: no match for 'operator<<' in 'std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char, std::char_traits<char> >&)(& std::clog)), ((const char*)"Vihut arvo: ")) << vihut'
mika132 kirjoitti:
Juu tajusin tuon koodin.. Ei se voi suorittaa noita kolmea muuta whilea koska ensimmäinen while toteutuu vain niin kauan, kun k on vähemmän kuin 3.
Väärin. Yritäpä uudelleen.
Eikun ei se voi suorittaa viimeistä kertaa noita muita whileja koska k tulee ensin täyteen. Anteeksi.. :D
Väärin edelleen. Käännä ja aja Metabolixin koodi, katso mitä se tulostaa ja yritä hahmottaa.
ahaaa..
Se siis tekee tekee kaikki asiat heti ensimmäisellä kierroksella, koska i ja j arvoja ei palauteta se ei tee niitä kuin ensimmäisellä kierroksella.
nyt meni oikein.. eikös?
mika132 kirjoitti:
ahaaa..
Se siis tekee tekee kaikki asiat heti ensimmäisellä kierroksella, koska i ja j arvoja ei palauteta se ei tee niitä kuin ensimmäisellä kierroksella.
nyt meni oikein.. eikös?
Palauteta? Kenelle? Miksi?
Oikeasti mietipä muuttujien i ja j arvoja toisella kierroksella ylimmän while-silmukan sisällä.
niin niin.. ne ovat jo yli 4, koska niitä ei palauteta 0 missään vaiheessa, mutta en ymmärrä miten voin tuota koodia hyödyntää vectoreiden kanssa? Miten voin palauttaa vectorit nollaan seuraavalla kierroksella?
Niin, mitenköhän vektoreista saa tietää ensimmäiseen indeksiin osoittavan iteraattorin?
Metabolix kirjoitti:
Korjauksen pitäisi olla itsestään selvä; jos ei ole, hautaa peliprojektisi ja rupea koodaamaan noita tekstimuotoisia kertotauluja ym. perusharjoituksia (kuten PHP-haasteessa on).
:)
Meninkin päästämään jo riemun kiljahduksen.. :D
Huomasinpa toisella testikerralla, että tuli 2 ongelmaa (tai 3 mutta sen yhden osaan korjata)
Ongelma 1:
Vastustajat pitää tappaa tietyssä järjestyksessä.
Ongelma 2:
Yhden panoksen mennessä tuhoutumis pisteeseen se tuhoaa kaikki panokset.
while (pelin_kello + ajan_muutos <= Game::sekunnit()) { pelin_kello += ajan_muutos; piirretty = false; Huone_2_toiminnot(button); while(vihut != zompie.end()){ poistetaan=false; tapetaan_vihu=false; while(selaaja != Oliot.end()){ if (selaaja->anna_x() >= 639) { poistetaan=true; } else if (selaaja->anna_x() <= 0) { poistetaan=true; } else if (selaaja->anna_y() >= 439) { poistetaan=true; } else if (selaaja->anna_y() <= 0) { poistetaan=true; } if (selaaja->x >= vihut->x && selaaja->x <= vihut->x + 40) { if (selaaja->y >= vihut->y && selaaja->y <= vihut->y + 40) { tapetaan_vihu=true; } } if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { selaaja->x-=std::cos(selaaja->meno_kulma) * 12; selaaja->y+=std::sin(selaaja->meno_kulma) * 12; ++selaaja; } } if (tapetaan_vihu) { vihut = zompie.erase(vihut); } else { ++vihut; } } } if (piirretty) { Game::odota(); } else { while(selaaja != Oliot.end()){ Game::PiirraKuva(Game::Photos::panos, selaaja->anna_x(), selaaja->anna_y(), false); ++selaaja; } while(vihut != zompie.end()){ Game::PiirraKuva(Game::Photos::zompii, vihut->x, vihut->y, true); ++vihut; } Game::Photos::temp = rotozoomSurface(Game::Photos::hahmo, rad2deg(kulma), 1, 1); Game::PiirraKuva(Game::Photos::temp, hahmo_sijainti_x, hahmo_sijainti_y, true); SDL_FreeSurface(Game::Photos::temp); Game::DrawText(Game::Tekstit::text_2, 500, 10); piirretty = false; } SDL_Flip(Game::ruutu);
mika132 kirjoitti:
Miten voin palauttaa vectorit nollaan seuraavalla kierroksella?
Samalla tavoin kuin ne ovat nollassa alunperinkin. Katso ensimmäinen rivi, jossa selaaja ja vihut määritellään.
No nyt sain nollattua, mutta yksi ongelma on vielä.
Se yksi ongelma on vielä se, että viholliset pitää tappaa järjestyksessä.
while (pelin_kello + ajan_muutos <= Game::sekunnit()) { pelin_kello += ajan_muutos; piirretty = false; Huone_2_toiminnot(button); while(selaaja != Oliot.end()){ poistetaan=false; if (selaaja->anna_x() >= 639) { poistetaan=true; } else if (selaaja->anna_x() <= 0) { poistetaan=true; } else if (selaaja->anna_y() >= 439) { poistetaan=true; } else if (selaaja->anna_y() <= 0) { poistetaan=true; } if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { selaaja->x-=std::cos(selaaja->meno_kulma) * 12; selaaja->y+=std::sin(selaaja->meno_kulma) * 12; ++selaaja; } } std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); while(vihut != zompie.end()){ poistetaan=false; tapetaan_vihu=false; while(selaaja != Oliot.end()){ if (selaaja->x >= vihut->x && selaaja->x <= vihut->x + 40) { if (selaaja->y >= vihut->y && selaaja->y <= vihut->y + 40) { tapetaan_vihu=true; } } if (poistetaan) { selaaja = Oliot.erase(selaaja); } else { ++selaaja; } if (selaaja == Oliot.end()) { std::vector<peli::Omaluokka>::iterator selaaja = Oliot.begin(); } } if (tapetaan_vihu) { vihut = zompie.erase(vihut); } else { ++vihut; } if (vihut == zompie.end()) { std::vector<peli::Zompi>::iterator vihut = zompie.begin(); } } }
tuohon loppuun sen verran, että yritin sitäkin, että tuo vihut juttu nollattaisi tuolla ulkopuolella, mutta sekään ei sitä korjannut. Tarkoitan nyt vihut != zompie.end() silmukan ulkopuolella.
Riveillä 43 ja 52 on täysin tyhjät lauseet. Eivät tee mitään. Kyseisten skooppien 'selaaja'/'vihut' muuttujat tuhoutuvat heti riveillä 44 ja 53 (menevät skoopista ulos). Se mitä haluat tehdä aiheuttaisi sitä paitsi ikuisen loopin.
Koodaus ei ole sun juttus, suosittelen vaikka kutomista.
Kiitos sanoista! =)
Sain nimittäin tuon johdosta halun tehdä tuon systeemin ja sain sen! Ampuminen ja vihollisten kuoleminen toimii nyt 110%!! :D
Ps. Kiitos kaikille auttamisesta. En vain huomannut, että koodistani puuttui pari oleellista asiaa. =)
Kun nyt kerran opiskelet C++, niin voisi olla kannattavaa tehdä noille vihulaisille ja panoksille omat metodit liikkumista, törmäystarkistusta ja piirtämistä varten. Pysyisi meinaan tuo peliluuppi hiukan luettavamman näköisenä.
Esim. alla nopeasti kirjoitettuna "luokka" panoksia varten Hollywoodilla (en osaa C++ olio-ohjelmointia):
shots = { shots = {}} Function shots:add(x, y, xs, ys) Local shot = { x = x, y = y, xs = xs, ys = ys } InsertItem(self.shots, shot) EndFunction Function shots:del(pos) RemoveItem(self.shots, pos) EndFunction Function shots:move() Local a, b = NextItem(self.shots) While GetType(a) <> #NIL b.x = b.x + b.xs b.y = b.y + b.ys If b.x < 0 Or b.x > 800 self:del(a) ElseIf b.y < 0 Or b.y > 600 self:del(a) EndIf a, b = NextItem(self.shots, a) Wend EndFunction Function shots:draw() Local a, b = NextItem(self.shots) While GetType(a) <> #NIL DisplayBrush(6, b.x, b.y, {AnchorX = 0.5, AnchorY = 0.5} ) a, b = NextItem(self.shots, a) Wend EndFunction Function shots:collision() Local w1 = GetAttribute(#BRUSH,6,#ATTRWIDTH) Local h1 = GetAttribute(#BRUSH,6,#ATTRHEIGHT) Local w2 = GetAttribute(#BRUSH,7,#ATTRWIDTH) Local h2 = GetAttribute(#BRUSH,7,#ATTRHEIGHT) Local k, c Local a, b = NextItem(self.shots) While GetType(a) <> #NIL c = ListItems(baddies.baddies) For k = 0 To c-1 If Collision(#BRUSH, 6, b.x - w1/2, b.y - h1/2, 7, baddies.baddies[k].x - w2/2, baddies.baddies[k].y - h2/2) explosions:add(b.x, b.y) shots:del(a) baddies:del(k) points = points + 1 Break EndIf Next a, b = NextItem(self.shots, a) Wend EndFunction
Metodien avulla peliluupista saa paljon selkeämmän, kun tarvitsee vain:
player:move(xs!, ys!) player:rotate(player.angle) baddies:move() shots:move() shots:collision() baddies:collision() starfield:draw() player:draw() baddies:draw() flames:animate() flames:draw() explosions:animate() explosions:draw() shots:draw()
Tuonkin voisit vielä kyllä "pakata" itse peliluokalle metodeihin: move, collision, animate ja draw.
Aihe on jo aika vanha, joten et voi enää vastata siihen.