Loppuraporttikirjoittaja: Zeerim Cheung 13.01.2007 |
||
|
Takaisin projektin pääsivulle | Jatka tiedostoihin AutobahnToteuttamani projekti on lähes samankaltainen kuin suunnittelinkin eikä se poikkea muutamaa yksityiskohtaa lukuunottamatta aihe-ehdotuksestani ja projektisuunnitelmastani. Pelin nimi on siis Autobahn ja sitä voisi jopa kutsua autopeliksi. Pelin tapahtumapaikkana on eräs saksalainen moottoritie, josta löytyy loputon suora. Pelaaja on saanut alleen upouuden italialaisen punaisen urheiluauton ja hän päättää lähteä testaamaan sitä yleiselle liikenteelle. Ainoa sopiva paikka löytyy Saksan moottoriteillä, koska muuten nopeusrajoitukset estäisivät urheiluauton todellisten kykyjen näyttämistä. Pelaaja päättää nöyryyttää hitaampia saksalaisia autoja ohittamalla niitä mahdollisimman monta, mutta kuten tiedämme tällainen kaahailu päättyy loppujen lopuksi aina kolariin. Pelin käynnistyttyä se alkaa aloitusruudusta, jossa pyydetään pelaajalta nimi sekä aloitusnopeus, joka voi olla väliltä 1-10. Painamalla "Aloita peli"-painiketta pääsee varsinaiseen pelitilaan.
Varsinaisessa peliruudussa näkyy alussa suora tie, jossa on viisi kaistaa ja jonka vasemmalla reunalla keskimmäisellä kaistalla on punainen urheiluauto, joka on tietenkin pelaajan auto.
Peli lähtee liikkeelle painamalla välilyöntiä, jolloin pelaajan auto lähtee liikkeelle ja eteen alkaa tulla erinäisiä objekteja. Pelaaja voi ohjata omaa autoaan näppäimistön ylä- ja alanuolipainikkeilla, joista auto siirtyy ylemmälle ja alemmalle kaistalle. Päällimmäisenä tarkoituksena on ohittaa mustat autot ja näin välttää kolari. Jokaisesta ohitetusta autosta tienaa yhden pisteen pelinopeudesta riippumatta. Viidentoista ohitetun auton jälkeen pelinopeus kasvaa yhdellä eli pelaajan auto kiihtyy hiukan, paitsi ensimmäinen nopeuden kasvu riippuu alkunopeudesta eli se tapahtuu silloin, kun autoja on ohitettu 15 kertaa aloitusnopeuden verran autoja. Nopeus ei kuitenkaan voi kasvaa loputtomiin, koska tälläkin urheiluautolla on huippunopeus, joka tulee vastaan, kun peli nopeus nousee kymmeneen. Koska pelitavoitteena on kerätä mahdollisimman paljon pisteitä ajon aikana, autojen ohittelun lisäksi on hyvä yrittää kerätä tielle ilmestyviä keltaisia palluroita, jotka esittävät bonuspiste-esineitä. Niitä keräämällä tienaa pistemäärän, joka on yhtäsuuri kuin sillä hetkellä vallitseva pelinopeus. Pelaaja voi myös varustaa autonsa über-puskurilla, mikä onnistuu poimimalla tielle silloin tällöin ilmestyviä punaisia kolmioita. Tällä varustuksella pelaaja voi törmätä yhteen mustaan autoon vahingoittumatta. Useamman puskurin kerääminen ei kuitenkaan tuota pelaajalle yhtään lisäarvoa, koska eihän autoon voi asentaa kerralla useampaa etupuskuria. Silloin, kun pelaajan auto on varustettu über-puskurilla, ilmestyy tätä kuvaava ikoni pelaajan nimen perään. Tiellä voi kaiken tämän lisäksi ilmestyä myös öljytahroja, jotka heittävät pelaajan joko ylemmälle tai alemmalle kaistalle. Niitä kannattaa vältellä, jos haluaa säilyttää kontrollin ajoneuvoonsa.
Peli päättyy, kun pelaajan auto kolaroi toiseen autoon eikä pelaajalla ole über-puskuria. Jos pelaaja on saanut kerättyä tarpeeksi pisteitä, hän pääsee Hall of Fame -listalle, joka näytetään pelin päätyttyä. Jos peli päättyy tasapisteisiin verrataan loppunopeutta, jolloin korkeimman loppunopeuden omaava peli rankataan paremmaksi. Jos tämäkin on sama, verrataan tuloksen teko ajankohtaa sekunnin tarkkuudella, jolloin aikaisemmin tehty tulos rankataan paremmaksi. Viimeiksi verrataan annettujen nimien aakkoksellista järjestystä, jossa järjestyksessä ensin tuleva nimi rankataan paremmaksi. Kun ruudussa näkyy Hall of Fame -ruutu, voi pelaaja päättää seuraavan tapahtuman valitsemalla jokin valikkorivissä olevista vaihtoehdoista. Hän voi aloittaa uuden pelin tai lopettaa ohjelman. Valikkorivissa on myös painikkeet, joita saa peliohjeen ja pelitiedot näkyviin. Nämä valikkorivin painikkeet ovat pelaajan käytössä ohjelman kaikissa osissa. Tekninen toteutusTämä peli on ohjelmoitu käyttäen Java-ohjelmointikieltä. Jotta peli toimisi, täytyy koneessa olla Java 1.5 tai uudempi versio (tarkista komentorivikomennolla "java -version"), koska pelissä on sellaisia ominaisuuksia, joita vanhemmat virtuaalikoneet eivät ymmärrä. Olen tehnyt varsinaisen ohjelmointityön kotona tietokoneella, jossa on JDK 1.5.0_10 ja Windows XP Home Edition SP2. Koodamiseen käytin NetBeans IDE 5.5, joka on Javan kehitystyökalu. Kaikki tiellä olevat objektit sekä nimen jälkeen tuleva über-puskuri-ikoni ovat piirretty Windows:in Paint-ohjelmalla, jolla on saatu hyvä retrofiilis peliin, jossa on vähän perinteistä 8bit Nintendo-tuntua. Tie on kuitenkin piirretty Graphics2D-luokan avulla. Pelissä käytetään vain yhtä säiettä. Testaukseen on käytetty ohjelmointikoneen lisäksi TKK:lla olevia koneita. Peli toimii moitteettomasti muun muassa TKK:n ATK-keskuksen Windows-koneilla, joissa on Windows XP Pro, Linux koneilla, joissa on ilmeisesti Linux Ubuntu sekä OLO-huoneenlla, jossa ohjelman demokin tapahtui. Ohjelma ei kuitenkaan toiminut sujuvasti TKK:n Tietotekniikkatalon Paniikki-luokassa, joissa oli ongelma koneiden tehon kanssa. Siellä javax.swing.Timer-luokkaa ei millään saanut toimimaan sujuvasti, joten peli toimi siellä nykivästi. En myöskään lisännyt lopulliseen ohjelmaversioon ääniefektejä, koska en voinut varmistaa ohjelman toimintakykyä äänikortittomissa koneissa. Kokeilin kylläkin jossakin vaiheessa erilaisia ääniefektejä pelini kanssa eikä täysin sopivia ääniefektejä oikein löytynyt. Ohjelma koostuu yhdeksästä .java-tiedostosta, joista kahdessa toteutetaan pelissä käytetty graafinenkäyttöliittymä ja loput liittyvät pelilogiikan ja tuloksien tallentamisen toteutukseen. Käyttöliittymän toteutukseen on käytetty monia Swing-komponentteja ja monia java.awt- ja java.awt.event-pakkauksiin kuuluvia luokkia. Projektisuunnitelmassa ajattelin vielä toteuttaa aloitus-, peli- ja tulosruudun eriluokkiin, mutta huomasin ohjelmoidessa, että aloitus- ja tulosruudun pystyi helposti toteuttamaan myös Autobahn-luokkaan, mikä hallinnoin grafiisenkäyttöliittymän kaikkia osia paitsi varsinaista pelattavaa osaa, joka kuuluu Tie-luokkaan. Tie-luokassa toteutetaan varsinaisessa pelissä olevan animoinnin ja siinä piirretään kaikki pelissä ilmestyvät esineet. Ensikisi ruutuun piirretään vihreitä suorakulmioita, jotka kuvaavat tienvarrella olevaa ruohikkoa, toiseksi ruudun poikki meneviä valkoisia suorakulmioita, jotka kuvaavat kaistaviivoja, ja kolmanneksi harmaita suorakulmioita, jotka ovat autokaistoja. Nyt ollaan piirretty tie, jossa on yhteinäisiä valkoisia kaistaviivoja. Sitten laitetaan tämän tien päälle harmaita suorakulmioita, jotka peittävät osan valkoisista kaistaviivoista. Kun halutaan saada tie liikkumaan, niin siirretään harmaat pylväät vaakatasossa. Tämän päälle laitetaan kaikki muut objektit liikkumaan tien päällä. Luokassa käytetään kaksi javax.swing.Timer:a, joista toisen päätehtävä on päivittää pelaajalle näkyvää kuvaa ja kutsua esineiden välisen kontaktin tarkastusta ja toisen tarkoitus on pyytää muiden esineiden kuin oman auton arpomista tielle sekä poistaa ohitetu esineet muistista. Tässä luokassa toteutetaan myös pelaajan auton ohjaus, jota saadaan aikaiseksi käyttämällä KeyAdapter-luokkaa, joka toteuttaa KeyListener-rajapinnan. Näin saadaan punaista autoa tottelemaan näppäimistöä. Pelaajan punaista autoa kuvaa OmaAuto-luokan ilmentymä, jolla on kaksi ominaisuutta, jotka ovat kaista, jossa se sijaitsee, sekä true- tai false-tila, joka kuvaa auton über-puskuritilaa. Kaikki muut tiellä esiintyvät objektit ovat Esine-luokan ilmentymiä. Tarkempi esineen tyyppi määrätään EsineTyyppi-enumeraation avulla. Esineillä on lähinnä vain tieto omasta tyypistään ja sijainnistaan, jotta Tie-luokka tietäisi, minkälaisen kuvan ja mihin kohtaan tietä pitää laittaa mitäkin. Kaikki esineet, paitsi mustat autot, liikkuvat samaa tahtia kuin tiekin, mutta mustat autot luodaan liikkumaan vähän hitaammin, jotta nekin näyttäisivät liikkuvan tien suhteen. Kaikki tiellä näkyvät Esine-luokan ilmentymät säilytetään Esineet-luokan ilmentymään, joka toimii saman tapaisesti kuin ArrayList-olio, mutta siinä suoraan sisällön ominaisuuksia. Pelimoottorina toimii Peli-luokka, joka arpoo esineitä tielle java.util.Random-luokan avulla, laskee pisteet ja ohitetut autot, määrää mitä tapahtuu pelaajan auton ollessa kontaktissa toisen esineen kanssa ja laittaa graafisenkäyttöliittymän-luokat lopettamaan peliä. Peli kertoo Autobahn- ja Tie-luokalle niiden tarvitsemat tiedot. Pelituloksien tallentamiseen käytetään käytännössä täysin samanlaista ratkaisua kuin kurssin kuudennessa harjoitustehtävässä. Tulos-luokka toteuttaa Comparable-rajapinnan ja sen ilmentymä kuvaa yhtä tehtyä pelitulosta. Tällainen olio luodaan jokaisen pelin jälkeen, jonka jälkeen tarkistetaan, onko se tarpeeksi hyvä tallennettavaksi. Jos pelitulos on riittävän hyvä, se tallennetaan Tulokset-luokan avulla tiedostoon, jonka nimi on tulokset.txt. Tulokset-luokka lukee tiedostosta parhaat tulokset ja hoitaa myös tuloksien käsittelyn ja kirjoittamisen uudelleen tiedostoon. Pelissä ei tarvittu erityisen monimutkaisia algoritmeja, mutta monet asiat vaativat paljon testausta, jotta siitä tulisi järkevä ja mukava pelata. Oli käytännössä kaksi vaihtoehtoa toteuttaa nopeuden kasvu joko kutsumalla tiheämmin repaint()-metodia tai siirtää useamman pikselin verran liikettä kuvaavia harmaita pylväitä. Lopulta päätin kutsua repaint-metodia aina yhtä usein eli 20 millisekunnin välein, jolloin ruutu päivittää 50Hz taajuudella, ettei grafiikan pyörittäminen olisi liian raskas koneelle. Nopeuden kasvu toteutin kasvattamalla jokaisen ruudun päivitykerralla liikkeen kuvaavien harmaiden pylväiden liikkuman pikselin määrää. Paljon testausta vaati myös se, kuinka usein uusia esineitä piti arvota ja millä todennäköisyydellä jokin esine arvotaan tielle. Esineitä arvotaan tiheämmin nopeuden kasvaessa lineaarisesti. Esineiden arpominen tapahtuu taas java.util.Random-luokalla jokainen kaista toisistaan riippumatta tietyillä todennäköisyyksillä, joita on testattu paljon. En ole poistanut mahdollisuutta, että tulisi mahdottomia tilanteita, koska mielestäni ne kuuluu asiaan ja useammasta tilanteesta pääsee pois über-puskurin avulla. Käsitekartta luokista löytyy tästä. ProjektityöskentelyJo aikaisessa vaiheessa minulle selkeni projektini aihe ja jopa eräät yksityiskohdat. Vaikka idea oli olemassa, toteutustavat olivat pitkään kuitenkin hakusessa, kun ei tarvittavat tekniikat olleet vielä halussa. Alusta alkaen suurimpana esteenä idean toteutuksessa pidin sitä, miten tiehen saisi liikkeentuntua. Uskoin projektini olevan muuten hyvinkin toteutuskelpoinen. Projektisuunnitelmaa tehdessä ei ollut vielä tietoa, miten pelituloksia saattoi tallentaa, mutta tiesin kuitenkin sen olevan viimeises Java-harjoituksen aiheena, joten liitin sen suunnitelmiini luottavaisin mielin. Lopuksi kävikin niin, että viimesen harjoituksen ideaa pystyi soveltamaan projektiini lähes täsmälleen samanlaisena. Kun aloitin varsinaisen työskentelyn noin neljä viikkoa ennen projektikoodin palautusta, päätin keskittyä ensiksi uusien menetelmien opiskeluun ja erityisesti miten saada tie aikaiseksi ja liikkumaan. Sain assareilta vinkin, että Graphics2D-luokkaan kannattaa tutstua syvällisesti. Kokeilin ensin laittaa tien kuvatiedostona ja liikuttaa sitä, mutta siitä ei tullut mitään. Sitten piirsin tien, joka koostui ainoastaan suorakulmioista, Graphics2D-olion avulla. Muistin viimeiseltä olosessiolta Mikko Kosken heittämän idean liikkuvista pylväistä, joten laitoin tien päällä harmaita pylväitä ja laitoin ne liikkumaan ajastimen tahdissa. Kolmen tunnin Graphics2D pyörittelyn jälkeen sain liikkuvan tien aikaiseksi. Tästä innostuneen tein projektiani seuraavat seitsemän tuntia, jolloin aloin liittää tien päälle ohjattavaa autoa, muita esineitä ja niiden arvontamekanismia. Saman päivän loppupuolella sain jo pelattavan pelin aikaiseksi. Muuten samalla viikolla tein töitä vain satunnaisesti ja ensimmäisen päivän kymmenen tunnin session lisäksi sain tehtyä noin viisi tuntia lisää hommia projektin parissa. Ensimmäisen viikon tuloksena oli pelattava peli, jossa oli kasvava pelinopeus, tuloksien tallennusjärjestelmä sekä nimen kysyminen käyttäjältä. Käytännössä puuttui enää aloitus-, tulosruutu ja niiden asettelu CardLayout:iin sekä alkunopeuden valinta pelin alussa. Tässä vaiheessa päätin, että voisin alkaa pitää parin viikon joululomaa. Siis suunnitelman mukainen aikataulu petti mullakin, mutta ehkä kohtuullisen positiivisella tavalla. Kun joululoma oli vietetty ja muutto uuteen kotiinkin saatu aikaiseksi, aloitin jälleen työt projektini parissa. Tässä vaiheessa tärkeimmät tehtävät olivat arvonta-algoritmin ja nopeuksien optimointi sekä ulkoasun ja CardLayout:n toteuttaminen projektiin. Optimaaliset arvonta- ja nopeussäädöt löytyivät vähitellen kokeilemalla, eikä niihin uponnut järjettömiä aikoja. Pyrin myös antamaan muiden ihmisten kokeilla peliäni, jotta saisin vähän ulkopuolista mielipidettä pelinopeuteen. tämän jälkeen keskityin CardLayout:n opiskeluun, mikä ilmeni parin tunnin Java tutorials tutkimisen jälkeen yllättävän yksinkertaiseksi asiaksi. Aloitus- ja tulosruudun väätäminen sekä niiden asetteleminen CardLayout:iin vei kolmisen tuntia. Nämä uudet ulkoasu muutokset toivat kuitenkin kaksi uutta ongelmaa peliini, joiden korjaaminen vei seuraavat puolitoista päivää. Ensimmäinen pelin kannalta hyvin merkittävä ongelma oli sellainen, että aloitusruudun asettaminen ennen varsinaisen peliruutua teki auton ohjaamisen näppäimistöllä mahdottomaksi. Muutaman tunnin Java tutorialsin tutkimisen jälkeen aloin ymmärtää, että kyseessä oli ongelma näppäimistöfokuksen kanssa. Ilmeisesti näppäimistöfokus ei siirtynyt automaattisesti aloitusruudusta peliruutuun, vaikka se laitettiinkin näkyväksi. Yön yli nukuttua löysin sopivan metodin, jolla pystyi pyytämään fokuksen siirtoa peliruutuun, mutta sen sijoittaminen oikeaan paikkaan vei pari tuntia lisää. Kun korjailin ensimmäistä ongelmaa, oli samaan aikaan ollut myös toinen bugi. Ongelma koski peliruudun värivirheitä, jotka aiheutuivat siitä, kun aloitusruudun värejä näkyi läpi. Muutaman tunnin Kala-kirjan ja Java tutorialsin tutkimisen jälkeen löysin korjauksen ongelmaan paintComponent-metodin API:sta ratkaisun. Ongelma johtui kyseisen komponentin läpinäkyvyydestä. Kun käytin metodia setOpaque(false), värivirheet hävisivät täysin. Näiden parin bugin korjaamisen jälkeen olin hyvinkin tyytyväinen peliini ja aikaa DL:ään oli vielä muutama päivä. Tässä vaiheessa aloin kommentoida koodiani. Olen aina koennut kommentoimisen hyvin raskaaksi hommaksi ja joskus tuntuu siltä, että siihen menee yhtä paljon aikaa kuin varsinaiseen koodaamiseen. Tällä kertaa kommentoimiseen meni noin seitsemän tuntia, mikä on merkittävä määrä projektiin kulutetusta ajasta. Tämä osuus hoitui kuitenkin rutiininomaisesti ja aloin pohtia lisäominaisuuksia peliini. Yksi usein kuulemani ehdotus lisäominaisuudeksi oli ääniefekti. Etsiskelin muutaman tunnin sopivia äänitiedostoja netistä, mutta niiden löytäminen oli uskomattoman hankalaa. Kokeilin muutamaa efektiä pelissäni ja ne tuntui äärimmäisen tyhmiltä. Ajattelin myös sitä, etten tiennyt miten voisin varmistaa niiden toimimisen äänikortittomissa tietokoneissa. Tämä ongelma tuli esiin myös, kun viimeisestä Java-harjoitukseen lisäsin ääniefektejä, eikä se enää toiminut Paniikin koneissa. Näiden syiden takia päätin olla käyttämättä äänejä lopullisessa pelissäni. FiiliksetKuvittelin alussa, että joutuisin käyttää koko joululomani tämän projektin parissa. Onneksi suunnittelin tarpeeksi hyvin jo alusta lähtien ja suunnitelmakin oli alusta asti realistinen. Aloitin hommat täsmälleen silloin, kun suunnitelinkin aloittavani. Kuitenkin pääsin eteenpäin monta kertaa nopeammin kuin alussa kuvittelin, joten aikaa jäi reilusti enemmän lomailuun. Aikaa kului projektiin kokonaisuudessa varmasti alle 60 tuntia, mikä on vähemmän kuin ohjeellinen projektiin käytettävä aika. Pitää toivoa, ettei siitä rangaista projektin arvostelussa. Pelistä tuli kylläkin vähintää niin hyvä kuin, mitä alun perin suunnittelinkin. Sain peliini kaikki suunnittelemani ominaisuudet ja jopa enemmänkin. Siitä tuli myös visuaalisesti parempi kuin kuvittelin suunnitteluvaiheessa, koska käytin tien piirtämisessä Javan valmiita piirtotyökaluja. Myös ohjelman selkeys yllätti minut positiivisesti. Kuvittelin, että ohjelmakoodista ja luokkajaosta olisi tullut selvästi sekavampi kuin mitä se on, koska suunnitelmani ei ollut kauheen teknisesti yksityiskohtainen. Olen erityisen tyytyväinen siihen, että sain pidettyä grafiikan ja pelilogiikan erillään. Tämä on ensimmäinen kerta, kun jouduin toteuttaa yksin näin kokonaisvaltaista projektia. Tästä työstä huomaa hyvin kuinka olennaista suunnittelu on ennen varsinaisen työn aloittamista. Olen erityisen tyytyväinen siihen, että sain aloitettua hommat silloin, kun suunnittelinkin, mikä on hyvin harvinaista herkkua. Hyvän suunnittelun takia en ole joutunut valvomaan yhtään yötä tämän projektin takia. Positiivinen juttu oli myös se, että sain itseopiskelulla opittua muutaman projektissa tarvittavan ohjelmointiin liittyvän asian, kuten animoinnin, Gaphics2D-luokan ja CardLayout:n käytön. Peliäkin on mukava silloin tällöin pelata, kun ei kotona ole muuta tekemistä. TuotokseniLopullisen version ohjelmakoodi löytyy tästä ja Javadoc:it tästä. Peliä pystyy kokeilemaan lataamalla tiedoston Autobahn.jar tästä ja purkaamalla se esimerkiksi WinRar-ohjelmalla ja ajamalla sieltä löytyvä tiedosto Autobahn.bat (Windows) tai komentorivikomennolla java Autobahn. Voit myös ladata ohjelmakoodin, kääntää se ja ajaa se komentorivikomennolla java Autobahn. |
||