Tag: godotengine

Tilemapit ja tietokoneohjaus

(Klikkaa peliruutua aktivoidaksesi näppäimet: nuolet + space)

Vaikka tarkoitukseni oli pienen tilemap-tutkailun jälkeen jatkaa LeMans-kloonin parissa puuhastelua, jumahdin tarkastelemaan TileMap- ja TileSet-noodeja hieman pidemmäksi aikaa.

Pääsyy tähän oli se, että huomasin että tilesetin yksittäisiin ruutuihin voi lisätä törmäyksiä tarkkailevien noodien lisäksi myös NavigationPolygonInstance-noodin. Tämän noodin avulla tilemapiin merkitään ne alueet, joilla pelaaja tai tietokoneen ohjaama hahmo voivat liikkua. NavigationPolygonInstance toimii yhteistyössä Navigation2D-noodin kanssa; Jos Navigation2D-noodilla on lapsielementteinä NavigationPolygonInstance-noodeja, se luo niiden perusteella kartan alueesta, jossa pelaaja ja tietokone voivat liikkua. Navigation2D-noodin get_simple_path()-funktio tarjoaa myös varsin yksinkertaisen tavan hakea reitti etappipisteinä paikasta A paikkaan B:

path = nav.get_simple_path(start_position, goal, false)

Kun reitti – esimerkiksi pelaajan senhetkiseen sijaintiin – on selvillä, onnistuu tietokoneen ohjastaman hahmon liikuttaminen pisteestä toiseen helposti esimerkiksi linear_interpolate()-funktion avulla. GDQuest esittelee tämän tavan liikuskella kattavasti YouTubessa.

Itse halusin tehdä asiat hieman vaikeamman kautta, ja päädyin toteutukseen jossa tietokoneen ohjastama tankki katsoo joka framen kohdalla missä suunnassa seuraava piste on ja kääntää keulaansa tarvittaessa sen suuntaan. Tai jos seuraava piste on vähän tankin takana, voi tankki myös peruuttaa ja kääntyä. Tällä tavoin tehtynä liike näytti omaan silmääni luonnollisemmalta kuin interpolaation avulla tehty liike.

Koska tankkien liikuttelu osoittautui varsin hauskaksi, luulen että rakentelen tähän prototyyppiin vielä mahdollisuuden tuhota tankkeja ampumalla ennen kuin jatkan LeMansin pariin.

Source: https://github.com/mikahimself/tanked

Tilemap-tutkiskelua

(Klikkaa peliruutua aktivoidaksesi näppäimet: nuolet + space)

LeMans-kloonia aloitellessani päädyin tutkailemaan kuinka Godotin sisäänrakennettu tileset-työkalu toimii ja kuinka helppoa sen avulla olisi laatia LeMansin ei-niin-monimutkaiset radat ja tarkkailla törmäyksiä.

Lyhyt vastaus: varsin helppoa. Oheinen, pikku prototyyppi syntyi parissa tunnissa ja siitäkin osa meni tileset-grafiikoiden piirustamiseen ja törmäyslaatikoiden kanssa näpertelyyn . Pääsin samalla muistelemaan kuinka z-indeksit toimivat, ja niiden avulla tankin päälle lankeaa rasterivarjo seinien vieressä. Ehkäpä tässä täytyykin vielä rakennella Tank-klooni ennen LeMansiin keskittymistä…

Source: https://github.com/mikahimself/tanked

Breakout-ish

