Dejan Katašić: FLASH I ACTIONSCRIPT, diplomski rad

3                  Prvi primer: Pasijans

Jedna od najzaslužnijih aplikacija u računarskom opismenjavanju svakako jeste čuvena igra kartama Solitaire iz standardnog paketa Windows. Pasijans je poznatiji naziv igre. Program Pasijans ima za cilj ilustraciju korišćenja objekta movieClip i realizaciju interakcije u ActionScriptu, u Flashu.

3.1          Elementi pasijansa

Pasijans je igra sa kartama. Radna površina podeljena je na:

·        7 kolona – celom širinom, centralni i donji deo površine, sa kartama slaganim jedna na drugu i određenim smicanjem ka dole

·        dek – sadrži ostatak špila, karte nepodeljene na kolone, gornji levi ugao

·        4 steka – za slaganje karata po bojama i veličini, gore desno

·        kontrolni deo – nova partija i undo-redo, između deka i stekova

3.1.1     Karte

Karte su grafički objekti sa kojima korisnik vrši interakciju, tj. igra igru.

Na karti su uočena tri dela:

·        prednji

·        zadnji

·        dugme

Svaki deo može biti vidljiv ili nevidljiv, u zavisnosti od stanja u kome se neka posmatrana karta nalazi. Stanje “otvorena” predstavlja kartu kojoj se vidi lice, a naličje ne vidi, dok stanje “zatvorena” vidi naličje i ne vidi lice. Dugme na karti svojom “vidljivošću” (dugme je providno) dozvoljava ili ne korisničku interakciju.

Karte su u potpunosti vektorski realizovane, tako da se, na primer, lice karte se, pri prvom zahtevu za prikaz lica, inicijalizuje preko vrednosti simbola i veličine karte postavljanjem odgovarajućih simbola na predefinisane pozicije za odgovarajuću veličinu.

3.1.2     Kolone

Kolone zauzimaju centralnu površinu aplikacije. Ima ih sedam i mogu sadržavati karte. Karte u koloni mogu biti otvorene ili zatvorene.

Prilikom deljenja se postavlja određeni broj zatvorenih karata (čiji broj tačno odgovara rednom broju kolone) i na vrh jedna otvorena karta. Tokom igre se karte se prebacuju i sa kolona i na kolone, a zatvorene karte se otvaraju.

3.1.3     Dek

Dek je “ostatak” karata iz špila koji pri deljenju nije stao na kolone. Nalazi u se u gornjem levom uglu. Podeljen je na deo u kome se nalaze zatvorene karte i drugi s otvorenim kartama. Pri deljenju se preostale karte smeštaju u zatvoreni deo. Karta na vrhu zatvorenog dela reaguje na klik prebacivanjem (okretanjem) određenog broja karata u otvoreni deo, a karta na vrhu otvorenog dela može se prebacivati na kolone ili stekove.

3.1.4     Stekovi

Cilj igre je prebaciti sve karte na stekove. Postoji četiri steka, a sve karte u nekom steku moraju biti istog znaka i ređaju se od najmanje ka najvećoj. Stekovi se nalaze gore, desno.

3.2          Interakcija

Korisnik sa kartama može da čini sledeće, u zavisnosti od toga gde se karta nalazi:

3.2.1     Prebacivanje grupe karata sa kolone na drugu kolonu

Ako je ciljna kolona prazna, moguće je prebaciti grupu otvorenih karata predvođenu kraljem (K).

Ako ciljna kolona nije prazna i ako je karta na vrhu kolone otvorena, može se prebaciti grupa karata kod koje je boja vodeće karte različita od boje ciljne karte i veličina vodeće karte prethodnik ciljne.

3.2.2     Prebacivanje karte sa kolone na stek

Ako je karta kec (A) može se prebaciti na prazan stek.

Karta se može prebaciti na stek ako su karte na steku istog znaka kao i karta i ako je karta na vrhu steka po veličini prethodnik karte koja se prebacuje.

3.2.3     Okretanje karte u koloni

Ukoliko prilikom prebacivanja karata sa kolone na vrhu kolone ostane zatvorena karta, njoj postaje vidljivo dugme i klikom na kartu se karta otvara.

3.2.4     Okretanje karata u deku

Klikom na kartu na vrhu zatvorenog dela deka prebacuju se karte na otvoreni deo i tamo otvaraju. Okreću se po tri karte, ukoliko na zatvorenom delu deka ima dovoljan broj karata, inače koliko može.

