Tietokoneavusteinen opetus, 2017 Harjoitus 2: Raahaus, satunnaisuus ja taulukot (14.3.2017) Tietokoneavusteinen opetus -kurssilla opetetaan Adobe Flash CS6:n käyttämistä ja HTML5-tekniikoita neljänä kertana: 10.3., 14.3., 17.3. ja 24.3. Harjoituskerroilla tutustutaan työvälineiden käyttöön harjoitusten avulla. - Jokaisena harjoituspäivänä järjestetään kaksi harjoitusryhmää, joissa käsitellään sama sisältö. - Harjoitukset järjestetään klo 10:15-12:00 ja 12:15-14:00 mikroluokassa B1084. - Harjoitusryhmiin saa saapua vapaasti ei ennakkoilmoittautumista. - Harjoituskerran tehtävät julkaistaan etukäteen osoitteessa http://people.uta.fi/~joel.luukka/tao/ - Tehtävät käydään läpi yhteisesti harjoituksissa ratkaisuja ei tarvitse tehdä ennen harjoituksia. Tapahtumakäsittelijät ActionScript-ohjelmointi perustuu järjestelmässä syntyvien tapahtumien (event) käsittelyyn. Tapahtumia on kahdenlaisia: käyttäjän tuottamia (user event) ja järjestelmän luomia (system event). Käytännössä pääosa ActionScript-ohjelmakoodista keskittyy tietyn tapahtuman käsittelyyn. CS6:ssa tapahtumia käsitellään siten, että ohjelmoija määrittelee tapahtumankäsittelyfunktion ja liittää sen ko. tapahtumia aikaansaavan komponentin tapahtumakuuntelijoiden joukkoon metodilla addeventlistener: 1 instanssinimi.addeventlistener(tapahtuma,tapahtumakasittelija); Yllä esitetyn skriptin parametri tapahtuma on merkkijono. Useimmat tapahtumatyypit, kuten hiiritapahtuma (MouseEvent) määrittelevät vakioarvot tapahtumien merkkijonoille. Tapahtumakuuntelijaa lisättäessä voidaan käyttää joko vakioarvoa tai merkkijonoa. Seuraavan skriptin sisältämät esimerkit ovat siten toiminnaltaan identtiset: 1 // Tapahtumakäsittelijän lisäys hiiren klikkaukseen 2 instanssinimi.addeventlistener("click",tapahtumakasittelija); 3 4 // Vakioarvo MouseEvent.CLICK == "click" 5 instanssinimi.addeventlistener(mouseevent.click,tapahtumakasittelija); Tapahtumankäsittelijä on tavallinen ActionScript-funktio, joka saa parametrinaan funktiokutsun laukaisseen tapahtuman: 1 function tapahtumakasittelija(tapahtuma) { 2 // Oma koodi tänne 3 } Näissä harjoituksissa keskitytään käyttäjän tuottamien tapahtumien, kuten hiiritapahtumien, käsittelyyn. Hiiritapahtumia ja niitä vastaavia merkkijonoja ovat mm.: MouseEvent-luokan vakio CLICK DOUBLE_CLICK Vakiota vastaava merkkijono "click" "doubleclick" " 1 / " 6
MouseEvent-luokan vakio MOUSE_UP MOUSE_DOWN MOUSE_OVER MOUSE_OUT MOUSE_MOVE Vakiota vastaava merkkijono "mouseup" "mousedown" "mouseover" "mouseout" "mousemove" Raahaus Toteutetaan ohjelma, jossa palloja tulee raahata maalialueelle. Raahauksen päättyessä maalialueelle pallo saa jäädä raahauksen päättymispisteeseen ja annetaan onnistumisesta palaute. Muussa tapauksessa pallo palautetaan takaisin lähtöpisteeseen. 1. Tee piirtotyökalulla näyttämölle yksi pallo ja yksi laatikko. 2. Muuta nämä MovieClip-olioiksi: valitse koko objekti (täyteväri ja ääriviivat) näyttämöllä ja valitse hiiren oikealla painikkeella avautuvasta valikosta "Convert to Symbol...". Nimeä objektit. 3. Anna laatikolle instanssinimi "maali". 4. Luo lisää palloja raahaamalla kirjastosta. Anna myös palloille instanssinimet. 5. Lisää näyttämölle dynaaminen tekstikenttä ja anna sille instanssinimeksi esim. "palaute". 6. Kirjoita ohjelman alustus- ja tapahtumankäsittelijäskriptit: " 2 / " 6
1 // Alusta pelikenttä pysäyttämällä aikajana, määrittämällä 2 // apumuuttujat ja kirjoittamalla ohjeteksti. 3 stop(); 4 var koord_x = 0; 5 var koord_y = 0; 6 palaute.text = "Raahaa pallot maaliin"; 7 8 // Määritellään tapahtumankäsittelijät raahauksen 9 // alkamiselle ja päättymiselle. 10 function drag_on(event) { 11 12 // Tyhjennetään palautekenttä 13 palaute.text = ""; 14 15 // Tallennetaan raahauksen alkamispiste apumuuttujiin 16 koord_x = event.target.x; 17 koord_y = event.target.y; 18 19 // Aloita raahaus 20 event.target.startdrag(); 21 }; 22 23 function drag_off(event) { 24 25 // Lopetetaan raahaus 26 event.target.stopdrag(); 27 28 // Tutkitaan pudotettiinko pallo jonkin päälle ja jos 29 // pudotettiin, tutkitaan onko sen instanssinimi "maali" 30 if(event.target.droptarget = null && 31 event.target.droptarget.parent.name == "maali"){ 32 33 // Raahaus onnistui 34 palaute.text = "Raahaus onnistui"; 35 } 36 else{ 37 38 // Pallo pudotettiin nuualle kuin maalin päälle. 39 // Palautetaan pallo lähtöpisteeseen. 40 event.target.x = koord_x; 41 event.target.y = koord_y; 42 palaute.text = "Raahaus ei onnistunut..."; 43 } 44 }; Tapahtuman kohde (event.target) on viite siihen olioon, joka on tapahtuman tuottanut. Tämän viitteen avulla voidaan siis hakea pallon koordinaatteja (event.target.x ja event.target.y) ja se olio, jonka päälle raahattava olio "pudotetaan" (event.target.droptarget). 7. Lisää tapahtumakuuntelijat jokaiselle pallolle: 1 pallox.addeventlistener(mouseevent.mouse_down,drag_on); 2 pallox.addeventlistener(mouseevent.mouse_up,drag_off); 8. Kokeile ohjelman toimintaa. + Jos pallo menee raahatessa maalin taakse, voit siirtää maalin taka-alalle Modify-valikon Arrange-alivalikon kautta. " 3 / " 6
Satunnaisuus ja taulukot Tietokoneavusteinen opetus, 2017 Satunnaisuuden ohjelmointi perustuu Math-luokan random-funktioon, joka palauttaa satunnaisen liukuluvun puoliavoimelta väliltä [0,1[. Random-funktion palauttama luku on harvoin käytettävissä sellaisenaan, joten lukua täytyy muokata käyttökohteen vaatimusten mukaiseksi. Liukuluvun muokkaamiseen riittää usein melko yksinkertaiset aritmeettiset operaatiot: 1 // Alustetaan raja-arvot 2 var min = 5; 3 var max = 30; 4 5 // Liukuluku väliltä [0,1[ 6 var a = Math.random(); // a = 0.1734... 7 8 // Liukuluku väliltä [0,max[ 9 var b = Math.random() * max; // b = 23.5547... 10 11 // Kokonaisluku väliltä [0,max] 12 var c = Math.floor( Math.random() * (max + 1) ); // c = 3 13 14 // Kokonaisluku väliltä [min,max] 15 var d = Math.floor( Math.random() * (max + 1 - min) ) + min; // d = 14 Taulukko (Array) on tietorakenne, johon voidaan tallentaa useita muuttujia samanaikaisesti. Niiden avulla voidaan käsitellä muuttujia ilman, että jokaisella muuttujalla on erikseen määriteltyä muuttujaviitettä. ActionScript-taulukot ovat dynaamisia, eli niiden kokoa voidaan muuttaa taulukon luomisen jälkeen. Taulukoille on määritetty useita funktioita, joiden avulla taulukkoja voidaan manipuloida. Alla on esitetty tärkeimpiä taulukon käsittelytapoja ja funktioita: 1 // Luodaan taulukko 2 var arr1:array = new Array(); 3 var arr2:array = []; 4 5 // Lisätään alkio taulukkoon 6 arr1[0] = "A"; // Lisätään alkio "A" taulukon 1. paikalle 7 arr1.push("b","c"); // Lisätään alkiot "B" ja "C" taulukon loppuun 8 9 // Luetaan alkion arvo 2. paikalta 10 var arvo = arr1[1]; 11 12 // Haetaan taulukon alkioiden määrä 13 var taulukon_koko = arr1.length; 14 15 // Poistetaan 1 alkio paikalta 0 16 var poistettu1 = arr1.splice(0,1); 17 18 // Poistetaan taulukon viimeinen alkio 19 var poistettu2 = arr1.pop(); Lisätään raahaustehtävään toiminto, joka arpoo onnittelutekstin ennalta määrätyistä teksteistä aina kun pallo pudotetaan maaliin. 9. Lisää skriptiin funktio, joka arpoo satunnaisen kokonaisluvun väliltä [0,max]. 1 function arvokokonaisluku(max) { 2 var satunnaisluku = Math.random() * (max + 1); 3 var kokonaisluku = Math.floor(satunnaisluku); 4 return kokonaisluku; 5 }; " 4 / " 6
10. Lisää skriptin alkuun taulukko, joka sisältää joitain onnittelutekstejä: 1 var onnittelutekstit:array = ["Hyvä","Onnistui","Jee"]; 11. Muuta drag_off-tapahtumakäsittelijäfunktiota siten, että onnistuneen raahauksen yhteydessä arvotaan palautekentän tekstiksi jokin taulukossa olevista teksteistä. 33 // Raahaus onnistui, Arvotaan onnitteluteksti. 34 var tekstin_paikka = arvokokonaisluku(onnittelutekstit.length - 1); 34 palaute.text = onnittelutekstit[tekstin_paikka]; 12. Kokeile ohjelman toimintaa. Lisätehtäviä Toteutetaan usean maalin sisältävä raahaustehtävä, missä raahauksen päätteeksi täytyy päätellä mihin maaliin raahattu olio raahattiin ja oliko maali sopiva juuri tälle oliolle. 13. Aloita uudesta kohtauksesta ja lisää näyttämölle raahattavia kuvioita, kaksi eri maalia ja dynaaminen palautetekstikenttä kohtien 1-5 mukaisesti. 14. Lisää alustusskripteihin taulukot, jotka kuvaavat maalien "hyväksymiä" raahattavia olioita. Taulukko sisältää niiden olioiden instanssinimet, jotka kuuluvat ko. maaliin. 1 var maali1 = ["pallo1","pallo2","pallo3"]; 2 var maali2 = ["nelio1","nelio2","nelio3"]; 15. Lisää tapahtumakäsittelijäfunktiot. Muokkaa drag_off-funktiota siten, että se tunnistaa kolme eri lopputulosta raahaamiselle ja antaa kustakin sopivan palautteen: - Raahattava olio pudotetaan oikeaan maaliin, jolloin raahattavan olion nimi löytyy ko. maalin listalta. - Raahattava olio pudotetaan väärään maaliin. - Raahattava olio putosi molempien maalien ulkopuolelle. Tietyn arvon kuulumista taulukkoon voi testata Array-luokan indexof-funktiolla, joka palauttaa alkion paikan taulukossa tai -1, jos arvoa ei löydy. 1 if(maali1.indexof(event.target.name)>-1){ 2 // Arvo löytyi listalta 3 } 4 else { 5 // Arvoa ei ollut listalla 6 } 16. Lisää tapahtumakuuntelijat raahattaviin olioihin ja testaa ohjelman toimintaa. Lisätään raahaustehtävään pisteenlaskutoiminto, joka myöntää käyttäjälle pisteitä onnistuneista raahauksista. Voit lisätä toiminnon joko ensimmäiseen raahaustehtävään tai yllä olevan lisätehtävän mukaiseen raahaustehtävään. " 5 / " 6
17. Lisää näyttämölle dynaaminen tekstikenttä, joka esittää käyttäjän pisteet. Anna sille instanssinimeksi esim. "pisteet". 18. aseta pisteet-kentän tekstisisällöksi 0 kentän alustuksen yhteydessä: 1 pisteet.text = "0"; 19. Lisää drag_off-funktioon pisteitä lisäävä skripti if-lohkoon, jossa on testattu että käyttäjä on onnistunut raahauksessaan: 1 // Raahaus onnistui 2 pisteet.text = String( Number(pisteet.text) + 1 ); Yllä esitetyssä skriptissä haetaan pisteet-tekstikentän tekstiarvo ja muutetaan se numeroarvoksi. Numeroarvoa kasvatetaan sopivasti, minkä jälkeen uusi pistemäärä muutetaan takaisin merkkijonoksi ja sijoitetaan pisteet-tekstikentän tekstisisällöksi. 20. Testaa ohjelman toimintaa. + Ohjelmaa voi huijata antamaan loputtomasti pisteitä siirtämällä olion uudelleen omaan maaliinsa. Kuinka tämä voidaan estää? Tällaiset huijausyritykset saadaan estettyä esimerkiksi pitämällä kirjaa niistä raahattavista olioista, joista on jo myönnetty pisteitä. Tee uusi taulukko, johon kerätään pisteytettyjen olioiden instanssinimet, ja lisää pisteitä vain jos raahatun olion instanssinimeä ei olla lisätty listalle (ks. indexof kohdassa 15). Satunnaisuuden ohjelmoinnilla voidaan toteuttaa toimintoja, jotka toteutuvat vain tietyllä todennäköisyydellä. Esimerkiksi kolikonheiton lopputulos on kruuna (tai klaava), kun Math.random() < 0.5, nopanheiton lopputulos on täsmälleen 3, kun Math.random() < (1/6) ja 52 kortin pakasta saadaan ässä silloin kun Math.random() < (1 / 13). Toteutetaan yksinkertainen kolikonheittosimulaattori, joka kertoo nopanheiton lopputuloksen. 21. Lisää näyttämölle dynaaminen tekstikenttä, joka kertoo laskiko kolikko kruuna- vai klaavaasentoon, ja painike, jonka avulla kolikko voidaan heittää uudelleen. Anna näille molemmille instanssinimet. 22. Lisää skriptiin tapahtumakäsittelijäfunktio, joka asettaa tekstikentän tekstisisällöksi "Kruuna" todennäköisyydellä 0.5 ja muissa tapauksissa tekstisisällöksi asetetaan "Klaava". 23. Liitä tapahtumankäsittelijä painikkeeseen lisäämällä painikkeelle tapahtumakuuntelija. 24. Testaa ohjelman toimintaa. " 6 / " 6