(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.

Pong, vihdoin ja viimein


(Klikkaa peliruutua aktivoidaksesi näppäimet)

Vaikka ensimmäisen Godot-projektini valmistumisessa kesti yllättävän pitkään, ei syy ollut Godot Enginessä, vaan pikemminkin lämpimissä kesäsäissä. Nyt, ilmojen hieman viilennyttyä, sain vihdoin otettua ensimmäiset kunnon askeleet Godot-maailmaan ja samalla Pong-kloonini valmiiksi.

Päälimmäisenä tästä projektista mieleeni jäi se, miten mukavaa peliä oli askarrella Godotilla ja GDScriptillä, ja miten helposti kaikkiin vastaantulleisiin kysymyksiin löytyi vastaus joko Godotin omasta dokumentaatiosta tai pikaisella googletuksella. Ja miten näppärästi sisäänrakennetun koodieditorin tilalle sai vaihdettua Visual Studio Coden Godot Tools -lisäpalikan avulla.

Itse pelin rakentelin hyvin yksinkertaisessa muodossa. Peliruudun tekstejä lukuunottamatta koko graafinen ulkoasu koostuu suorakulmiosta, eli draw_rect()-funktio tuli projektin aikana hyvin tutuksi. Pelin tapahtumia luodessani tutustuin myös Godotin versioon tarkkailija-mallista, joka perustuu signaaleihin ja ajastimiin. Tutuksi tuli myös Godotin tapa jaotella sisältö scene-objekteihin. Ennen kuin aloittelen seuraavaa projektia, aion lukaista mitä scene-objektien organisoinnista ja käytöstä kerrotaan dokumentaation Best practises -osiossa. Päädyin nimittäin itse – näin jälkikäteen ajateltuna – toteuttamaan mailat vähän typerästi.

Nyt pelissä on yksi maila-scene, josta pelatessa esillä on kaksi ilmentymää. Maila-sceneen on liitetty vain yksi skripti, joka ihmispelaajan ohjastamana ottaa näppäinkomennot vastaan ja tietokoneen ohjaamana ennustaa mihin pallo tulee liikkumaan ja siirtelee mailaa sen mukaan. Fiksumpi tapa olisi ehkäpä ollut luoda yksi scene, joka sisältää ihmis- ja tietokonepelaajan mailojen yhteiset piirteet ja laatia periyttämällä omat maila-scenet tietokoneen ja ihmisen ohjastamille mailoille. No, jatkossa tiedän tämänkin.

Seuraavaksi sitten Breakout.

P.S. HTML5-eksporttien testaaminen käy kätevästi, jos koneelta löytyy Python 3. Siirry komentorivillä export-kansioon ja käynnistä paikallinen palvelin komennolla python -m http.server ja avaa selaimessa osoite http://localhost:8000.

 

Uusi alku, osa neljä

Rakas päiväkirja, tänään päätin – ties kuinka monennettako kertaa – ryhtyä tutustumaan uuteen pelimoottoriin.

Olen viimeisten kymmenen vuoden aikana rakennellut sekalaisen valikoiman pelivirityksiä XNA Game Studiolla, Unitylla, GameMakerilla, Phaserilla ja ties millä. Näitä teoksia on yhdistänyt pikseliestetiikka, 2D-pelimaailmat ja se, että useimmat projektit ovat jääneet auttamattomasti puolitiehen. Oikeastaan vain yksi projekti on nähnyt päivänvalon; Windows Phonelle rakenneltu, Speden Speleistä tuttu reaktiotesti, joka kantoi nimeä Reactionary, ja jota ladattiin Microsoftin puodista lähestulkoon tuhat kertaa.

Vaan onko nyt kaikki toisin? Olenko oppinut aiemmista projekteista jotain ja saanko tällä kertaa jotain aikaiseksi? Se jää nähtäväksi. Tällä kertaa kuitenkin pyrin siihen, että:

  • aloitan huomattavasti pienemmistä ja yksinkertaisemmista projekteista kuin aiemmin
  • en aloita kuutta eri projektia samanaikaisesti
  • kirjaan ylös oppimaani aktiivisesti
  • een ensin keskeneräisen projektin valmiiksi ennen kuin aloitan seuraavaa
  • muistan ylle kirjatut periaatteet vielä huomenna.

Ja koska lupasin juuri aloittaa jostakin pienestä ja yksinkertaisesta projektista, ensimmäinen tuotokseni olkoon Pong.