3.2.5     Okretanje deka

Kada su sve karte deka u otvorenom delu, klik na zatvoreni deo prebacuje sve karte na zatvoreni deo i pri tom ih zatvara.

3.2.6     Prebacivanje karte sa deka na kolonu ili stek

Karta na vrhu otvorenog dela deka može se prebaciti na kolonu ili stek pod istim uslovima kao i pri prebacivanju karata sa kolona.

3.2.7     Prebacivanje karte sa steka na kolonu

Karta se sa steka može prebaciti na kolonu ako zadovoljava uslov prebacivanja na kolonu.

3.3          Kreiranje karata

Objekat movieClip može sadržavati druge objekte movieClip. Svaki od objekata koje sadrži jedinstveno se identifikuje svojim imenom i dubinom. Jedan od metoda za dodavanje novog objekta je attachMovie. Ovaj metod zahteva tri parametra. Prvi parametar jeste naziv objekta iz biblioteke koji se želi instancirati. Sam naziv je izvozno ime bibliotečkog elementa koji je proglašen kao izvozni, što omogućava instanciranje ovim metodom. Drugi parametar metoda je jedinstveni naziv (u odgovarajućoj lokalnosti) elementa koji se kreira. Korišćenje postojećeg imena za posledicu proizvodi zamenu objekta. Treći parametar jeste dubina. To je vrednost veća ili jednaka nuli. Na određenoj dubini može se nalaziti najviše jedan movieClip objekat. Dodela zauzete dubine novom objektu briše postojeći objekat na istoj dubini. Broj dubine je bitan zbog vizuelizacije, jer se “dublji” objekti (manji broj) nalaze ispod...

Već je napomenuto da se karte sastoje iz tri dela čija vidljivost prikazuje stanje karte. Karta je grafički predstavljena objektom tipa movieClip i ona sadrži tri objekta istog tipa koji predstavljaju lice i pozadinu karte, i dugme. Karti su dodeljeni metodi za prikazivanje i sakrivanje ovih elemenata. Inicijalno se metodama za prikazivanje dodeljuju funkcije za kreiranje samih elemenata i metodama za sakrivanje prazna funkcija, dok se nakon prvog poziva metoda za prikazivanje, nakon inicijacije elementa karte, metodama se pridružuju funkcije za prikazivanje i sakrivanje elementa, respektivno. Na primeru pozadine to izgleda ovako:

3.3.1     Kreiranje pozadine karte

function showBack () {this.myMovie.myBack.show ();}

function hideBack () {this.myMovie.myBack.hide ();}

function initBack () {

      this.myMovie.attachMovie (_root.back, "myBack", _root.backLevel);

      this.hideBack = _root.hideBack;

      this.showBack = _root.showBack;

}

Ključna reč this referencira kartu kojoj su pridruženi metodi, pri pozivu metoda. Pri inicijaciji same karte doljejuje joj se prazan movieClip nazvan myMovie i postavlja metod showBack = _root.initBack. _root je korenski objekat, movieClip u kom se nalazi kompletan kod ovog primera (to ne mora tako da se realizuje). Pri prvom pozivu showBack izvršiće se initBack (), odnosno biće dodat movieClip objekat u myMovie pod nazivom myBack na dubinu backLevel (svaki deo karte ima svoju dubinu), a metodama se dodeljuju nove funkcije.

3.3.2     Dugme

Sličnu inicijaciju ima i dugme. Dugemetu se dodeljuje osobina myCard koja referencira na kartu. myButton je tipa movieClip, a sadrži providno dugme koje reaguje na akcije miša. Ovo iz razloga da se omogući uklanjanje dugmeta po potrebi. Dugme sadrži sledeće akcije:

on (press) {myCard.onPress ();}

on (release, releaseOutside) {myCard.onRelease ();}

Referencira na metode svoje karte. Ova realizacija predstavlja hendlere. Dodelom odgovarajućih funkcija ovim metodama karte obezbeđuje se odgovarajuće ponašanje karte u posmatranom stanju.

3.3.3     Kreiranje lica karte

Karte su realizovane u potpunosti kao vektorski objekti. Da bi se izbeglo kreiranje 52 različita vektorska crteža lica karata, korišćeno je kreiranje na osnovu osobina karte pomoću nekoliko primitiva. Kartu određuje znak i veličina. U gornjem levom i donjem desnom uglu karte nalaze se mali simbol znaka i oznaka veličine karte, dole su obrnuti. U centralnom delu je raspoređen potreban broj simbola znaka, zavisno od veličine. Neke karte imaju slike, ali je to ovom prilikom zanemareno i ponuđeno alternativno rešenje.

