Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Ampuminen

Sivun loppuun

mika132 [12.12.2010 22:44:27]

#

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ä?

Metabolix [12.12.2010 22:49:43]

#

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;
}

mika132 [12.12.2010 23:49:13]

#

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.

Metabolix [13.12.2010 00:13:53]

#

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?)

mika132 [13.12.2010 00:23:33]

#

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;

Metabolix [13.12.2010 00:33:53]

#

Niin, no minusta tuossa koodissa ei ole mitään vikaa. Luultavasti vain et itse ymmärrä, mitä teet. Kerrataanpa varmuuden vuoksi:

  1. Lisäät vektoriin uuden Omaluokka-olion, joka on kohdassa panos_x, panos_y.

  2. Tarkistat, onko panos_x suurempi kuin 500.

  3. Käyt kaikki vektorin oliot:

    • tulostat koordinaatit
    • piirrät panoksen haluttuun kohtaan
    • jos äsken mainittu vertailu oli tosi, poistat tämänkin panoksen

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.

mika132 [13.12.2010 00:46:20]

#

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.

Grez [13.12.2010 00:52:26]

#

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.

Metabolix [13.12.2010 00:53:31]

#

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().

mika132 [13.12.2010 01:02:42]

#

Ymmärsin, että tarkoitit näin:

selaaja = Oliot.erase(Oliot.end());

näyttäisi ainakin nyt poistavan tuon panoksen. Kiitos paljon! :D

Metabolix [13.12.2010 01:09:03]

#

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?

mika132 [13.12.2010 01:31:29]

#

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;
    }
}

Metabolix [13.12.2010 01:42:50]

#

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()?

mika132 [13.12.2010 01:52:57]

#

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..

hunajavohveli [13.12.2010 09:41:20]

#

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.

mika132 [13.12.2010 18:50:15]

#

En ymmärrä tuota konsruktio käsitettä? Mitä se meinaa? Ja kyllä se läpi meni. En tiedä sitten miten, mutta meni ainakin.

Grez [13.12.2010 20:01:39]

#

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.

Metabolix [13.12.2010 20:03:41]

#

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!).

mika132 [13.12.2010 23:36:30]

#

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.
                }
            }

hunajavohveli [14.12.2010 01:26:04]

#

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ä.

mika132 [14.12.2010 02:01:10]

#

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;
    }
}

mika132 [14.12.2010 06:21:10]

#

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?

User137 [15.12.2010 16:49:23]

#

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.

Metabolix [15.12.2010 17:07:23]

#

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;
}

mika132 [16.12.2010 10:18:35]

#

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.

Metabolix [16.12.2010 10:23:42]

#

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?

mika132 [16.12.2010 10:42:46]

#

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);

Metabolix [16.12.2010 11:24:25]

#

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).

mika132 [16.12.2010 11:38:38]

#

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.

User137 [16.12.2010 11:57:26]

#

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?

mika132 [16.12.2010 12:11:57]

#

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'

Chiman [16.12.2010 12:44:54]

#

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.

mika132 [16.12.2010 12:47:27]

#

Eikun ei se voi suorittaa viimeistä kertaa noita muita whileja koska k tulee ensin täyteen. Anteeksi.. :D

Chiman [16.12.2010 12:50:12]

#

Väärin edelleen. Käännä ja aja Metabolixin koodi, katso mitä se tulostaa ja yritä hahmottaa.

mika132 [16.12.2010 14:01:37]

#

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?

Teuro [16.12.2010 14:03:52]

#

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ä.

mika132 [16.12.2010 14:11:27]

#

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?

Milo [16.12.2010 14:29:11]

#

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).

:)

mika132 [16.12.2010 14:52:53]

#

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);

Chiman [16.12.2010 14:57:23]

#

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.

mika132 [16.12.2010 15:21:47]

#

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.

Milo [16.12.2010 15:55:11]

#

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.

mika132 [16.12.2010 16:19:23]

#

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. =)

jalski [17.12.2010 13:24:40]

#

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.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta