Ohjelman kuvaus
Tekninen toteutus
Projektityöskentelyn kuvaus
Ohjelma lähdekoodeineen
Ohjelma lähdekoodeineen
zip-pakettina
Ohjelman
Javadoc-dokumentaatio
Ohjelman kantava idea on parvisimulaatio, joka simuloi lintuparven liikehdintää. Minua fiksummat ihmiset ovat tutkineet lintuparvien käyttäytymistä ja tehneet siitä sopivan yksinkertaisen mallin. Jokaisella linnulla on kolme sääntöä, joiden mukaan se liikkuu:
Jos parvea uhkaa petolintu, linnut luonnollisesti myös pakenevat sitä. Petolintua saa ohjata itse hiirellä.
Näitä sääntöjä sopivasti painottamalla ja säätämällä parven liikehdintä näyttää varsin aidolta. Käyttäjän vastuulle jääkin keskipisteeseen pyrkimisen ja samaan suuntaan lentämisen painotus. Väistäminen ja pakeneminen painotetaan tilanteen vakavuuden mukaan.
Parven koon voi antaa ohjelmalle komentoriviparametrinä, oletuksena on 60 lintua.
Ohjelman ikkunaa dominoi sinitaivas, jossa voi seurata lintujen kommelluksia. Oikeassa laidassa on ohjauspaneeli, josta lintujen ominaisuuksia voi säätää. Ohjauspaneeli jakautuu kahteen osaan, joista toisessa säädetään lintujen liikkumissääntöjen painotuksia ja toisessa lintujen ominaisuuksia, kuten kääntönopeutta.
Ohjelma on koodattu Javan versiolla J2SE 1.4.2, käyttäen ohjelmointityökaluna Eclipsen versiota 3.0.1.
Ohjelman luokkarakenne näyttää seuraavalta. Palikoita klikkailemalla pääsee niiden kuvauksiin. Hurjimmat voivat katsoa myös UML-härdellin.
Ohjelman sisältämät luokat kuvauksineen:
Parvi on nimensä mukaisesti yhtä lintuparvea kuvaava luokka. Parven luontimetodille annetaan parven lintujen lukumäärä, jolloin parvi generoi halutun määrän lintuja, joiden sijainti ja suunta ovat satunnaisia ja muut ominaisuudet oletusarvoissaan.
Linnut asustavat ArrayListissä, joka on käsittääkseni aika tehokas vaihtoehto. Tärkein tietorakenteelta vaadittava ominaisuus on nopea iterointi, jota vaaditaan parven lintujen läpikäyntiin. Yksittäistä lintua ei tarvitse hakea koskaan, eikä myöskään poistaa olioita joukosta.
Parvi huolehtii lintujen liikuttamisesta, eli kutsuu vuorotellen kaikkien lintujen liiku-metodia. Jos käyttäjä on säätänyt lintujen ominaisuuksia, nämä muutokset välitetään linnuille samalla iterointikierroksella.
Lintujen piirto tapahtuu myös parven toimesta. Tämän helpottamiseksi Parvi periytyy JPanel-luokasta. Piirtometodi iteroi lintulistaa, kysyy linnun sijainnin ja suunnan, laskee piirrettävien viivojen koordinaatit ja piirtää ne. Linnut esitetään selkeyden vuoksi kolmioina.
Lentava on abstrakti luokka, joka kuvaa geneeristä lentävää otusta. Ominaisuuksia ovat kaikki Linnun ja Petolinnun yhteiset ominaisuudet, muun muassa paikka, suunta, parvi, nopeus ja kääntönopeus. Varsinaisten liikkumissääntöjen määrittely jätetään alaluokille. Lentavan alaluokkien täytyy siis toteuttaa toimi() -metodi, joka käskee otusta liikkumaan yhden askeleen verran liikkumissääntöjensä mukaan. Varsinaisen paikasta toiseen liikkumisen koodi on Lentavassa.
Linnun periytyy Lentavasta. Perittyjen ominaisuuksien lisäksi sillä on kasan muita ominaisuuksia määrittelevä Lintuspeksit-olio. Nämä ominaisuudet annetaan linnulle luontimetodin parametreina.
Kun linnun toimi-metodia kutsutaan, lintu laskee uuden liikkumissuuntansa liikkumissääntöjensä mukaan ja siirtyy uuteen sijaintiinsa. Liikkumissäännöt ovat metodeita, jotka palauttavat kukin oman Vektori-olionsa. Lopullinen liike määräytyy, kun nämä vektorit lasketaan yhteen määriteltyjen painotusten mukaan.
Tiedon hankkiminen parvesta on keskitetty yhteen metodiin, jottei parvea tarvitse iteroida jokaisen säännön osalta erikseen. Iteroinnin tulokset välitetään säännöt laskeville metodeille. Lennä samaan suuntan -sääntö lasketaan kuitenkin suoraan tiedohankinnan yhteydessä yksinkertaisuutensa vuoksi.
Väistämissääntö toimii siten, että lintu tarkastaa onko yksikään parven linnuista määritellyn rajan sisäpuolella. Jos ei, sääntö ei vaikuta. Jos taas on, palautetaan toisesta linnusta poispäin osoittava vektori, jonka painotus riippuu siitä, kuinka lähellä toinen lintu on. Pyri parven keskelle -metodi palauttaa parven keskipisteeseen osoittavan vektorin. Lennä samaan suuntaan -vektori kertoo lähistön lintujen keskimääräisen suunnan ja nopeuden. Jos petolintu on lähistöllä, mukaan tulee myös petolinnusta poispäin osoittava vektori, jonka paino riippuu petolinnun etäisyydestä.
Koska lintu ei voi liikkua useaan suuntaan vaikka haluaisikin, täytyy vektoreista laskea jonkinlainen kompromissi. Pelkkä keskiarvo olisi yksinkertaistanut lopputulosta liikaa painotettunakin, joten piti kehitellä parempi systeemi. Päädyin hieman muunnettuun versioon painotetusta keskiarvosta, jossa painotettavilla asioilla on prioriteetit ja ns. “painoa” on rajoitetusti, joten tärkeimmät asiat, kuten petolinnulta pakeneminen ajavat tiukassa paikassa kokonaan vähemmän tärkeiden asioiden ohi.
Luokka, joka kokoaa yhteen linnun säädettävissä olevat ominaisuudet. On tietoinen siitä, onko asetuksia muutettu sen jälkeen, kun ne on viimeksi kerrottu linnuille.
Lentavan alaluokka. Liikkuu yksinkertaisesti kursoria kohti. Toimii Parven hiirikuuntelijana ollessaan olemassa.
Paaohjelma on nimensä ennustamalla tavalla pääohjelmaluokka. Se ei sisällä juurikaan logiikkaa, vaan sen tehtävä on koota lintuparvi ja sen säätimet samaan ikkunaan. Paaohjelma periytyy JFramesta.
Paneeli, joka sisältää säätimet parven ominaisuuksien muuttelemiseen. Ainoa logiikanpoikanen on säätimien arvojen muuttaminen linnuille sopivaan asteikkoon. Sisältää myös napin, josta petolintu singahtaa areenalle ja sieltä pois.
Vektorilla on tunnettuun tapaan suunta ja pituus. Niiden lisäksi luokka osaa palauttaa vaaka- ja pystykomponenttinsa ja tehdä joitakin yksinkertaisia vektorilaskutoimituksia, kuten kierto ja skaalaus.
Aloitin projektin koodaamisen vasta melko myöhään, joulukuun alkupäivinä. Olin kuitenkin käyttänyt suunnittelemiseen suuren määrän aivojen luppoaikaa, joten alku sujui hyvin nopeasti. Parin illan koodaamisen jälkeen ohjelman perusta oli kasassa, linnut näkyivät ruudulla ja liikkuivat eteenpäin. Tästä harppauksesta tyrmistyneenä pidin pienen tauon koodaamisessa, ja arvelin vaikeimman olevan takanapäin. Kuinka väärässä olinkaan! Liikkumissääntöjen ohjelmointi ja hienosäätö osoittautui odotettua haastavammaksi, ja niitä tahkottiin vielä tammikuun puolellakin.
Odottamaton hankaluus aiheutui rajoittaessa lintujen kääntymisnopeutta. Kun mennään suuntaan a ja pyritään seuraavaksi suuntaan b, miten voidaan määrittää, lähdetäänkö kääntymään myötä- vai vastapäivään? Olen aivan varma, että on olemassa äärimmäisen elegantti matemaattinen konsti tämän selvittämiseen, mutta itse en sitä ilmestystä kokenut. Itse ongelman sain kyllä ratkaistua, mutta tyylikkyydestä tuskin voidaan puhua.
Ajankäyttösuunnitelmassa ei siis yllättäen pysytty, mutta en kuitenkaan pidä toteutunutta ajankäyttöjakaumaani mitenkään epäonnistuneena. Kiire ei missään vaiheessa ollut häiritsevää, enkä tainnut ylittää tuntimäärääkään pahasti.
Ohjelman toteutukseen olen pääosin tyytyväinen. Luokkarakenne ja rakenne muutenkin on mielestäni onnistunut ja selkeä. Nykyinen rakenne tekee kuitenkin toisen parven lisäämisen hankalaksi, koska piirtämiskoodi on niin tiukasti naitettu parviolioon. Liikkumissäännöissä olisi varmasti hienosäädettävää, muun muassa törmäysten täydellinen välttäminen, mutta en katsonut sen olevan siihen tarvittavan ajan arvoista.