Potrebni primitivi su simbol znaka i tekstualno polje boje koja odgovara znaku. Instancira se simbol znaka, umanjuje i postavlja na predefinisanu poziciju u gornjem levom uglu karte. Instancira se simbol tekstualnog polja, postavlja na predefinisano mesto gore levo, dodeljuje vrednost veličine karte. Instancira simbol znaka, umanjuje, okreće za 180 stepeni, postavlja dole desno. Instancira simbol teksta, okreće, postavlja dole desno, dodeljuje vrednost. Ako veličina karte ne odgovara slici, iz predefinisanog niza čitaju se pozicije i rotacije instanci simbola znaka koji zauzimaju centralni deo karte. Slike instanciraju simbol teksta, uvećavaju i uvećavaju, postavljaju ga više centra karte i dodeljuju mu vrednost veličine karte, i instanciraju simbol znaka, uvećavaju i postavljaju niže centra karte. Asovi instanciraju simbol znaka, uvećavaju i postavljaju u centar.

3.4          Deljenje karata

Kolone, dek i stekovi su objekti koji vode računa o kartama čiji su domaćini. Određuju poziciju, dubinu i stanje karata, čuvaju ih u povezanim listama i vode računa o posebnim slučajevima korišćenja. Deljenje:

cards.scramble ();

var newCards = cards.slice (0);

for (var i = 0; i < numberOfColumns; i++) {

      columns [i].dealToMe (newCards.pop (), true);

      for (var j = i + 1; j < numberOfColumns; j++) {

            columns [j].dealToMe (newCards.pop (), false);

      }

}

while (newCards.length > 1) {

      deck.dealToMe (newCards.shift (), false);

}

deck.dealToMe (newCards.shift (), true);

Karte se mešaju (metod scramble) i kopiraju (reference) u privremeni niz newCards koji se potom koristi za dodelu karata kolonama i deku. Drugi argument metoda dealToMe kod kolona predstavlja da li se karta postavlja licem (true) ili naličjem (false), dok kod deka vrednost true predstavlja kartu sa vidljivim dugmetom. Deli se otvorena karta na prvu kolonu, pa zatvorene na ostale, dalje otvorena na sledeću kolonu i zatvorene na ostale i tako redom dok se na poslednju kolonu ne postavi otvorena karta. Ove karte uzimaju se “odozgo” metodom pop, a preostale se redom spuštaju na dek, “odozdo” metodom shift.

3.5          Prebacivanje karata

Ceo film u Flashu posmatra se takođe i kao movieClip objekat, tako da je u primeru pasijansa u svakom trenutku potrebno voditi računa o dubinama na kojima se nalaze pojedine karte kako bi vizuelizacija bila zadovoljavajuća. Kako elementi scene, dek, kolone i stekovi, tokom igre “razmenjuju” karte, njihovo kreiranje kao grafičkih elemenata zahtevalo bi brisanje, s jedne strane, i instanciranje, s druge, karata pri svakom prebacivanju s jednog elementa na drugi. Stoga ovi elementi nisu realizovani kao movieClip objekti, već samo objekti koji pomažu kartama i igraču da se igra igra. Zato se karte nalaze u korenskom movieClip objektu (_root), a svakom elementu je dodeljen dopustivi opseg dubina vodeći računa o maksimalnom broju karata koje element može da primi, i element vodi računa o dubini svojih karata i njihovoj poziciji.

Sada je jasno da karta pri promeni svog kontejnera, menja i svoju dubinu. Tom prilikom koristi se metod swapDepths, koji za parametar uzima novu dubinu objekta ili ciljni objekat za zamenu dubine.

3.5.1     Početak prevlačenja

Metod startDrag omogućava objektu movieClip kretanje po sceni indukovano promenom pozicije pokazivača miša. Kažemo da se objekat “vuče” (drag). Ono što je bitno je da se u jednom trenutku može vući samo jedan movieClip objekat. U primeru pasijansa dozvoljeno je sa kolone vući više karata. Da bi to bilo izvodivo, potrebno je staviti sve karte koje se žele vući u neki movieClip objektat koji se potom vuče i cela stvar funkcioniše. Ovaj objekat mora biti postavljen na dubinu veću od dubine na kojima se mogu nalaziti pojedine karte kako bi grupa karata koja se vuče vizuelno bila iznad svih elemenata scene. Objekat movieClip ne može da menja svog roditelja tako da je rešenje u kreiranju kopije lica karata u objektu koji se vuče i ukidanju vidljivosti originalnih karata dok traje prevlačenje. Kako se jedna karta može više puta premeštati u toku partije, u objektu koji se vuče prave se trajne kopije karata i regulacijom vidljivosti kopija određuje se koje karte se vuku a koje ne. Takođe, taj objekat vodi računa o poziciji kopija i njihovoj dubini zbog adekvatnog prikaza.

