(Klikkaa peliruutua aktivoidaksesi näppäimet)
Saatuani oman Pong-versioni valmiiksi, uhosin lukevani Godot-dokumentaation Best Practices -osion ennen kuin aloitan seuraavaa projektia. No, se jäi tekemättä, mutta sain kuin sainkin lopulta hieman Breakoutista vaikutteita ottaneen pelini valmiiksi. Mitä uutta opin tällä kertaa?
Suunnittelu
Suunnittelu on tärkeää. Sen opin viime kerrasta, mutta en oikein vieläkään tiennyt mitä kaikkea suunnitellessa tulisi ottaa huomioon. Piirtelin kyllä paperille kaikki palaset, joita kuvittelin pelissä tarvitsevani ja hahmottelin epämääräisten viivojen avulla näiden palasten välisiä suhteita. Yritin myös miettiä ennalta millaisia funktioita saattaisin peliä toteuttaessani tarvita ja hahmottelin mitä ominaisuuksia kussakin palasessa olisi hyvä olla.
Tärkeimmäksi opiksi jäänee kuitenkin se mitä unohdin. En nimittäin yhtään miettinyt ennalta mitä signaaleja eri palasten välillä liikkuu ja milloin ne liikkuvat. Minkä palasen olisi syytä tietää että pallo osui tiileen ja tuhosi sen? Kenelle olisi syytä tiedottaa, että pallo lipui mailaa hipoen ränniin? Mikä objekti hallinnoi tietoa siitä montako palikkaa on vielä tuhottavana ja kuinka kyseinen objekti ilmoittaa siitä muille kiinnostuneille?
Godotin sisäänrakennettu signaalijärjestelmä on varsin mainio, mutta jotta siitä saisi kaiken irti, on syytä miettiä signaalien kulkua ennen kuin ryntää toteuttamaan peliään. Nyt päädyin lisäämään pelirunkooni GameController-skriptin, joka vastaa signaalien ja ajastinten avulla pelin logiikasta. Tosin, koska lisäsin kyseisen scenen pelirunkoon vähän jälkijunassa, muutamat pelin kulkuun vaikuttavat signaalit sijaitsevat muissa palikoissa.
Eli siis note to self, muista signaalit jo suunnitteluvaiheessa ensi kerralla.
Toteutus
Breakout ei pelinä ole erityisen monipuolinen, joten pelin toteuttaminen ei ihmeitä vaatinut. Jotta pallon suuntaa voisi muuttaa sen perusteella mihin kohtaa mailaa se osuu, pallon tyypiksi valikoitui KinematicBody2D. Näin pallon voi aluksi ampua liikkeelle johonkin tiettyyn suuntaan ja liikuttaa sitä move_and_collide-funktion avulla. Jos pallo osuu tiileen tai seinään, se kimpoaa, ja kimpoamissuunnan saa laskettua normaalivektorin ja bounce-funktion avulla. Ja tiileen törmättäessä tietenkin tiili-objekti poistetaan. Jos taas pallo osuu mailaan, sen kimpoamiskulma riippuu siitä mihin kohtaan mailaa pallo osuu. Yksi kätevä tapa toteuttaa tämä selviää HeartBeastin tutoriaalivideosta.
Kentät, eli oikeastaan se montako tiiltä ruudulle piirretään ja millaisen kuvion ne muodostavat, määräytyy taulukkojen avulla. Jokainen kentän rivi on yksi taulukko ja kaikki rivit ovat aina yhden level-taulukon alla. Tämä level-taulukko rullataan läpi kahden sisäkkäisen for-silmukan avulla ja kentän tiilet piirretään ruudulle. Helppoa ja hauskaa.
Suurin osa logiikasta rullaa jo edellä mainitsemassani GameController-skriptissä. Pallo lähettää sille signaalin osuessaan tiileen, ruudun alareunassa oleva alue puolestaan viestii, kun pallo valahtaa mailan ohi ränniin (tämänkin olisi tosin voinut hoitaa pallon sisällä…), ja peliruutua piirtävä Gamescreen-skripti hihkaisee milloin koko uuden kentän sisältö on piirretty ruudulle ja peli voi alkaa. Ja GameController puolestaan viestii kun peli päättyy, kenttä vaihtuu tai pelaaja läpäisee kaikki kentät. Ja kuten sanottua, muutamia signaaleja vaihtuu myös GameControllerin ohitse, mikä on pienimuotoinen suunnitteluvirhe. Mutta parempi onni ensi kerralla.
Seuraavaksi ajattelin pysytellä vuodessa 1976 ja kokeilla kuinka helposti Atarin LeMans syntyy Godotin avulla.