NUORTEN PELIOHJELMOINTI Jyväskylän yliopisto Kesä 2010 Antti-Jussi Lakanen, Tero Jäntti, Vesa Lappalainen, Juho Tammela 7.6.2010
DreamSpark-koodi Visual Studio Professional 2008 -ohjelmiston lataamista varten: Ohjelman voit ladata osoitteesta https://www.dreamspark.com/default.aspx. Tarvitset yllä olevan koodin ohjelman lataamiseen. Tarkemmat asennusohjeet tämän vihkosen osiossa Työkalut tai kurssin WWW-sivulla https://trac.cc.jyu.fi/projects/npo09/wiki/visualstudioasennus 1
Johdanto 2
TERVETULOA PELIOHJELMOINNIN MAAILMAAN Olet astumassa sisälle peliohjelmoinnin ihmeelliseen maailmaan. Tämä vihkonen on tarkoitettu käytettäväksi peliohjelmointikurssin tukimateriaalina, ja se sisältää jonkin verran myös sellaista asiaa, mitä ei kurssilla käsitellä. Tämän oppaan avulla voit aloittaa peliohjelmoinnin käyttämiemme välineiden avulla, vaikka olisitkin unohtanut, miten asiat kurssilla tehtiinkään. Ohjeen aiheet etenevät siinä järjestyksessä, kuin ne kurssilla opetetaan: 1. Johdanto (tämä luku) 2. Työkalut 3. Ensimmäisen pelin tekeminen 4. Algoritminen ajattelu ja algoritmin suunnittelu 5. Aliohjelma 6. Ehtolause ja silmukka 7. Pelisuunnittelu Kunkin osion päätteeksi löytyy kurssilla yhdessä käsiteltäviä tehtäviä. Mukana on myös lisätehtäviä, joita käsitellään kurssilla mikäli aikaa jää. Voit tietenkin tehdä omaan tahtiin myös näitä lisätehtäviä, ja pyytää ohjaajilta apua niiden ratkaisussa. // TODO: Tehtävien lisääminen osioiden päätteeksi. Tässä oppaassa käytetyistä merkinnöistä Peliohjelmointi on kuin suklaalevy. Päältä kova, mutta sisältä makea. Tero Jäntti, koodaaja Tulet näkemään tässä kirjasessa matkan varrella seuraavia kuvakkeita. Niiden tarkoitus on osoittaa enemmän tai vähemmän tärkeää tietoa. Tämän kuvakkeen tarkoituksena on osoittaa jokin erityistä huomiota vaativa seikka. HUOMIO Tämä kuvake tarkoittaa jotain aiheeseen liittyvää erityistietoa, jonka voit vapaasti sivuuttaa ensimmäisellä lukukerralla. TECH STUFF 3
Tietoa kurssista Kurssi järjestettiin ensimmäisen kerran kesällä 2009 ja suuren suosion saattelemana niitä järjestetään kesällä 2010 ainakin kolme kappaletta ja enemmänkin, jos tulijoita riittää. Kirjoitushetkellä (toukokuu 2010) ilmoittautuneita tulevan kesän kursseille on noin 90 kappaletta. TECH STUFF Ensimmäisten kurssien kokemuksista valmistui Antti-Jussi Lakasen pro gradu -tutkielma Nuorten peliohjelmointi keväällä 2010. Gradu löytyy netistä osoitteessa http://users.jyu.fi/~anlakane/gradu/2010-05- 06-painoon.pdf, tai http://jyx.jyu.fi. Yhteystiedot Vastaamme mielellämme kysymyksiisi. Tavoitat opettajat ja ohjaajat yhteiseltä sähköpostilistalta. Ohjaajien sähköpostilista (viesti ei näy muille kurssilaisille): pelik2009.group@korppi.jyu.fi Kurssin oppilaiden sähköpostilista (viesti näkyy kurssilaisille ja ohjaajille): npo23_2010@korppi.jyu.fi. Tämä sähköpostilista on tarkoitettu kaikenlaisille kurssiin edes etäisesti liittyvälle keskustelulle, ja on käytössä vielä kurssin jälkeenkin. Opettaja: Antti-Jussi Lakanen, anlakane@jyu.fi, p. 0500 603 111 Järjestäjä: Tietotekniikan laitos, vastuuhenkilö Lehtori Vesa Lappalainen, vesal@jyu.fi, p. 0400 242 990 Kurssin WWW-sivu: https://trac.cc.jyu.fi/projects/npo09_pelit/. 4
Kurssin aikataulu Kurssi alkaa päivittäin kello 9:00 ja päättyy kello 15:00. Aamu alkaa aina lyhyellä oppitunnilla luentosalissa Delta, minkä jälkeen siirrytään tekemään harjoituksia tietokoneluokkiin. Ruokatauko pidetään noin klo 11:30 12:15, ruokailu tapahtuu opiskelijaravintola Piatossa (niin ikään Agorassa) tai omin eväin (käytössä mm. mikro, jääkaappi ja vedenkeitin). Aamupäivällä ja iltapäivällä on lisäksi yhteensä pari-kolme lyhyttä taukoa PV PAIKKA AIHEET Ma 9:00 Luentosali, sitten mikroluokat Ruokailun jälkeen luentosali, sitten mikroluokat Tutustuminen työkaluihin ja alkuvalmistelut, ensiohjelmointia, suunnittelu ja algoritmit Ti 9:00 Luentosali, sitten mikroluokat Ruokailun jälkeen luentosali, sitten mikroluokat Aliohjelma ja ohjausrakenteet (ehtolauseet, silmukat), oliot, valmiisiin pelimalleihin tutustuminen, oman pelin suunnittelu. Ke 9:00 Mikroluokat Ruokailun jälkeen luentosali, sitten mikroluokat Oman pelin suunnittelu, oman pelin tekeminen To 9:00 Luentosali, sitten mikroluokat Ruokailun jälkeen luentosali, sitten mikroluokat Oman pelin tekeminen Pe 9:00 Luentosali, sitten mikroluokat Ruokailun jälkeen luentosali, sitten mikroluokat Oman pelin viimeistely, pelien testaus ja pelin esittelytilaisuus, sekä parhaan pelin äänestäminen ja voittajien palkitseminen Huom! Aikataulut saattavat muuttua. Muutoksista tiedotetaan sähköpostin välityksellä, eli tarkkaile postiasi kurssin aikana. 5
Näin löydät luokkiin 6
Mitä on ohjelmointi Ohjelmointi tarkoittaa periaatteessa toimintaohjeiden antamista jonkin asian suorittamista varten. Toimintaa, jota voisi nimittää ohjelmoinniksi, tapahtuu elämässämme päivittäin. Ajo-ohjeiden antaminen puhelimessa voisi olla yksi esimerkki tällaisesta tilanteesta. Jos kotisi sijainti ei ole kaverillesi ennestään tuttu, sinun on annettava hänelle tarkat ohjeet ja komennot, joiden avulla hän löytää perille. Antamiasi ohjeita noudattamalla hän (toivottavasti) löytää perille. Toinen esimerkki on kakun valmistukseen kirjoitettu ohje: Sokerikakku 6 munaa 1,5 dl sokeria 1,5 dl jauhoja 1,5 tl leivinjauhetta 1. Vatkaa sokeri ja munat vaahdoksi. 2. Sekoita jauhot ja leivinjauhe. 3. Sekoita muna-sokerivaahto ja jauhoseos. 4. Paista 45 min 175 C lämpötilassa. Yllä oleva valmistusohje on ilmiselvästi kirjoitettu ihmistä varten, vieläpä sellaista ihmistä, joka tietää leipomisesta melko paljon. Jos sama ohje kirjoitettaisiin ihmiselle, joka ei eläessään ole leiponut mitään, täytyisi huomioida useita leipomiseen liittyviä niksejä: uunin ennakkoon lämmittäminen, vaahdon vatkauksen salat, yms. Tietokoneelle kirjoitettavat ohjeet poikkeavat merkittävästi ihmisille kirjoitetuista ohjeista. Kone ei osaa automaattisesti kysyä neuvoa törmätessään uuteen ja ennalta arvaamattomaan tilanteeseen. Se toimii täsmälleen niiden ohjeiden mukaan, jotka sille on annettu, olivatpa ne sitten miten tyhmiä tahansa. Kone noudattaa saamiaan ohjeita uskollisesti sortumatta ihmisille tyypilliseen luovuuteen. Alkeellista ohjelmointia on tavallaan myös mikroaaltouunin käyttäminen. Uunille annetaan ohjeet siitä, kuinka kauan ja millä teholla sen tulee toimia. Alkeellista ohjelmointia on myös mikroaaltouunin käyttäminen. 7
Työkalut 8
TYÖKALUT Tässä luvussa käydään lyhyesti läpi kurssilla käytettävät työkalut, ja opastetaan niiden asentaminen, jotta voit itse aloittaa tai jatkaa työskentelyä kotitietokoneellasi esimerkiksi kurssin jälkeen. Huomaa, että asennusjärjestys on oleellinen. Asenna ensin Visual Studio, sen jälkeen XNA Game Studio, ja viimeisenä Jypeli-kirjasto sekä projektimallit. Mikäli asennat XNA:n ennen Visual Studiota, ei Visual Studio tunnista automaattisesti XNA:n olemassaoloa. Visual Studio Professional 2008 Tietokoneelle pitää asentaa Visual Studio, XNA Game Studio, sekä Jypeli-kirjasto. Kurssilla käytössä oleva ohjelmointiympäristö eli IDE (eng. Integrated Development Environment) on nimeltään Visual Studio, erityisesti versio 2008 Professional. Ohjelmointiympäristön avulla voi kirjoittaa koodia, kääntää ja ajaa kirjoitetun ohjelman sekä jäljittää virheitä koodista (eli debugata ). Visual Studion voit ladata osoitteesta https://www.dreamspark.com/default.aspx. Klikkaa kohdasta Visual Studio 2008 Professional Edition (ks. kuva alla). 9
Lataamista varten sinun on vielä rekisteröidyttävä Windows Live -palveluiden käyttäjäksi, ellet ole jo sellainen. (Jos esimerkiksi käytät Microsoft Live Messengeriä, niin sinulla jo lienee Live-käyttäjätunnus.) Ohjelma on pakattu ns. ISO- eli levykuvatiedostoon, ja edellyttää erityistä purkamista. Ohjeet tiedoston purkamiseen löytyvät osoitteesta http://blogs.msdn.com/b/gautam/archive/2009/01/13/how-to-download-install-dreamsparksoftware.aspx (englanniksi). Vaihtoehtoisesti voit asentaa myös Visual C# 2008 Express Editionin (http://www.microsoft.com/express/vcsharp/). Suosittelemme kuitenkin Professional-version asentamista, sillä kurssin WWW-sivuilla olevat ohjeet on tehty Professional-versiota silmällä pitäen. Ohjeet Express Editionin lataamiseksi löydät osoitteesta https://trac.cc.jyu.fi/projects/npo09/wiki/visualstudioasennus#vaihtoehto1:visualc2008expr essedition. XNA Game Studio 3.1 XNA Game Studio on Microsoftin kehittämä peliohjelmointiin tarkoitettu luokkakirjasto (eli valmiiden ohjelman osasten, kuten olioiden ja aliohjelmien) kokoelma, ja Visual Studion laajennusosa. XNA:lla on pyritty houkuttelemaan nimenomaan aloittelevia ohjelmoijia tekemällä yksinkertaisten 2D-pelien ohjelmoinnista helppoa. XNA:lla tehdyt pelit toimivat ainakin Windows-tietokoneissa ja XBox 360 -pelikonsolissa sekä Zune-mediasoittimessa. XNA:lla tehdyt pelit eivät toimi tietokoneissa, joihin ei ole asennettu XNA Game Studiota. XNA:n voi ladata osoitteesta http://download.microsoft.com/download/b/d/d/bddf0144-5250-421d-b3ab-4d6be889927f/xnags31_setup.exe. Muista, että Visual Studio tulee asentaa ennen XNA:n asentamista. XNA:sta on ilmestynyt keväällä 2010 versio 4.0, mutta siinä on toistaiseksi vielä puutteita, joiden takia sitä ei voi käyttää tällä kurssilla. Huomioi tämä, jos etsit XNA-pakettia esimerkiksi googlettamalla. 10
Jypeli-kirjasto ja projektimallit Kun olet asentanut Visual Studion, XNA Game Studion ja TortoiseSVN:n, olet valmis lataamaan koneellesi Jypeli-kirjaston ja kirjastoon liittyvät projektimallit. Ennen Jypeli-kirjaston lataamista on hyvä luoda koneellesi jokin kansio tekemiäsi ohjelmointiprojekteja varten. Luo esimerkiksi kansio: C:\MyTemp ja tämän kansion alle kansio tunnus (eli käyttäjätunnus, jonka sait rekisteröityessäsi kurssille käyttäjäksi). Tämän kansion alle voit sijoittaa sekä Jypeli-kirjaston että omat kooditiedostosi. Lataa nyt Jypeli-kirjasto seuraavasti. 1. Mene osoitteeseen https://trac.cc.jyu.fi/projects/npo09/browser 2. Valitse haluamasi Jypeli-versio a. Mikäli haluat kirjaston uusimman kehitysversion, valitse trunk. Kehitysversiossa on enemmän ominaisuuksia, mutta siinä voi olla myös bugeja. On myös mahdollista, että siihen tehdyt muutokset ovat sellaisia, että kurssin aikana tehdyt pelit eivät toimi sen kanssa ilman muutoksia. b. Jos haluat viimeisimmän vakaan version, klikkaa tags, ja sieltä haluamasi versionumero (yleensä viimeisin). 3. Mene sivun alareunaan, ja klikkaa Download in other formats: Zip Archive. 4. Luo esimerkiksi kansio C:\MyTemp \ Jypeli ja tallenna ladattava tiedosto sinne. 5. Pura Zip-tiedosto. Jos sinulla ei ole Zip-pakettien purkuohjelmaa, niin voit ladata sellaisen ilmaiseksi, esimerkiksi osoitteesta http://www.izarc.org/download.html. 6. Kaikki kirjastoon liittyvät tiedostot ovat nyt kansiossa C:\MyTemp\ Jypeli\tags\2.0.0 (tai jokin muu versionumero). Esimerkiksi dll-tiedostot löytyvät tuon kansion alta lib-hakemistosta. 7. Voit poistaa lataamasi Zip-tiedoston. HUOMIO Huomaa, että jos haluat myöhemmin ladata uuden Jypeli-version (joka sisältää uusia ominaisuuksia), sinun täytyy uudestaan ladata myös Zip-tiedosto ja purkaa se vastaavasti kuin yllä. TECH STUFF Versionhallinnasta puhuttaessa tagilla tarkoitetaan koodista julkaistua versiota tai vaihetta. Tiettyyn versioon (siis tagiin) on tavallaan jäädytetty jollain tietyllä ajanhetkellä ollut koodin kehitysversio. Projektimalli on koodipohja, joka sisältää "pakolliset" tiedot uudesta Jypeli-pelistä, kuten viitteet Jypeli- ja XNA-kirjastoihin. Jotkin projektimallit sisältävät myös valmiin pelipohjan, jonka päälle voi lähteä rakentamaan omaa peliä. 11
Lataa ja asenna Jypeli-projektimallit seuraavasti. Mene osoitteeseen https://trac.cc.jyu.fi/projects/npo09/wiki/projektimallienasennus. Lataa sivun yläosassa olevat tiedostot ja tallenna ne seuraavasti: 1. Valitse yläreunan alasvetolistasta Oma tietokone (My Computer) 2. Klikkaa kansioita järjestyksessä: Suomenkieliset hakemistot: C: Documents and Settings Oma käyttäjätunnus Omat Tiedostot Visual Studio 2008 Templates Project Templates Visual C# Englanninkieliset hakemistot: C: Documents and Settings Oma käyttäjätunnus My Documents Visual Studio 2008 Templates Project Templates Visual C# 3. Luo tarvittaessa kansio nimeltä "Jypeli" ja avaa se. (Kansion luominen tapahtuu klikkaamalla tyhjää kohtaa hiiren oikealla napilla ja valitsemalla Uusi Kansio. 4. Paina Tallenna. Jos sinulla on Visual Studio auki, sulje se ja käynnistä uudestaan, jotta tallennetut projektimallit ovat käytettävissä. Projektimallien käyttöä esitellään seuraavassa luvussa (Ensimmäisen pelin tekeminen). 12
Ensimmäisen pelin tekeminen 13
ENSIMMÄISEN PELIN TEKEMINEN Tässä luvussa käydään läpi muutamia ensimmäisen pelin tekemiseen liittyviä asioita. Ensimmäisen pelin tekemisen aikana opit monta tärkeää ohjelmoinnin peruskäsitettä. Visual Studion käynnistäminen Käynnistä Visual Studio 2008 tuplaklikkaamalla työpöydällä olevaa pikakuvaketta tai valitsemalla Start All Programs Microsoft Visual Studio 2008 Microsoft Visual Studio 2008 Ensimmäisen pelin tekemisen aikana opit monta tärkeää ohjelmoinnin peruskäsitettä. Jos käytät Visual Studion Express-versiota, valitse sen sijaan Start All Programs Microsoft Visual C# 2008 Express Edition Jos käynnistät Visual Studion Professional-versiota ensimmäistä kertaa, sinulta kysytään minkä ohjelmointiympäristön asetuksia käytetään oletuksena. Koska kurssilla ohjelmoidaan C#-kielellä, valitse seuraavasti: 1. Valitse listasta Visual C# Development Settings 2. Klikkaa Start Visual Studio. 14
Projektin luominen Kun Visual Studio on käynnistynyt, tehdään uusi projekti. Projekti on työtila, jossa käsitellään koodia ja peliin liittyviä grafiikka- ja musiikkitiedostoja. Seuraavaksi kerrotaan, miten luodaan uusi projekti peliä varten. Jatkossa teet projektit muitakin pelejä varten samaan tapaan, mutta nimeksi voit valita mitä tahansa (mielellään kuitenkin vain englanninkielisiä aakkosia sekä numeroita nimessä). Voit tietenkin käyttää muitakin projektimalleja kuin FysiikkaPeliä (projektimalleista lisää hetken päästä). Klikkaa Visual Studiossa File New Project... 15
Aukeavassa ikkunassa tee seuraavat vaiheet (Professional-versio). 1. Klikkaa vasemmalla olevasta listasta Visual C#. 2. Klikkaa sitten vasemmalla olevasta listasta Jypeli. 3. Valitse oikealla olevasta listasta kohta FysiikkaPeli. 4. Aseta Name-tekstikenttään pelin nimeksi "Pong" (tai muu valitsemasi nimi) 5. Kirjoita Location-kenttään polku C:\MyTemp \tunnus, missä kirjoitat sanan tunnus tilalle oman hakemistosi (mikä haettiin näiden ohjeiden mukaan). Voit myös painaa Browse... -nappia ja etsiä hakemistosi sitä kautta klikkaamalla järjestyksessä My Computer Local Disk (C:) MyTemp tunnus 6. Ota ruksi pois kohdasta Create directory for solution. 7. Vahvista uuden projektin luominen klikkaamalla OK. 16
Mikäli käytät Express-versiota, toimi seuraavasti: 1. Avaa Visual C# -valikosta Jypeli-kohta. 2. Klikkaa FysiikkaPeli. 3. Kirjoita Name-kohtaan Pong. 4. Laita Location-kohtaan oikea kansio, esimerkiksi C:\MyTemp \tunnus. 5. Varmsta, että kohdassa Create directory for solution ei ole ruksia. 6. Kuittaa painamalla OK. Ohjelmoinnin aloittaminen Nyt olet valmis aloittamaan ohjelmakoodin kirjoittamisen. Huomaa, että juuri luodussa uudessa projektissa on paljon tiedostoja. Projektin tiedostot näkyvät Visual Studion oikeassa reunassa Solution Explorer -paneelissa. Mikäli Solution Explorer on syystä tai toisesta näkymättömissä, saat sen esiin klikkaamalla valikosta View Solution Explorer tai käyttämällä näppäinoikotietä Ctrl+W, S (Ctrl-näppäin alas painettuna näppäile W ja sitten S). Lisää näppäinoikoteitä löydät kurssin wiki-sivulta osoitteessa https://trac.cc.jyu.fi/projects/npo09/wiki/nappainkomentoja. HUOMIO 17
Tässä vaiheessa meitä kiinnostaa ainoastaan tiedosto nimeltä Peli.cs, johon tulee C#- ohjelmointikielellä kirjoitettavaa koodia. Tuplaklikkaa tuota tiedostoa, jolloin se aukeaa editoriin muokattavaksi. Voit nyt aloittaa ohjelman kirjoittamisen esimerkiksi kurssin Pong-tutoriaalin mukaan, joka löytyy WWW-osoitteesta https://trac.cc.jyu.fi/projects/npo09/wiki/pong/vaihe1. Muuttujat ja perustyypit Muuttujat toimivat ohjelmassa tietovarastoina erilaisille asioille. Niihin voidaan tallentaa laskennan välituloksia, tietoa ohjelman käyttäjästä ja paljon muuta. Ilman muuttujia järkevä tiedon käsittely olisi oikeastaan mahdotonta. Muuttujat ovat ohjelmointikielen helpotus. Oikeastihan muuttujien arvot tallennetaan keskusmuistiin tai ns. rekistereihin. Muuttujan nimi onkin ohjelmointikielten helpotus, sillä näin ohjelmoijan ei tarvitse tietää tarvitsemansa tiedon keskusmuisti- tai rekisteriosoitetta, vaan riittää muistaa itse nimeämänsä muuttujan nimi. Muuttuja määritellään seuraavasti. muuttujantietotyyppi muuttujannimi; Esimerkiksi muuttuja, johon tullaan tallentamaan ohi kulkeneiden autojen määrää, voitaisiin esitellä seuraavasti. int autojenmaara; Huomaa, että tässä tapauksessa muuttujaa ei ole pakko alustaa, vaan se voidaan tehdä myöhemmin esimerkiksi seuraavasti. autojenmaara = 5; Muuttujan alustaminen tapahtuu aina käyttämällä = -merkkiä. Mikäli muuttujan arvo on alustettu (kuten edellä on), voidaan arvoa muuttaa myös suhteessa edelliseen arvoon. Jos esimerkiksi nyt kirjoitettaisiin, autojenmaara = autojenmaara + 1; niin paljonko autojen uusi määrä olisi? Vastaus on kuusi. HUOMIO Huomaa, että on yhtä kuin -merkki ilmoittaa sijoituksesta siis, että jokin arvo asetetaan jonkin muuttujan sisällöksi. Tämä ei välttämättä heti tunnu loogiselta, jos asiaa ajattelee matematiikan avulla: miten x voi olla x + 1. 18
Alla on esitelty muutamia C#-kielen muuttujien perustyyppejä, sekä esimerkkejä niiden käytöstä. Näitä tietoja tarvitset jo tehdessäsi ensimmäistä pelitutoriaalia, Pongia. LUVUT Nimi C#:ssa Suomennos Selitys Esimerkki int Kokonaisluku (eng. integer) Muuttuja, johon voidaan sijoittaa etumerkillinen kokonaisluku. Inttyypin luvulla ei ole desimaaliosaa. Inttyyppisiin muuttujiin voidaan tallentaa lukuja n. -2 miljardista +2 miljardiin. int luku = 250; int luku = -5; double Liukuluku (eli desimaaliluku) Muuttuja, jolla voi ilmaista desimaalilukuja jopa 15 desimaalin tarkkuudella. Lukualue riittävästi. double d = 0.000145; (huomaa piste, ei pilkku) Lukuja varten on olemassa muitakin tyyppejä. Yksi mainitsemisen arvoinen on byte, nimensä mukaisesti tavun kokoinen (8 bittiä) ja arvoalue 0..255 (ei etumerkkiä). MERKIT JA MERKKIJONOT Nimi C#:ssa Suomennos Selitys Esimerkki char Merkki (eng. character) Char-tyypin muuttujaan voidaan tallentaa (vain) yksi merkki. char c = 'a'; char d = ' '; (yksinkertaiset lainausmerkit) string Merkkijono (eng. string of characters) String-tyyppiseen muuttujaan voidaan tallentaa useita merkkejä kerrallaan, vaikkapa sanoja tai lauseita. string a = "Antti-Jussi"; (kaksinkertaiset lainausmerkit) TOTUUSARVO Nimi C#:ssa Suomennos Selitys bool Totuusarvo, tosi tai epätosi (true tai false) Tarvitaan, kun halutaan esimerkiksi vertailla muuttujien arvoja. Esimerkiksi if(5==6) antaa tulokseksi false. 19
Usein muuttujiin täytyy tallentaa erilaisten laskutoimitusten tuloksia. Vertailuoperaattorit palauttavat aina totuusarvon (true tai false). LUKUJEN LASKEMISTA Operaattori Käyttö Selitys = a = b; Sijoitus (b:n arvo sijoitetaan muuttujaan a). + a + b; Lasketaan kaksi lukua, a ja b, yhteen. Muista että + -operaattoria voidaan käyttää myös merkkijonojen yhdistämiseen. - a b; Vähennyslasku (a:n arvosta vähennetään b:n arvo). * a * b; Kertolasku / a / b; Jakolasku. Huom. nollalla ei saa jakaa! % a % b; Jakolaskun jakojäännös, esimerkiksi 9 % 2 tulos on 1, 9 % 3 tulos on 0, 14 % 8 tulos on 6. Lisäksi esimerkiksi sijoitus a = a + b voidaan kirjoittaa lyhyempään muotoon a += b. Sanallisesti ilmaistuna tämä tarkoittaa, että muuttujan a arvoon lisätään b:n arvo. Sama käytäntö pätee myös muille operaattoreille. Kahden muuttujan vertailua voidaan käyttää esimerkiksi if-lauseessa. Muuttujien paikalla voidaan edelleen käyttää operaatiolausekkeita. Tässä yleisimmät vertailuoperaattorit. VERTAILUOPERAATTORIT Operaattori Käyttö Selitys Esimerkki == a == b Yhtäsuuruus // Tutkitaan ovatko sanat samoja String sana1 = Antti-Jussi; String sana2 = antti-jussi; if(sana1 == sana2) { MessageDisplay.Add( Samat ); } else { MessageDisplay.Add( Eivät ihan samoja ); } 20
!= a!= b Erisuuruus // Tutkitaan lukujen yhtäsuuruutta int a = 5; int b = 50; b /= 10; if((a!=b)) { // Luvut eivät samat } else { // Luvut samat } < a < b Pienempi kuin > a > b Suurempi kuin Muuttujien tyyppimuunnokset Joskus on tarvetta muuttaa vaikkapa kokonaisluku liukuluvuksi tai merkkijonoksi. Se onnistuu tekemällä seuraavien esimerkkien mukaan. Kokonaisluku-tyyppisen (int) muuttujan muuttaminen liukuluku-tyyppiseksi (double). int luku = 7; double luku2 = (double)luku; Muutetaan vielä luku2-muuttuja merkkijonoksi ToString()-aliohjelmalla. Huomaa, että muuttujan merkkijono alustus tapahtuu tässä samalla kertaa. String merkkijono = luku2.tostring(); 21
Algoritmit 22
ALGORITMINEN AJATTELU JA ALGORITMIN SUUNNITTELU Mikä on algoritmi Algoritmi on ohje tai toimenpidesarja, jolla voidaan ratkaista joku tietty ongelma. täytyy olla yksikäsitteinen, eli se ei saa olla tulkinnanvarainen. Eräänlaisia algoritmeja ovat esimerkiksi keittokirjassa olevat Algoritmi on yksikäsitteinen toimenpidesarja. ruokaohjeet kirjahyllyn mukana tulevat kokoamisohjeet jne. Näiden ohjeiden mukaan tehtynä ruoan ja kirjahyllyn pitäisi valmistua tuossa tuokiossa! Eri asia on sitten se, valmistuuko oikeasti Algoritmin kertoo ainoastaan miten joku asia tehdään, ei miksi. Algoritmi ei siis itsessään ole oikea tai väärä, vaan saman ongelman ratkaisuun voi olla monta erilaista algoritmia, joista jokin voi olla toista parempi. Esimerkiksi mansikkakakun voi tehdä monella tavalla, ja jokaisella meistä on varmaankin oma lempikakku. Niinpä voidaankin olla montaa mieltä siitä, mikä tapa tehdä kakkua (eli mikä algoritmi!) on paras. Jakokulmassa jakaminen on myös eräs alakoulusta tuttu algoritmi. Miksi algoritmeja pitää suunnitella? Tietokone ei ymmärrä mitään siitä, mitä siihen syötetyllä ohjelmalla pyritään tekemään. Koska tietokone ei ymmärrä ihmisten käyttämää kieltä, ei esimerkiksi keittokirjaa sellaisenaan voi naputtaa koneeseen ja tehdä kokkausrobottia. Koska tietokone on "tyhmä", tietokoneohjelmassa algoritmin ohjeet täytyy selittää rautalangasta vääntäen erittäin tarkasti. Suurin osa tietokoneohjelmien virheistä tulee joko siitä, ettei algoritmia ole esitetty tietokoneelle oikein, tai siitä, että koko algoritmi on alkujaankin ollut päin mäntyä. 23
Mikä on huono algoritmi? Palataan vielä aikaisempaan esimerkkiin, missä piti selvittää onko kokonaisluku parillinen vai pariton. Voidaan sanoa, että algoritmi, jolla asia selvitettiin aiemmin, toimi hyvin. Myös seuraavanlainen (ns. pseudokielinen eli muka-ohjelmointikielinen ) algoritmi toimisi ainakin johonkin pisteeseen asti. Jos luku on 0, se on parillinen Jos luku on 1, se on pariton (ja niin edelleen johonkin lukuun saakka) Jos luku on -1, se on pariton Jos luku on -2, se on parillinen (ja niin edelleen johonkin lukuun saakka) Jos tutkittava luku olisi vaikkapa -50 miljoonaa, jouduttaisiin tekemään hurjan monta tarkistusta ennen kuin tieto saataisiin selville. Toki se lopulta selviäisi, mutta voidaan varmaankin olla yhtä mieltä siitä, että tämä algoritmi ei ole kovin kummoinen. Tästä huomaamme, että ei ole yhdentekevää, miten ohjelmoinnissa esiintyviä ongelmia ratkaisemme siis millaisia algoritmeja kirjoitamme. Emme tietenkään halua tuhlata tietokoneen voimia turhuuteen, vaan tavoite on saada prosessorista mahdollisimman paljon irti. Niinpä tehokkaat algoritmit tarkoittavat nopeampia ohjelmia ja vähemmän odottamista käyttäjälle. Ei ole yhdentekevää, millaisia algoritmeja kirjoitamme. Esimerkiksi aliohjelmia tehdessämme meidän on mietittävä, miten toteutamme ne mahdollisimman tehokkaasti (ja mielellään myös mahdollisimman vähillä koodiriveillä). Aliohjelmia käsittelemme tarkemmin seuraavassa luvussa. 24
Aliohjelmat 25
ALIOHJELMAT Aliohjelmat eli funktiot ovat ohjelman osia, joista jokainen hoitaa jotain omaa erityistä tehtäväänsä. Voidaan sanoa, että ohjelmat koostuvat aliohjelmista, eli ne ovat ohjelmien rakennuspalikoita. Kun ohjelma voidaan jakaa pienempiin osiin (aliohjelmiin), sen hallinta helpottuu. Muun muassa virheiden jäljittäminen helpottuu, kun ohjelma on jaettu (tarpeeksi pieniin) aliohjelmiin. Esimerkiksi Pong-pelissä pallo luotiin kentälle, paikkaan ( 200, 0) seuraavalla tavalla. //TODO: Tarkista koodi. PhysicsObject pallo = new PhysicsObject( 10.0, new Vector( 40.0, 40.0 ) ); pallo.shape = Shapes.Circle; pallo.x = -200.0; pallo.y = 0.0; Add( pallo ); Aliohjelmilla on nimi, parametrit ja palautusarvo. Seuraavassa esimerkki aliohjelmasta, joka yhdistää kaksi merkkijonoa. Palautusarvon tyyppi Nimi Parametrit String Yhdista(String jono1, String jono2) { String yhdiste = jono1 + jono2; Runko return yhdiste; } Aliohjelma koostuu näistä osista: Palautusarvon tyyppi: esimerkissä String. Aliohjelman nimi: esimerkissä Yhdista. Parametrit: esimerkissä String jono1, String jono2. Runko: aaltosulkujen väliin kirjoitettava ohjelmakoodi. Aliohjelmat ovat rakennuspalikoita, joiden avulla ohjelman hallinta helpottuu. 26
Aliohjelmaa voidaan kutsua pääohjelmasta tähän tapaan. // Alustetaan ensin merkkijonot jono1 ja jono2 String jono1 = Antti- ; String jono2 = Jussi ; // Alustetaan merkkijono jonot1ja2 ja // kutsutaan Yhdista()-aliohjelmaa String jonot1ja2 = Yhdista(jono1, jono2); Käydään seuraavaksi läpi aliohjelman osat yksitellen. Palautusarvo ja sen tyyppi Aliohjelmalta odotettavaa vastausta sanotaan aliohjelman palautusarvoksi. Esimerkiksi aliohjelma SummaaLuvut voisi palauttaa kysyjälle syötetyn kokonaisluvun summan. Palautusarvon tyyppi kirjoitetaan aina ennen aliohjelman nimeä, ja se kertoo, minkä tyyppistä tietoa aliohjelmasta saadaan ulos. Esimerkiksi SummaaLuvut-aliohjelman palautusarvon tyyppinä luonnollinen valinta olisi int, tosin periaatteessa double kävisi myös, ja olisi jopa parempi siinä tapauksessa, että aliohjelmalla pitäisi pystyä laskemaan myös desimaalilukuja. Palautusarvoksi on myös mahdollista asettaa erityistyyppi void, jolloin aliohjelma ei palauta mitään. Parametrit Aliohjelman nimen perään sulkujen sisällä kirjoitettu lista kertoo sen parametrit, eli mitä aliohjelmalle syötetään. Jokainen parametri koostuu tyypistä ja nimestä. Nämä parametrit ovat käytettävissä aliohjelmassa samaan tapaan kuin tavalliset muuttujat. Jos aliohjelmalle ei halua määrittää parametreja, voi listan jättää tyhjäksi. Sulut on silti jätettävä: String EiParametreja() { } Aliohjelman runko Merkityksellisin osa aliohjelmassa on sen runko, joka kirjoitetaan aaltosulkujen väliin. Runko voi sisältää mitä tahansa ohjelmointikielen lauseita. 27
Return-lause Jos palautusarvon tyypiksi on määritetty jotain muuta kuin void, on itse palautusarvo palautettava aliohjelmasta erityisellä return-lauseella. Return-lauseen käyttö on yksinkertaista: kirjoita vain return ja palautusarvon tyypin kanssa samaa tyyppiä oleva muuttuja tai lauseke. int Summaa( int a, int b ) { return a + b; } Aliohjelma voi palauttaa muuttujan (kuten yllä olevassa esimerkissä) tai suoraan jonkin arvon, esimerkiksi arvon 2, kun palautusarvon tyyppinä on kokonaisluku (int). int Kakkonen() { return 2; } 28
Ehtolause ja silmukka 29
EHTOLAUSE JA SILMUKKA Yksinkertaisessa ohjelmassa koodirivit käydään läpi yksitellen, suoritetaan toistensa jälkeen, kunnes ohjelma päättyy. Monimutkaisemmissa ohjelmissa tullaan tilanteeseen, missä jokin asia täytyy toistaa useita kertoja esimerkiksi jos haluamme tehdä tuhat palloa yhden sijaan. Tässä meitä auttavat silmukat eli toistolauseet. Toisaalta ohjelma voi olla sellainen, ettei se joka kerralla mene samaa rataa, vaan joissakin tilanteissa voi tulla eteen valintoja. Se, millä tavalla ohjelma etenee, riippuu valinnan tuloksesta. Yksi esimerkkinä valintatilanteesta voisi olla tällainen: Jos pelaaja liikkuu pelikentän rajojen sisäpuolella, hahmo liikkuu vapaasti, mutta seinään törmätessään hahmo pysähtyy. Ehtolause ja sen käyttäminen If-lause on siis rakenne, jonka avulla voidaan tehdä jotakin, mikäli jokin ehto on totta. Vastaavasti jos tämä jokin ehto ei ole totta, tehdään jotain muuta. Esimerkiksi ehto voi olla ulkona sataa (vastaus on aina kyllä tai ei). Jos ulkona sataa ollaan sisällä Muuten mennään ulos pelaamaan jalkapalloa Ehtolausetta tarvitaan esimerkiksi seuraavanlaisessa tilanteessa. Tehtävä: Tee aliohjelma, joka saa parametrina kokonaisluvun. Aliohjelman tulee palauttaa true (tosi), mikäli luku on parillinen, ja vastaavasti false (epätosi), mikäli luku on pariton. Ilman ehtolausetta (jota sanotaan myös valintalauseeksi) pystymme kyllä selvittämään onko luku parillinen vai pariton. Emme kuitenkaan pysty muuttamaan paluuarvoa true:ksi tai false:ksi parillisuuden mukaan. Kun ohjelmassa haluamme tehdä eri asioita riippuen esimerkiksi käyttäjän syötteistä tai aliohjelmien parametreista, tarvitsemme ehtolauseita. Käännetään vielä aiemmin mainittu kokonaislukuesimerkki C#-ohjelmointikielelle. Siis, tehdään aliohjelma, joka palauttaa true tai false sen mukaan, onko luku parillinen vai ei. public bool OnkoLukuParillinen(int luku) { if ( (luku % 2) == 0 ) return true; else return false; } Ensimmäisellä rivillä esitellään aliohjelma, ja suluissa kerrotaan, millaisia parametreja aliohjelma ottaa vastaan. Toisella rivillä otetaan muuttujan luku ja luvun 2 jakojäännös. Jos jakojäännös on 0, niin silloin luku on parillinen, eli palautetaan true. Jos jakojäännös ei mennyt tasan, niin silloin luvun on pakko olla pariton eli palautetaan false. 30
Itse asiassa, koska aliohjelman suoritus päättyy return lauseeseen, voitaisiin else sana jättää kokonaan pois. Else lauseeseenhan mennään ohjelmassa nyt vain siinä tapauksessa, että if ehto ei ollut tosi. Voisimmekin kirjoittaa aliohjelman hieman lyhyemmin seuraavasti: public static bool OnkoLukuParillinen(int luku) { if ( (luku % 2) == 0 ) return true; return false; // Huom! Ei tarvita else-lausetta } Usein if lauseita käytetään aivan liikaa. Tämänkin esimerkin voisi yhtä hyvin kirjoittaa vieläkin lyhyemmin (ei aina selkeämmin kaikkien mielestä) seuraavasti: public bool OnkoLukuParillinen(int luku) { return ( (luku % 2) == 0 ); } Tämä johtuu siitä, että lauseke ( (luku % 2) == 0 ) on true jos luku on parillinen ja muuten false. Saman tien voimme siis palauttaa suoraan tuon lausekkeen arvon ja aliohjelma toimii täysin samalla tavalla. Usein if-lauseita käytetään aivan liikaa. Silmukat Ohjelmoinnissa tulee usein tilanteita, joissa samaa tai lähes samaa asiaa täytyy toistaa ohjelmassa useampia kertoja. Jos haluaisimme esimerkiksi tulostaa MessageDisplayoliolle luvut 1 10, onnistuisi se seuraavasti. MessageDisplay.Add( 1 ); MessageDisplay.Add( 2 ); MessageDisplay.Add( 3 ); MessageDisplay.Add( 4 ); MessageDisplay.Add( 5 ); MessageDisplay.Add( 6 ); MessageDisplay.Add( 7 ); MessageDisplay.Add( 8 ); MessageDisplay.Add( 9 ); MessageDisplay.Add( 10 ); Tuntuu kuitenkin tyhmältä toistaa lähes samanlaista koodia useaan kertaan. Tällöin on järkevämpää käyttää jotain toistorakennetta. Toistorakenteista käytetään usein myös nimitystä silmukat. Esitellään seuraavaksi tärkeimmät toistorakenteet ja otetaan muutama käyttöesimerkki. 31
SILMUKAT Nimi C#:ssa Selitys Käyttöesimerkki while Silmukka, jota toistetaan niin kauan kuin jokin ehto on voimassa. Käytetään, kun ei tarkasti tiedetä etukäteen, montako kertaa silmukkaa toistetaan (tai toistetaanko yhtään kertaa!). while(sana!= ) { } sana = PyydaSanaKayttajalta(); Tulosta(sana); for Silmukka, jota käytetään, kun suoritusten lukumäärä on tiedossa ennakkoon, esimerkiksi tulostetaan kymmenen kertaa Moi for (int i = 0; i < 10; i++) { MessageDisplay.Add( Moi ); } EHTOLAUSE Nimi C#:ssa Selitys Käyttöesimerkki if/else Rakenne, jonka avulla voidaan tehdä jotakin, mikäli jokin ehto on totta. Vastaavasti jos ehto ei ole totta, tehdään jotain muuta. Esimerkiksi ehto voi olla ulkona sataa (vastaus on aina kyllä tai ei) Jos ulkona sataa ollaan sisällä Muuten mennään ulos pelaamaan jalkapalloa // Kysytään luku käyttäjältä, ja tulostetaan sitten viesti int i; i = KysyLukuKayttajalta(); if(i<50) { } Tulosta( Antamasi luku + i + on pienempi kuin 50 ); else { } Tulosta( Antamasi luku + i + on suurempi tai yhtä suuri kuin 50 ); 32
Esimerkki silmukan käytöstä: monta palloa Tehdään aliohjelma, joka luo halutun kokoisen pallon haluttuun paikkaan, ja vielä haluamalla värillä. // TODO: Tarkista koodi. protected override void Begin() { Level.CreateBorder(1.0, true); Gravity = new Vector2D(0, -500); // Painovoiman asettaminen Camera.ZoomToLevel(Level, this); } int i=0; while(i < 100) { int sade = RandomGen.NextInt(5, 20); PhysicsObject pallo = LuoPallo( RandomGen.NextDouble( Level.Left + sade, Level.Right sade ), RandomGen.NextDouble( Level.Bottom + sade, Level.Top sade ), RandomGen.NextColor(), sade ); Add(pallo); i++; } // Luo yksittäisen pallon ja palauttaa sen. PhysicsObject LuoPallo(double x, double y, Color vari, double sade) { PhysicsObject pallo = new PhysicsObject(10, Shapes.CreateCircle(sade)); pallo.color = vari; pallo.x = x; pallo.y = y; return pallo; } 33
Pelin suunnittelu 34
PELIN SUUNNITTELU Suunnittelu on kannattavaa, koska se helpottaa ohjelmointia. Pelin koodaaminen on helppoa, kun tietää, mitä haluaa. Kaikki pelit (ja muut ohjelmat) pitää suunnitella hyvin ennen niiden toteutusta, ettei sitten jälkikäteen tarvi ihmetellä että kuinkas tämä näin huonosti tulikaan tehtyä. Suunnittelun lisäksi myös pelien testaaminen ja kokeileminen on tärkeää. Kokeilemalla selviää, mikä toimii ja suunnitelmiin voi siis tehdä muutoksia. Millainen on mielenkiintoinen peli? Mieti, millaiset pelit ovat hyviä. Miksi ihmiset pelaavat pelejä? Pelien yhteydessä puhutaan usein pelattavuudesta, jonka halutaan olevan mahdollisimman hyvä. Tärkeää on myös pelikokemus. Hyvä peli huomioi seuraavat: Pelin pelaaminen (esim. ongelmat ja haasteet, jotka pelaajan täytyy kohdata voittaakseen) Tarina (esim. juoni ja hahmonkehitys) Pelimekaniikka (esim. pelissä olevien olioiden vuorovaikutus ympäristön kanssa) Käytettävyys (esim. käyttöliittymän ja kontrollien toimivuus) Rajoitukset tällä kurssilla Rajoitukset Jypelin puolesta. Lyhyesti sanottuna 2D (eli 2-ulotteisuus) tarkoittaa sitä, että voi liikkua ylös, alas ja sivuille, mutta ei syvyyssuunnassa. Pelin pitää olla siis 2D-peli, joko sivustapäin kuvattu tai ylhäältäpäin kuvattu peli Samalla koneella pelattava peli (ei verkkopeli) Muita huomioitavia tekijöitä. Kurssilla oman pelin tekemiseen on aikaa varattu n. 12 tuntia. Ajassa ei ehdi kovin paljoa, mutta tietysti kotona voi jatkaa omaa tuotostaan. Kaikki kurssilla käytettävät ohjelmat on ladattavissa netistä kurssin jälkeen. Oma kokemus ohjelmoinnista. Jos on aiemmin ohjelmoinut, niin voi tehdä vaikeampia juttuja. Kannattaa myös huomioida, että jotkin pelit ovat helpompia toteuttaa Jypelin avulla. Esimerkiksi tasohyppelypeli on helpompi tehdä kuin muistipeli. Fysiikka on valmiiksi rakennettu Jypeliin, eli fysiikkapelien tekeminen on helppoa. 35
Millaisia pelejä voin tehdä? Jypelillä voi tehdä joitain pelityyppejä helpommin, kuin toisia. Helppoja pelejä ovat erityisesti valmista fysiikkamoottoria käyttävät pelit. Pelit ovat kaksiulotteisia Windows- ja/tai Xbox 360 -pelejä. Helposti onnistuvat esimerkiksi: Tasohyppely Avaruuslentely Tykki- tai tankkipeli Myös nämä onnistuvat kohtuullisen helposti: Autopeli Taistelupeli Biljardi tai minigolf Matopeli Vaikeampia pelejä ovat: Muistipeli (tarvitaan tietorakenteita) Strategiapelit, kuten tornipuolustus (tekoäly, reitinhaku, pelilogiikka) Riippuu kuitenkin myös aina pelistä ja tekijästä, kuinka vaikeaa tekeminen on. Muista myös, että Jypelin alla oleva XNA mahdollistaa kaikenlaisten pelien tekemisen. Hahmotelma Omassa suunnitelmassa pitää olla vähintään Tekijöiden nimet Pelin nimi Pelialusta: onko peli Windowsille vai Xbox 360:lle (vai molemmille) Pelaajien lukumäärä Pelin taustatarina tai kuvaus pelin teemasta Pelin idea ja tavoitteet Hahmotelma pelistä (kuva tai kuvia paperilla) Toteutuksen suunnitelma: mitä tekisin ja missä järjestyksessä? Millä aikataululla? Lisäksi suunnitelmassa voi esimerkiksi olla (ei pakollisia) Mikä tekee pelistä mielenkiintoisen pelata? Tarvittavat kirjaston osat Näppäimet ja mitä niistä tapahtuu Grafiikka, äänet ja musiikki: millaisia ovat, teenkö itse vai mistä saan? Kenttien hahmotelmia 36
Esimerkkisuunnitelma Avaruuslaskeutuja (LunarLander) -pelistä Tekijä: Janne N. Tietoja pelistä Pelin nimi: Avaruuslaskeutuja Pelialusta: Windows ja Xbox 360 Pelaajien lukumäärä: 1 pelaaja Pelin tarina Ihmiset kartoittavat asutettavia planeettoja. Avaruuslaskeutujan tehtävänä on laskeutua turvallisesti planeetalle, jotta sitä voidaan tutkia. Aluksessa on herkkiä osia, jotka eivät kestä nopeaa vauhtia. Polttoainekin uhkaa nopeasti loppua. Tarvitaan siis tarkkaa aluksen ohjaajaa. Pelin idea ja tavoitteet Pelissä laskeudutaan avaruusaluksella planeetaan pinnalle. Planettan pinta on rosoinen, eikä hyviä laskeutumispaikkoja välttämättä aina ole. Tavoitteena on laskeutua mahdollisimman vähän polttoainetta käyttäen ja hyvässä asennossa planeetan pinnalle. Jos vauhti on liian nopea tai alus on huonossa kulmassa, niin alus räjähtää. Pelissä arvotaan aina uusi planeetan pinta, johon laskeudutaan. 37
Hahmotelma pelistä Toteutuksen suunnitelma Keskiviikko Tekisin ensin kentän, jossa on littana planeetan pinta ja alus. Lisään alukseen ohjauksen. Alusta voi pyörittää oikealle ja vasemmalle sekä ylöspäin. Aluksen sijainti on kentän yläreunassa. Lisätään polttoainemittari. Kun polttoaine loppuu, niin aluksen moottoria ei voi käyttää. Torstai Lisätään aluksen nopeuden ja kulman näyttävät mittarit. Lisätään pistelaskuri, joka laskee pisteet. Pisteet näytetään myös näytöllä. Aluksen pitää räjähtää, jos törmätään liian suurella nopeudella planeettaan. Perjantai Lisätään satunnaisesti luotava maasto. Viimeistellään peli. Jos on aikaa Värinätehosteet ohjaimeen. Useampi pelaaja peliin. Tehdään kilpailumoodi, kumpi laskeutuu nopeammin. 38