3.5.2     Kraj prevlačenja

Stanje prevlačenja objekata prekida se pozivom metoda stopDrag.

3.5.3     Odluka o prebacivanju

Rezultat prevlačenja je da karta ili grupa karata menja svoj element, odnosno poziciju i dubinu, ili vraćanje na prethodno stanje. Ova odluka donosi se kroz proveru metodom hitTest. Pri početku prevlačenja uočavaju se vrednosti vodeće karte koja se prevlači, boja, znak i veličina, i uočavaju se kolone i stekovi koji zadovoljavaju uslov za primanje vučene karte ili grupe karata. Na kraju prevlačenja se poziva hitTest, sa parametrom karte na vrhu uočenog elementa scene. Metod vraća true ako se objekti preklapaju, inače vraća false. Znači, ako se pri prolasku kroz niz uočenih objekata hitTest vrati true kod nekog elementa, na taj element se prebacuje karta ili grupa karata, a ako hitTest svuda vraća false, jednostavno se karte ponovo postavljaju kao vidljive i nikakva promena se ne dešava u odnosu na situaciju pre prevlačenja.

3.6          Undo i Redo mehanizam

Jedna prednost programa iz ovog primera u odnosu na poznatiju verziju za Windows jeste mogućnost za neograničeni Undo i Redo. Ovo omogućava igraču da slobodnije greši i ispita više načina na putu rešenja igre.

Suština rešenja je u korišćenju nizova čiji elementi prate akcije promene stanja igre.

U okviru objekta options sadrži nizove undoArray i redoArray. Na početku svake partije ovi nizovi se prazne i onemogućava se pristup grafičkim elementima (dugmad) za iniciranje Undo/Redo akcija.

Kada se desi događaj koji menja stanje sistema (menja stanje bar jedne karte), to se beleži u ovim nizovima za potrebu vraćanja na prethodno stanje. To radi addUndo:

function addUndo (myUndo, myRedo) {

      var undoAction = new Object ();

      undoAction.myUndo = myUndo;

      undoAction.myRedo = myRedo;

      this.showUndo ();

      this.undoArray.push (undoAction);

      this.redoArray.splice (0);

      this.hideRedo ();

}

Funkcija addUndo je metod objekta options, tako da se this odnosi na njega. Metodi showUndo, hideUndo, showRedo i hideRedo pale i gase dugmiće za undo i redo (ako je neki niz prazan, ne može se pozvati akcija). Nizovi sadržavaju objekte (undoAction) sa delovima za undo (myUndo) i redo (myRedo). Metod addUndo dodaje objekat na niz undoArray i prazni niz redoArray. Metod doAction pokazuje šta su myUndo i myRedo:

function doAction (myAction) {

      var action;

      for (i = myAction.length - 1; i >= 0; i--) {

            action = myAction [i];

            action [0].doThis = action [1];

            if (action.length == 2) {action [0].doThis ();}

            else {action [0].doThis (action [2]);}

      }

}

Parametar u doAction, myAction, je ili myUndo ili myRedo, a metod se poziva putem metoda doUndo ili doRedo, iniciranih klikom na odgovarajuće dugme. Parametar myAction je niz akcija koje definišu promenu u sistemu. Akcije se pamte kao nizovi, gde je prvi član referenca na objekat, drugi član referenca na funkciju objekta i treći opcioni član je referenca parametra funkcije. Metodu doThis objekta (action [0]) dodeljuje se funkcija (action [1]). Potom se poziva metod doThis, ako ima parametra (action.length != 2) sa parametrom (action [2]), inače bez parametra. Ovakav pristup je zadovoljavajuć jer primer nije zahtevao akcije koje sadrže više od jednog parametra, mada je moguće i uopštenje za proizvoljan broj parametara.

Ovakva realizacija zahteva tačno definisanje svih akcija koje se izvode pri jednoj promeni stanja kao i inverznih akcija.


 

vrh strane