2010 m. lapkričio 23 d., antradienis

Klaidos, klaidos, klaidos...

Prieš gerą savaitę ant lapo užsirašiau nemažai punktų apie tai, ko žaidime dar nėra (arba ko per daug). Klaidų ir lūžimų žaidime buvo akivaizdžiai per daug. Tad vienas iš punktų buvo "Pašalinti programos lūžimus (pažiūrėti į animacijas)". Toks "mažutis" punkčiukas palyginus su kokiu "Padaryti, kad minotaurai galėtų imti daiktus žaidimo lauke".;) Vargais negalais pavyko sumažinti lūžimų dažnumą ir ištaisyti nemažai klaidų...

O buvo viskas taip. Įsisąmoninau du dalykus: 1) reikės dar ne vieną kėdę nutrinti, kol galėsiu sakyti, kad kažkas veikia ir tai iš tikrųjų veiks, 2) turiu prisiekti, kad naudosiu panašią sintaksę:
if (somePointer)
{
     delete somePointer;
     somePointer = 0;
}
o ne:
delete somePointer
net jei esu tikras, kad tas pointeris į kažką rodo. Šiandien rodo, o rytoj jau nebe. Dėl pirmo punkto viskas kur kas blogiau - pvz.: buvau tikras, kad bet kokios operacijos su string klase yra nekaltos ir negali sukelti staigios mirties mano programai. WRONG! Buffer overflow, you are out! C++ netikrina ribų. Kaip tik dabar vėl išplaukia rtfb vaizdas (įsivaizduojamas) ir sako: "Nereikėjo pradėti nuo c++".:)

Beje, animacijos (t.y. Animacijų Būsenų Mašina) buvo mažiausiai kaltos ir puikiausiai darė savo darbą (gal dėl to, kad suprogramuotos buvo palyginus neseniai).

Taigi kas padaryta:
Ištaisyta dauguma klaidų.
Minotaurai gali paimti daiktus ir pinigus nuo žemės.
Rodomi įvairūs užrašai - tipo "Double kill", "Stunned by ...", "Item gained" ir t.t.
Pradėtas piešti akademijos (vietos, kur treniruojasi minotaurai) vidinis kiemas. Dar nieko gražaus.

Artimiausiu metu (savaitė ar pan.) planuoju parodyti ką nors žaidžiamo.

Beje, vyrukas iš paveiksliuko - vienas iš minotaurų trenerių. Jis klausia: "Ar tikrai nori treniruotis? Šitas reikalas ne minkštakūniams."

5 komentarai:

  1. Tokios klaidos parodo disciplinos trūkumą. Realiam gyvenime jei atsiranda bent vienas išdaužtas langas ar grafitis, tuoj pasipila lavina išdaužtų langų ir grafičių. Todėl nuo pat pradžiu reikia stengtis nepalikti netvarkos. Kiek pas tave buvo kalnas warningų...

    Padaryk trenerį rtfb, kur sakytų "Ar tikrai nori programuoti -=_C++_=-, šitas reikalas ne minkštakūniams", reference pic http://lh3.ggpht.com/_T8Oq_wge5kg/Sdm_VwWWb6I/AAAAAAAABeI/wUHooRG39PQ/s800/IMGP0937.JPG :]]]]]

    AtsakytiPanaikinti
  2. Na tavo požiūris į pointer‘ių reikšmės tikrinimą prieš atlaisvinant atmintį yra iš esmės neteisingas.
    Teisingai darei kai naudojai vien tik trynimo komandą. Tačiau yra dar keletas taisyklių ką reikėjo padaryti:
    1. Sukurdamas pointer‘į užpildyk jį 0, tuomet jei ir nebuvo rezervuota atmintis 'delete' komanda bus teisinga (programa nelūš).
    2. Jei atlaisvinus vietą pointer‘is vis dar gali būti naudojamas ( kintamasis ne lokalus funkcijos kintamasis, o pvz. klasės kintamasis) užpildyk jo reikšme 0.
    Jei vis dėl to nepavyksta išvengti klaidų, reikia pasirašyti funkcijas, kurios registruotų kaip atmintis buvo rezervuojama ir atlaisvinama. Bei jei bandoma atlaisvinti atmintį kuri nebuvo rezervuota nagrinėtis kas ir kaip. ( paieškok google‘i ‚CrtDbg‘ arba ‚ CrtDbg Library‘).
    Sėkmės

    AtsakytiPanaikinti
  3. Ar nepaisant to, kad mano požiūris į pointerius yra neteisingas, jis leidžia man atsikratyti neegzistuojančių objektų trynimo ir palaidų pointerių? Jei taip, man nesunku parašyti tą if'ą. Reikalas tas, kad sudaliju savo žaidimą į būsenas, iš kurių kiekviena yra atskira klasė su savo on_entry(), on_update() ir on_exit(). Dažnai resursai sukuriami ir pradedami naudoti vienoje būsenoje, o panaikinami visai kitoje. Būsenų tvarka dažnai keičiasi (prisipažinsiu, neparašiau design doc'o), tad toks būdas man pasirodė paprastas ir greitas metodas valdyti resursus. Aišku, galėčiau sutaupyti savo laika pasinaudodamas tavo patarimais - nežinojau, kad delete puikiai susitvarko su 0 pointeriu.

    AtsakytiPanaikinti
  4. delete funkcija pati netrina tuščių pointer‘ių (užpildytu 0), tad tavo darbas beprasmis.
    O programa lūžta todėl, kad bandoma atlaisvinti atmintį kuri nebuvo rezervuota. Tad jei neužpildai pradžioje (ar po atlaisvinimo) pointer‘io nuliu, nors ir su tavo if, sąlyga bus teisinga. Tad programa bandys atlaisvinti tai, kas nerezervuota.
    O struktūra neturi esmės (kaip tu kuri objektus, tavo paminėtos būsenos). Na nebent nuorodos į šiuos objektus naudojamos iš daugelio vietų.
    Tuomet naikindamas objektą, visas nuorodas į šį objektą turi užpildyti 0. T.y. susinaikindamas objektas turi kažkur pranešti – ‚manęs nebėra‘, o kiekvienas objektas kuris naudoja nuorodą į jį, panaikinti šia nuorodą ( užpildyti 0 ar dar kažkaip pasinaikinti).

    AtsakytiPanaikinti
  5. Viską supratau. Tą savo if'ą taip ir rašau su mintimi, kad jei pointeris nenulinis, bandoma objektą trinti ir pointeris verčiamas nuliu. Teoriškai, jei visada trinu tokiu būdu, pointeriai, kurie rodė į sunaikintą objektą turėtų visada tapti nuliais. Problema ta, kad galėjau paprasčiausiai dar ne visur sugaudyti paprastus vienišus delete. Beje, problemų dėl neinicializuotų į 0 pointerių irgi turėjau, jau pasimokiau.:)

    AtsakytiPanaikinti