∞ MAZEn idea on yksinkertainen: astu labyrinttiin, kuuntele ja etsi uloskäynti. Kun löydät portaalin, päädyt seuraavaan labyrinttiin. Kierros vaihtuu, mutta matka jatkuu.
Peli rakentuu kolmesta tiedostosta: index.html, style.css ja game.js. HTML antaa pelille rakenteen, CSS ulkoasun ja JavaScript hoitaa labyrintin, liikkumisen, kuvan piirtämisen ja äänet.
Tässä päivityksessä tavoitteena oli saada peli toimimaan myös puhelimella sekä muistamaan saavutettu kierros. Samalla vastaan tuli kaksi opettavaista ongelmaa: näkymätön mobiiliohjain ja satunnaislukugeneraattori, joka muutti väärää muuttujaa.

Labyrintti syntyy kaksiulotteisesta kartasta
Vaikka peli näyttää kolmiulotteiselta, sen maailma on ruudukko. Seinät, käytävät ja uloskäynti ovat kartan soluja.
Näkymä piirretään raycasting-tekniikalla. Pelaajan katsesuunnasta lähetetään laskennallisia säteitä, jotka etsivät seiniä. Seinän etäisyys määrää, kuinka korkeana se piirretään ruudulle. Lähellä oleva seinä täyttää näkymän, kaukana oleva jää matalammaksi.
Portaali tuo harmaaseen labyrinttiin sykkivää valoa. Myös ääni auttaa suunnistamaan: kun pelaaja katsoo uloskäynnin suuntaan, kuuluu vihje. Suunnan tarkentuessa signaali tihenee. Se kertoo uloskäynnin suunnan, mutta ei paljasta reittiä seinien läpi.
Puhelin tarvitsee oman tavan liikkua
Tietokoneella ohjaus perustuu WASD-näppäimiin ja hiireen. Pointer lock lukitsee hiiren pelin käyttöön, jolloin katsesuuntaa voi kääntää ilman, että osoitin karkaa ikkunan reunaan.
Puhelimella sama ratkaisu ei sovellu ohjauksen perustaksi. Siksi mobiiliversiossa peli käynnistyy kosketuksella ilman hiiren lukitusta.
Vasemmassa alakulmassa oleva virtuaalijoystick liikuttaa pelaajaa eteen, taakse ja sivuille. Näyttöä pyyhkäisemällä käännetään katsetta. Liikkuminen ja katsominen toimivat eri kosketuksilla, joten molempia voi käyttää samanaikaisesti.
Tärkeä korjaus löytyi liikkeen laskentajärjestyksestä. Joystickin tuottama liike täytyy lisätä ennen seinätarkistuksia:
Näppäimistö ja joystick → liikesuunta → seinätarkistus → pelaajan uusi sijainti.
Jos joystickin vaikutus lasketaan vasta pelaajan siirtämisen jälkeen, ohjain voi reagoida kosketukseen ilman, että pelaaja liikkuu lainkaan.
Miksi ohjain ei näkynyt?
Ensimmäisen korjauskierroksen jälkeen palaute oli lyhyt: ”ei näy mobiiliohjaimia”.
Ohjainten näkyvyys oli sidottu liian tiukasti laitteen tunnistukseen ja pelin käynnissäoloon. Lopulliseen korjaukseen lisättiin useampi tapa tunnistaa mobiilikäyttö: kosketusominaisuudet, osoittimen tyyppi ja näytön leveys.
Lisäksi aloitusruutuun tuli PLAY WITH TOUCH CONTROLS -painike. Sen avulla pelaaja voi valita kosketusohjauksen itse, vaikka automaattinen tunnistus ei osuisi oikeaan.
Myös tyylitiedosto piti rakentaa kokonaiseksi. Pelkkä joystickin testityyli ei riitä: mukana täytyy olla pelinäkymän, aloitusruudun, HUDin, ilmoitusten ja painikkeiden ulkoasu.
CSS- ja JavaScript-viittauksiin lisättiin samalla versionumerot, jotta selain hakisi päivitetyt tiedostot vanhojen välimuistikopioiden sijaan.
Seuraava palaute oli jo toisenlainen: ”toimii! tattis!”
Sama seed, sama labyrintti
Tallennus vaatii, että labyrintti voidaan luoda uudelleen samanlaisena. Tätä varten pelillä on seed eli luku, josta labyrintin muodostaminen alkaa.
Alkuperäisessä rakenteessa satunnaislukugeneraatt
15.50
∞ MAZE – loputon labyrintti ja kadonneen joystickin arvoitus
∞ MAZE on selaimessa toimiva ensimmäisen persoonan labyrinttipeli. Sen idea on yksinkertainen: kulje käytäviä, kuuntele ja löydä uloskäynti. Perillä odottaa uusi labyrintti.
Projektin kiinnostavin vaihe alkoi, kun tietokoneella toimivaan peliin lisättiin mobiiliohjaus. Vasempaan alakulmaan piti ilmestyä virtuaalinen joystick. Mutta puhelimella sitä ei näkynyt.
Siitä alkoi korjauskierros, jossa käytiin läpi käyttöliittymä, liikkeen laskenta, tallennus ja satunnaislukugeneraattori.
Kolme tiedostoa, kokonainen peli
Peli rakentuu kolmesta tiedostosta:
- index.html sisältää pelinäkymän, aloitusruudun, tilatiedot ja ohjainten rakenteen.
- style.css määrittää ulkoasun ja elementtien sijoittelun.
- game.js hoitaa labyrintin generoinnin, liikkumisen, piirtämisen, äänet ja tallennuksen.
Kolmiulotteiselta näyttävä näkymä syntyy raycasting-tekniikalla. Labyrintti on pohjimmiltaan kaksiulotteinen ruudukko, johon pelaajan katsesuunnasta lähetetään laskennallisia säteitä. Seinän etäisyys määrää, kuinka korkeana seinäpalkki piirretään ruudulle.
Uloskäyntinä toimii hohtava portaali. Myös ääni auttaa suunnistamaan: kun katsesuunta osuu kohti uloskäyntiä, peli antaa äänivihjeen. Tarkempi suunta tihentää merkkiääntä. Näin kuunteleminen kuuluu itse pelaamiseen.
Miksi joystick ei näkynyt?
Korjauksen aikana selvisi, ettei kyse ollut vain yhdestä puuttuvasta CSS-rivistä.
Tyylitiedostoon oli päätynyt pelkkä joystickin testityyli. Kokonaisen pelin ulkoasu piti palauttaa samaan tiedostoon niin, että aloitusruutu, tilatiedot, tähtäin ja mobiiliohjaimet toimivat yhdessä.
Myös ohjainten näkyvyys oli liian vahvasti automaattisen laitetunnistuksen varassa. Ensimmäinen koottu versio ei vieläkään näyttänyt ohjaimia käyttäjän puhelimella, vaikka pelilogiikan testit menivät läpi.
Lopulliseen korjaukseen lisättiin useampi tapa tunnistaa mobiilikäyttö: kosketusominaisuudet, selaimen ilmoittama osoitintyyppi ja pieni näyttö. Aloitusruutuun tuli lisäksi PLAY WITH TOUCH CONTROLS -painike.
Painikkeella pelaaja voi ottaa kosketusohjauksen käyttöön itse. Selain ei siis yksin päätä, millä tavalla peliä saa pelata.
Samalla CSS- ja JavaScript-tiedostojen osoitteisiin lisättiin versionumerot, jotta selain hakee päivitetyt tiedostot vanhojen välimuistikopioiden sijaan.
Ohjauksen pitää vaikuttaa ennen seinätarkistusta
Joystickin näkyminen ratkaisee vasta puolet ongelmasta. Sen pitää myös liikuttaa pelaajaa.
Pelissä liike käsitellään tässä järjestyksessä:
- Luetaan näppäimistön ja joystickin syötteet.
- Lasketaan pelaajan ehdotettu liike.
- Tarkistetaan, estävätkö seinät liikkumisen.
- Päivitetään pelaajan sijainti.
- Tarkistetaan, saavuttiko pelaaja portaalin.
Jos joystickin liike lisätään vasta seinätarkistusten ja sijainnin päivityksen jälkeen, se ei vaikuta kyseisen päivityskierroksen toteutuneeseen liikkeeseen.
Korjatussa versiossa näppäimistö ja joystick syöttävät liikkeensä samoihin laskelmiin ennen törmäystarkistuksia. Silloin molempiin ohjaustapoihin pätevät samat seinät ja samat liikkumissäännöt.
Mobiililla vasen joystick hoitaa liikkumisen ja pelinäkymän pyyhkäisy kääntää katsetta. Tietokoneella säilyvät WASD ja hiiri.
Puhelin ei tarvitse hiiren lukitusta
Tietokoneella hiiren lukitus eli pointer lock mahdollistaa jatkuvan katsesuunnan muuttamisen. Hiiren osoitin ei pysähdy selainikkunan reunaan.
Kosketusohjaus ei tarvitse tätä toimintoa. Siksi mobiililla pelin käynnistäminen irrotettiin hiiren lukituksesta: aloitusruudun voi sulkea kosketuksella ja pelaamisen aloittaa suoraan.
Myös ohjaimen vapautuminen piti huomioida. Kun sormi nostetaan tai kosketus keskeytyy, joystickin liike nollataan. Samoin ohjaussyötteet tyhjennetään pelin menettäessä aktiivisuuden. Näin pelaaja ei jatka kävelyä sen jälkeen, kun ohjaus on jo lopetettu.
Sama seed, sama labyrintti
Tallennuksessa tuli vastaan toinen tärkeä yksityiskohta: satunnaisuuden pitää olla toistettavaa.
Labyrintti generoidaan siemenluvusta eli seedistä. Kun sama siemen annetaan samalle generaattorille, tuloksena pitää olla sama labyrintti.
Tätä varten tarvitaan kaksi erillistä muuttujaa:
- worldSeed tunnistaa nykyisen labyrintin ja pysyy vakaana sen generoinnin aikana.
- randomState on satunnaislukugeneraattorin muuttuva sisäinen tila.
Jokaisen labyrintin generointi alkaa asettamalla randomState = worldSeed. Sen jälkeen satunnaislukujen tuottaminen muuttaa vain generaattorin sisäistä tilaa.
Erottelu on pieni, mutta tallennuksen kannalta ratkaiseva. Jos myös tallennettavaksi tarkoitettu siemen muuttuisi generoinnin aikana, latauksessa ei enää aloitettaisi samasta lähtöarvosta.
Portaali on myös tallennuspiste
∞ MAZEn tallennus toimii labyrinttikohtaisena tarkistuspisteenä.
Kun pelaaja saavuttaa portaalin, peli siirtyy seuraavaan LOOPiin ja tallentaa sen numeron sekä siemenen selaimen localStorage-muistiin. Onnistumisesta kertoo PROGRESS SAVED.
Kun peli avataan uudelleen, tallennettu labyrintti muodostetaan samasta siemenestä. Pelaaja aloittaa sen lähtöpisteestä, ja PROGRESS LOADED kertoo latauksesta.
Kesken labyrintin saavutettua sijaintia ei tallenneta. Saavutettu LOOP säilyy, mutta sen reitti pitää kulkea uudelleen. Aloitusruudun RESET PROGRESS -painikkeella etenemisen voi nollata vahvistuksen jälkeen.
Testit ja puhelin täydentävät toisiaan
Korjatusta koodista tarkistettiin muun muassa siemenen toistettavuus, joystickin vaikutus liikkeeseen, seinien estämä kulku, portaalin käynnistämä tallennus sekä tallennuksen lataaminen ja nollaaminen.
Silti ensimmäisen toimituksen jälkeen palaute oli lyhyt:
ei näy mobiiliohjaimia
Se oli tärkeä muistutus testauksen rajoista. Pelilogiikan toimivuus ei vielä todista, että käyttöliittymä näkyy oikein käyttäjän selaimessa. Näkyvyysehdot, laitetunnistus ja ladattujen tiedostojen versiot vaikuttavat lopputulokseen yhtä lailla.
Seuraavan korjauksen jälkeen tuli odotettu vastaus:
toimii! tattis!
Lopulta projektin tärkein parannus oli varsin käytännöllinen: peli sai yhtenäiset tiedostot, eri ohjaustavat käyttävät samaa liikelogiikkaa ja pelaaja voi itse ottaa kosketusohjauksen käyttöön.
Nyt joystick löytyy. Uloskäynnin etsiminen jää pelaajalle.



