Olen toteuttanut ampumisen mutta en saa sitä toimimaan kunnolla. Olen lukenut putkasta ampumiseen liittyviä topikkeja, mutta en ole siltikään saanut ampumista toimimaan. Elikkäs olen saanut ampumisen toimimaan jotenkin kun olen käyttänyt taulukkoa int Ammus ammukset[AMMUKSIA]; mutta miten saan toimimaan vectoreiden kanssa?
Olen pähkäillyt ongelmaa jo 3 päivää, joten turha väittää, etten olisi miettinyt itse.
Tarkoitus on saada välilyönnistä tyyppi ampumaan tiettyyn suuntaan (suunnat 1-4)
ja ammukset pitäisi tallentaa vectoriin.
Ajattelin sen toteutusta vectoreilla jotenkin näin, mutta en saanut toimimaan. :(
if(player::keyboard[SDLK_SPACE]) { player::Ammu(); } void player::Ammu() { Ammus *luoti=new Ammus; ammukset.push_back(luoti); }
Voisiko joku ruksata esimerkin, jossa olisi yksinkertainen ammus luokka ja tuo funktio?
Olisin todella kiitollinen, tai sitten voi tehdä jonkin muun esimerkkikoodin ja minä yritän sen pohjalta toteuttaa oman koodin.
Olen kyllä todella huono ilmaisemaan ongelmiani. :D:D
class Ammus { private: int suunta; public: Ammus(int p_suunta): suunta(p_suunta) {} };
class Pelaaja { private: std::vector<Ammus> ammukset; int valittu_suunta; public: Pelaaja(); void ammu() { ammukset.push_back(Ammus(valittu_suunta)); } };
-- Pelaaja pelaaja; -- if (pelaajan_tulisi_ampua()) pelaaja.ammu(); --
Näinkin yksinkertaisissa sovelluksissa automaattinen muistinhallinta riittänee täysin.
Oke kiitos... :D
Edit:
miten sitten toteutan tämän. Muutin koodia tuohon suuntaan niin ohjelma vain välähtää ruudulla... :S:S:S:S
Mulla on kaikki tarkastukset ja luodin liikuttaminen toteutettu forissa, eli toimiiko nyt suoraan samalla tavalla+
for(int j=0;j<panosLaskuri;++j) { ammukset[j].Move(); ammukset[j].tarkistaOsumatSeiniin(); }
Kun ammuksia kuitenkin luultavasti tulee aina lisää ja katoilee satunnaisessa järjestyksessä, tietorakenteeksi voisi harkita listaa (std::list), jonka kanssa satunnaisen ammuksen poistokin tapahtuu vakioajassa (O(1)) eikä lineaarisesti (O(n)) kuten vektorilla. Toisaalta kun ammusten järjestyksellä ei ole merkitystä, myös vektorilla pääsee vakioaikaiseen ratkaisuun, kun poistettaessa siirtää poistettavan paikalle ensin viimeisen alkion ja poistaa sitten vektorin lopussa olevan.
template <typename T> void poista_valista(std::vector<T>& t, int indeksi) { // Vaihdetaan poistettavan ja viimeisen paikkaa; abXdeF => abFdeX swap(t.at(indeksi), t.at(t.size() - 1)); // Poistetaan viimeinen; abFdeX => abFde, X hävisi ja F siirtyi sen paikalle t.pop_back(); } poista_valista(ammukset, indeksi); // Tai jopa iteraattorityypille I (std::vector<T>::iterator tms.); // tämä funktio on tosin hieman vaarallinen, koska esimerkiksi satunnainen // Ammus* kelpaisi "poistettavaksi" ja tulos olisi tietenkin väärä. template <typename T, typename I> void poista_valista(std::vector<T>& t, I const& i) { std::swap(*i, *t.rbegin()); t.pop_back(); } poista_valista(ammukset, iteraattori_tai_osoitin);
Muokkaus.
Älä käytä omia laskurimuuttujia vaan size-funktiota (vektori.size(), lista.size() jne.)
Juu, mutt olin toteuttanut tämän taulukolla, ku en saanut toimimaan... projektissa käytetään vectoreita myös pelaajan veren paikantamiseen, vihollisten ruumiiden varastoimiseen ja vihollisen veren... Mutta joo, taidan aloittaa koodaan alusta koko homman, koska en ole periyttänyt luokkia mistään yläluokasta niin on tullut hirveästi turhaa ja huonosti ylläpidettävää koodia... (reilut 1000riviä) :D
Miten tää totteutettais listalla?
Ihan samalla tavalla.
Voisit nyt yrittää selittää ensin, mikä kohta on ongelmana. Koodaa vaikka ohjelma ensin niin, että se toimii yhdellä ammuksella. Toteuta tämä viimeksi mainitulla tyylillä (tarkista_kaikki -> tarkista_yksi -> seuraukset). Tässä vaiheessa siis tarkista_kaikki kutsuu funktiota tarkista_yksi vain kerran tällä ainoalla ammuksella ja useamman ammuksen lisääminen a) ei tee mitään tai b) ylikirjoittaa aina vanhan ammuksen. Kun tämä yksi ammus sitten lentää oikeaan paikkaan, muutat ammuksen lisäystä niin, että se lisää ammuksen listaan, ja samalla tietenkin muutat myös ammuksen tuhoamisen oikeassa paikassa ja laitat tarkistusfunktion käymään kaikki ammukset läpi.
Kannattaa opetella käyttämään viittauksia. Esimerkiksi juuri tuollaisessa listatyyppisessä ratkaisussa käytännössä koko ohjelman pitäisi käsitellä listalla olevia ammuksia vain viittausten kautta. Viittaus on melkein kuin osoitin, mutta sen kanssa tiettyjä tyypillisiä virheitä ei voi sattua vahingossa. Syntaksikin on toki hieman erilainen:
void osoitin(Ammus *ammus) { ammus->jasen(); } osoitin(&ammus);
void viittaus(Ammus& ammus) { ammus.jasen(); } osoitin(ammus);
Ilman osoitinta tai viittausta funktiokutsussa luotaisiin aina uusi kopio ammuksesta. Viittauksen kanssa kuitenkin käsitellään yhä samaa ammusta.
Voit katsoa listan toiminnasta ja sen funktioista esimerkiksi osoitteesta www.cppreference.com. Kannattaa myös katsoa Metabolixin kirjoitukset tarkkaan läpi. Varsinkin viittauksista kannattaa ottaa onkeensa, joista itse suosittelisin tuota jälkimmäistä, koska ilmeisesti yrität kirjoittaa C++-tyylisesti. Alempi on enemmän C++-tyylinen, ylemmän ollessa taasen enemmän C-tyyliä, mutta suurta väliähän tuolla ei ole.
Aihe on jo aika vanha, joten et voi enää vastata siihen.