Casio Loopy Pahkasika Galloping Ghost TIETOKONEKULTTUURIN ERIKOISLEHTI 12. VUOSIKERTA 2024.3 S K R O L L I . F I 9 , 9 € 2 2 4 .3 LIITTEENÄ PELILEHTI RASPBERRY PI PICO Retrokoneilun linkkuveitsi DEMOPARTYT Rakkaudesta lajiin NOKIAN PELIT joita ei julkaistu Taskutietokoneet ennen kännykkäaikaa ÄLYPÖNTTÖ – tirppatiirailua ATARI SUOMESSA – aina ei voi voittaa FREECIV
Nollanumeron ilmestymisestä tulee lokakuussa kuluneeksi 12 vuotta, mikä ei ole lainkaan vähäinen määrä printtijulkaisulle, joka syntyi kun printin piti olla jo täysin kuollut media. Koko porukka tuli Assyiltä kotiin fyysisesti väsyneenä mutta henkisesti latautuneena: työmme koetaan tärkeäksi, lehdelle on tarvetta ja sitä ollaan valmiita tukemaan. Tänä vuonna Assyt olivat meille harvinaisen onnistunut tapahtuma. Syitä optimismiin siis riittää, mutta tietenkin on muistettava myös tietyt realiteetit jatkuvuuden turvaamisen suhteen. 2024.3 2. Tämän vuoksi joudumme pitkästä aikaa nostamaan tilausten ja irtonumeroiden hintaa ensi vuodelle, jotta selviämme kohonneesta kulutasosta. Imemme yhteisöstä itseemme virtaa, joka auttaa kantamaan pitkän pimeän jakson yli, niinäkin hetkinä kun koko harrastustoiminnan mielekkyyden kyseenalaistaa. Nykyisin on toki muodikasta kerätä palautetta aivan kaikesta, vähintään tuulikaapissa seisovien hymynaamojen kautta, mutta mikään ei edelleenkään voita kasvotusten saatua kommenttia – eikä mikään ilahduta niin kuin otsikon mukainen spontaani lausahdus. Skrolli on ohittanut alkuinnostuksen, joka auttoi silloin, kun ensimmäisiä numeroita puskettiin kasaan enemmän tai vähemmän yrityksen ja erehdyksen kautta, usein keskellä yötä. Vuoden 2025 tilaukset ovatkin jo tätä kirjoittaessani hankittavissa kaupastamme osoitteessa tilaaskrolli.fi. Kiitos siitä. Raporttia tapahtumasta on luvassa nelosnumerossa. Taantuman partaalla laahustava taloustilanne on purrut myös ITalaan, minkä seurauksena mainosmyyntimme on ottanut osumaa parhaisiin vuosiin verrattuna. Jo fysiologisten tosiasioiden vuoksi juuri me joudumme jossain vaiheessa sen tekemisen lopettamaan, mutta samalla otamme avosylin vastaan kaikki lehden tekemisestä kiinnostuneet, jotta jatkuvuus on turvattu. Kiitos siitä kaikille teille, jotka pidätte tilauksenne voimassa vuodesta toiseen. SKROLLI – Tietokonekulttuurin erikoislehti PÄÄKIRJOITUS ”Ettehän vain ikinä lopeta tätä lehteä!” Tilaukset Yhteydenotot Lukijakanavat Mediamyynti Kotisivut Päätoimittaja Toimituspäällikkö, taitto Digipäällikkö Kuvatoimittaja Asiantuntijatoimittaja Talous Julkaisija Painopaikka tilaaskrolli.fi toimitus@skrolli.fi skrolli.fi/lukijakanavat myynti@skrolli.fi skrolli.fi Mikko Heinonen Manu Pärssinen Toni Kuokkanen Mitol Meerna Jarno N. Kauppinen, Tea Kauppinen, Ronja Koistinen, Valhe Kouneli, Miia Oinonen, Mikko Rasa, Tommi Uschanov, Susanna Viljanmaa Haldric, Antti Hannula, Juha Hollanti, Jari Jalonen, Ville Kankainen, Emma Kantanen, Markus Koskela, Pasi Kovanen, Kroko24, L1meE, Marko Latvanen, Miikka Lehtonen, Anni Murtosaari, Jarkko Nääs, Harri Pölönen, Janne Rautiainen, Kimmo Rinta-Pollari, Jari Sihvola, Risto Sipiläinen, Matilda Smeds, Timo Soilamaa, Janne Suni, Mikko Torvinen, Mikko Tuomela, Tapio / Uncultured Games, wieder_fi Susanna Viljanmaa Mikko Heinonen päätoimittaja Painotuotteet 1234 5678 Y M PÄ RISTÖMER KK I MIL JÖMÄRK T Painotuotteet 4041-0209 AUDITOITU TUOTE NEUTRAALI CO 2 PunaMu sta S krolli käy joka kesä Assembly Summer -tapahtumassa latautumassa. Kun vielä lehden perustaja ja ensimmäinen päätoimittajamme Ville-Matias Heikkilä pokkasi ykköspalkinnon Oldskool Demossa ja Skrolli Partyn kutsu esitettiin lauantai-illan demokompossa paraatipaikalla, näkyvyys oli hyvällä tasolla. Jokaisessa projektissa on erilaisia vaiheita. Saimme huippumäärän uusia tilaajia (tervetuloa!), kontakteja ja myös uusia juttuideoita. Avasimme myös vuoden 2025 tilaukset etukäteen, jotta saisimme tapahtumaan sopivasti myytävää, ja nekin otettiin vastaan oikein hyvin. Alanko Anssi Kolehmainen Skrolli ry PunaMusta Oy, Tampere ISSN 2323-8992 (painettu) ISSN 2323-900X (verkkojulkaisu) Toimittajat Tämän numeron avustajat Kansikuva Miika Auvinen, Jari Jaanto, Tapani Joelsson, Heikki Jungman, Jukka O. Skrolli Party muuten järjestetään juuri tämän lehden ilmestymisen aikoihin, ja sen osallistujalista näyttää kiitettävän täydeltä. Paras tapa varmistaa mieluisan asian jatkuminen kun on joko a) tukea sitä rahallisesti tai b) osallistua itse sen tekemiseen. Saa toki tehdä molempiakin. Assembly-kävijän toteamus oli luonnollisesti tarkoitettu kehuksi ja rohkaisuksi, mutta voihan sen ajatella olevan vaatimuskin: lehteä ei siis saisi lopettaa koskaan. Se on selvinnyt siitä, kun perustajat ja ensimmäiset aktiivit jatkavat muihin haasteisiin, ja muuttunut vähän jokaisen uuden päätoimittajansa myötä pitäen kuitenkin mielessään syntysanansa. Pieni lohtu sentään on, että syyskuun alusta voimaan astunut korkeampi arvonlisäveroprosentti ei koske lehtiä
74 Retrompaa romppausta JOKin pelipalsta luolastojen lumoissa. 86 Oikaisuja ja palautetta Sekä Pythonin siivousta. READ! Assembly Summer 2024:n satoa – demokilpailun voittaja Gray Marchers: The Message, 1k-voittaja Fulcrum: Building from Bedrock 1K ja Oldskool-demokisan voittaja PWP: Transcend the Game. Lue lisää demopartyistä alkaen sivulta 76.. 15 Sarjakuva Turrikaanien yössä Times of Lore. 78 Assembly Summer 2024 Tapaamisia ja toivoa. 50 Atari-aikakirjat Ensimmäisessä osassa 2600:n menestys Suomessa. 22 Amiga ja Apollo FPGA Kesäheilana jäälohhari. 56 Opi pelaamaan FreeCiviä Näillä ohjeilla valloittamaan maailmaa. 2024.3 0% 120% PRECALC DONE. 89 – 119 Retro Rewind Videopelilehti Skrollin liitteenä. 9 Kielet ruosteessa Kitaran viritys Rustilla jatkuu. 42 Ummikko ja elektroniikka Mitä jos rakentaisi piirturin itse. 26 Mustamäen piraatit Muistoja kopioiduista ohjelmakokoelmista. 16 Aikasarja Delta-aikamatka Tetriksen koodiin. 48 Tee oma Wiki-Chatbot Chatbot oppii puhumaan. 76 Assemblyt monelta kantilta Neljä roolia tietokokonetapahtumassa. 82 Alternative Party Pitkä tauko, mutta taas mennään. 33 Älypönttö omenapuussa Tirppojen tiirailua teknisemmällä tavalla. 68 Jälkidigitaalista pelaamista Blood Bowl on ilmiö itsekin. 64 Muovisoittimet ulos komerosta! Vielä riittää rytmipelattavaa. 36 Kolme täytettä vadelmapiirakkaan Raspberry Pi Pico on retroharrastajan ystävä. 2 Pääkirjoitus 4 Nokian salatut peliprojektit Paljon tehtiin myös kulissien takana. 12 Hitaasti hyvä tulee Slowly hurmaa hitaalla viestinnällä. 66 Kuisketta sammaleen suunnalta Näin tehtiin retroroolipeli ANSI-grafiikalla. READY. 24 Kolumni: C64 vastaan SV-328 Konesota ei koskaan kuole. 20 Ei näin! Mikko ei osta enää samaa peliä uudelleen. 80 Zoo, rakkaudesta lajiin C64-harrastajien omat juhlat. 72 JOKstoriaa XXX Bittiavaruuteen ammuttua rahaa. 28 BASIC taskussa Sharpin ja Epsonin taskutietokoneet
Kulissien takana puhelinjätti hääri esimerkiksi Doomin, Larryn ja fyysistä ympäristöä hyödyntävien pelien parissa, mikä kertoo yhtiön kiinnostuksen peleihin olleen laaja-alaista ja kunnianhimoista. Pelitutkimusyksikköä kiinnostivat myös kiihtyvyysanturit. Skrollissa 2024.2 julkaistu sarjan ensimmäinen osa käsitteli yhtiön teollisten muotoilijoiden visioimia pelilaitteita. Tutkijat kehittivät esimerkiksi etäisyysantureita hyödyntävän moninpelikonseptin nimeltä Pirates. Yhdessä Göteborgin yliopiston Interactive Instituten kanssa kehitettyä peliä demottiin akateemisissa konferensseissa vuosina 2000 ja 2001. Teksti: Heikki Jungman Kuvankäsittely (aloituskuva): Manu Pärssinen Nokia Research Centerin varhaiset konseptipelit T odennäköisesti Matopelin suosion siivittämänä Nokian tutkimuskeskukseen perustettiin vuonna 1998 kokonaan peleihin ja pelaamiseen keskittyvä pieni tutkimusryhmä. 2024.3 4. Näiden lisäksi Nokia rahoitti monenlaista peleihin liittyvää toimintaa, joka ei koskaan sellaisenaan päätynyt kuluttajien luureihin. Pelitutkimusyksikössä tehtiin myös esimerkiksi pienimuotoista 3D-pelimoottorien kehitystä ja tutkittiin kosketusnäyttöjen pelikäyttöä. Siinä pelaajat kävivät kauppaa ja meritaisteluita tuomalla kommunikaattorinsa fyysisesti lähelle toisiaan. Näitä hyödyntämään kehitettiin muunnelma Scorched Earth -pelistä (1991), jossa ammus lähetettiin liikkeelle kättä heilauttamalla. Sen tehtäväksi annettiin kehittää pelikonsepteja, jotka olisi mahdollista kaupallistaa 3–10 vuoden kuluessa. Skrolli julkaisee kolmiosaisen juttusarjan Nokian pelaamiseen liittyvistä hankkeista, jotka ovat pysyneet viime vuosiin asti salaisina. Sensorien kutistuminen puhelimen sisälle mahtuvaksi kulutuselektroniikaksi oli vielä vuosien päässä. 1990-luvun viimeisinä vuosina Nokiassa oltiin kiinnostuneita päälle puettavasta teknologiasta, joten pelitutkimustiimi kehitti ensimmäisinä projekteinaan prototyypin Nokian salaisuuksia avautuu Nokia Mobile Phonesin uumenissa tapahtui paljon kokeiluja, konseptointia ja tuotekehitystä, josta kännykkäjätin ulkopuolella ei kuultu mitään. Kolmannessa osassa selvitetään N-Gage -pelipuhelimen parjatun Sidetalking-ratkaisun juuria. Staattiset hotspotit puolestaan näkyivät pelimaailmassa saarina. Kun Nokian oman kännykkäliiketoiminnan päättymisestä on kulunut jo vuosikymmen, tietoa näistä projekteista tihkuu julkisuuteen yhä enemmän. Toisessa pelissä puhelinta käytettiin taikasauvana, jolla piirrettiin ilmaan loitsujen vaatimat maagiset symbolit. HISTORIA NOKIAN SALATUT PELIPROJEKTIT Nokia on julkaissut historiansa aikana kymmeniä pelejä, ja yhtiön alustojen kautta niitä on julkaistu lukemattomia lisää. Näiden prototyyppipelien käyttämät sensorit olivat vielä suuria mötiköitä, jotka kiinnitettiin erikseen puhelimeen
Kuvat: Hannu Viitala ja Markus Mertama. Pelaaja käyttää vihjettä suorittaakseen tehtävän pelin sisällä ja voittaa palkinnoksi leffaliput uusimman Tähtien sodan ensi-iltaan. Doomin saaminen pyörimään Starshipillä ei kuitenkaan ollut ihan helppo juttu. Pelaajat kantoivat laserpyssyjä, niiden valon rekisteröiviä liivejä, GPS-antennia ja kypärää, jonka näyttöön piirtyi yksinkertaisia ikoneja – sekä selkäreppua, johon oli pakattu pelin vaatima laskentateho. Viitala ja Mertama jatkoivat mobiilin Doomin parissa ja julkaisivat vielä C2Doom-version, joka toimii S60-, S80ja S90-sarjan puhelimissa. 5. Seuraavaksi Viitalalta ja Mertamalta pyydettiin, että myös Doomin äänien pitäisi toimia Starshipissä. Viitala porttasi Symbianille vapaa-ajallaan SDL-ohjelmistokirjaston. Yhdessä he julkaisivat pelin avoimen lähdekoodin lisenssillä vuonna 2001. Lisäksi tavallista puhelinta suurempi muistimäärä, leveä värinäyttö ja QWERTY-näppäimistö tekivät kommunikaattorista käyvän mobiilin pelilaitteen. Myös co-operativeja death match-moninpeli Bluetoothin yli onnistuvat. PC:llä Doomin minimivaatimus oli neljä megatavua. Puhelinjätti toivoi, että PC:ltä tuttu räiskintäklassikko tekisi vaikutuksen pelialan ammattilaisiin, sillä N-Gagesta rakennettiin pelilaitetta nimenomaan hardcore-pelaajille. C2Doomissa on muun muassa ääniefektit, musiikit sekä tuki näppäimistön konfiguroinnille ja kosketusnäytölle. ”Sanoin, että jos teillä on 1,7 megatavua muistia bootin jälkeen, niin ette te onnistu tekemään tähän mitään muitakaan pelejä”, Mertama kertoo. Tämän jälkeen N-Gagen Doomiinkin saatiin äänet. Kuva: Aalto-yliopiston arkisto / Nokia Design Archive. CDoom ja C2Doom. Doom ja Nokia Miten klassikkoräiskintä Doom liittyy Nokiaan. Vuonna 2001 julkaistu kommunikaattori oli tuohon aikaan näytön kuvasuhteen puolesta N-Gagea toimivampi pelikone, vaikkakin hyvin hintava sellainen. Skrolli 2024.2:ssa on kerrottu Nokian teollisten muotoilijoiden samanaikaisista visioista koskien sitä, miltä tämä vielä kömpelö teknologia tulisi näyttämään vuonna 2005. Mertama muistelee vastanneen, että se ei onnistuisi. Kännykkäjätin rahoittaman Doom-version juuret ovat Nokia 9210 Communicatorin kehityksessä. Starshipistä tuli sittemmin N-Gage-pelipuhelin. Puhelimessa oli neljä megatavua muistia, mistä käynnistyksen jälkeen vapaana oli vain 1,7 Mt. Pelaajan kommunikaattori poimii peliin liittyvän vihjeen aikakauslehden mainokseen piilotetulta sirulta. CDoom teki Nokiassa sen verran suuren vaikutuksen, että kun Entertainment and Media -yksikössä lyötiin lukkoon suunnitelma pelibisnekseen hyppäämisestä omalla pelilaitteella, Viitalaa ja Mertamaa pyydettiin konsultoimaan peliasioissa. Nokian teollisen muotoilun osaston vuonna 1999 tekemä havainnekuva mobiililaitteen mahdollistamasta fyysistä ympäristöä hyödyntävästä eli pervasiivisesta pelaamisesta. N-Gagella pyörinyttä Doomia ei koskaan julkaistu kaupallisesti, mutta sitä käytettiin esittelemään pelipuhelimen potentiaalia pelijulkaisijoille ja yhteistyökumppaneille suljettujen ovien takana. Markus Mertama muistelee pelin toimimaan saamisen vaatineen melkoista kikkailua. Mertama sai kuvaruudun vaihdot toimimaan rakentamalla niitä varten swappauksen, jossa kentän loppunäkymä kirjoitettiin tiedostoon. Nokia maksoi kaksikolle palkkion siitä, että he sovittaisivat CDoomin Starship-puhelinprototyypillä toimivaksi. ”Mutta meitä ei uskottu silloin, koska muisti maksaa rahaa.” Mertama uskoo, että N-Gagen muistimäärä nostettiin lopulta kahdeksaan megatavuun sen jälkeen, kun Tomb Raiderin porttaajat vaativat, että muistia täytyy olla enemmän. Doomin ”romahtavat” näkymänvaihdot vaativat kahden eri näkymän tallentamista muistiin yhtä aikaa, mikä oli Starshipillä mahdotonta. oikeassa tilassa pelattavasta lipunryöstön ja ammuntapelin yhdistelmästä. Monellakin tavalla, sillä Nokia käytti alkuperäisen Doomin kehittäjiin kuulunutta John Romeroa N-Gage-pelipuhelimensa mainosmiehenä, sekä myös rahoitti pelin mobiiliversion kehitystä Suomessa. 9210 Communicator -kehitysprojektissa työskennellyt ohjelmistokehittäjä Hannu Viitala pohti harrastusmielessä millaisia pelejä kehittyneemmälle kommunikaattorille voisi tehdä. Tässä toisen sukupolven kommunikaattorissa oli ensimmäisenä nokialaisena Symbian-käyttöjärjestelmä joka mahdollisti sen, että kuka tahansa pystyi luomaan siihen ohjelmistoja. Sam Lantinga taas oli rakentanut sen päälle vapaan lähdekoodin SDL Doom -projektin, ja Viitala innostui haasteesta saada Doom toimimaan kommunikaattorilla. Syntyi CDoom, jonka viimeistelyyn Viitala pyysi apua tiimikaveriltaan Markus Mertamalta
Forgotten Frontissa ohjattavia sotilaita olisi vain muutamia, jotta pelaajaa saataisiin sitoutumaan vahvemmin hahmoihin. Leisure Suit Larry Pocket Party -nimen saanut peli kuitenkin epäonnistui pahasti ja peruttiin vähin äänin, vaikka se oli pitkälle kehitetty ja teknisesti korkeatasoinen. Flopannut pelibrändi teki täyskäännöksen, kun se vuoden 2005 E3-messuilla uudelleenbrändättiin kaikille sopivaksi kasuaalipelaamiseksi. Niiden innoittamina RedLynxillä tehtiin konsepti Pathway to Glory 2:sta uudelle pelilaitteelle. Pelin historiaa tutkineen Michael Fitzmayerin mukaan summa oli lähes kaksi kertaa niin paljon kuin Sierra käytti Leisure Suit Larry: Love for Sail! -pelin (1996) kehittämiseen. Kuvat: Antti Ilvessuo. Nokia hankki oikeudet pelisarjan mobiiliversioon, jonka oli tarkoitus ilmestyä N-Gagelle loppuvuodesta 2004. Siinä missä perinteiset Larry-pelit ovat pikkutuhmia seikkailupelejä, joissa Larry yrittää ja yrittää, mutta harvoin saa kaipaamaansa, oli Nokian versio kokoelma rivoja minipelejä, jossa yhdyntään ryhdytään vähän väliä. Nokia oli esitellyt joillekin yhteistyökumppaneilleen suunnitelmiaan ja konseptikuvia täysiverisestä mobiilista pelikonsolista GD2:sta. Samasta mielenmaisemasta kertoo myös esimerkiksi minipeli, jossa tavoite on paljastaa tarjoilijattaren rinnat viskomalla juomarahoja tämän topin sisälle. Ei ole sattumaa, että Nokia oli kiinnostunut Larrysta, sillä N-Gagen markkinoinnissa seksi – tai pikemminkin seksismi – oli merkittävässä osassa (ks. Se paitsi kehitti omia viihdetuotteitaan, myös lisensoi oikeuksia tunnettuihin brändeihin. Skrolli 2023.4). Pelin tehtävät eivät olisi pelkkää taistelua, vaan liittyisivät sotilaan jokapäiväiseen elämään ja selviytymiseen, kuten esimerkiksi sian varastamiseen oman korsun väelle. Hahmoissa esiin oli tarkoitus tuoda esimerkiksi ikääntymistä, kulumista ja tunteita. 2024.3 6. Kunnian polun jatko-osat Pathway to Glory oli N-Gagen lippulaivapeli sekä suurin yksittäinen pelisatsaus Nokialta. Forgotten Front -nimellä kulkeneessa luonnostelmassa oli sotapelien valtavirrasta mielenkiintoisesti poikkeava näkökulma. Käytännössä mitään konkreettista ei Pathway to Glory 2:n eteen päästy tekemään, sillä Nokia ei koskaan julkaissut ohjelmistokehitystyökaluja GD2:een. Forgotten Front ei koskaan edennyt ajatuksia pidemmälle, mikä on sääli. Törkyiset taskubileet Suuruutensa päivinä Nokia ei ollut ainoastaan jättimäinen puhelinvalmistaja vaan myös viihdeyhtiö. Yksi näistä oli vuodesta 1987 lähtien Leisure Suit Larry -peleissä seikkaillut naistenmies Larry Laffer. Lopulta Nokialla kuitenkin nähtiin Pocket Partyn menneen liian pitkälle. Ensimmäisessä kamerapuhelin Nokia 3650:lle kehitetyssä prototyypissä sotivat isopäiset hahmot muistuttavat RedLynxin tuolloin tekemien TV-pelien estetiikkaa. Samoihin aikoihin räikeä seksismi haluttiin pois myös N-Gagen markkinoinnista. Pathway to Glorystä tehtiin kaksi prototyyppiä, ennen kuin Nokia ja RedLynx solmivat sopimuksen kaupallisen sotapelin kehittämisestä. RedLynxin perustajiin kuuluvan Antti Ilvessuon arkiston uumenista löytynyt dokumentti osoittaa, että Pathway to Glorylle pohdittiin myös ensimmäiseen maailmansotaan sijoittuvaa sivupolkua. Pelistä oli tehty yksinkertaisesti liian mauton, eikä sitä voinut julkaista. Tehtävistä saataviksi palkinnoiksi luonnosteltiin parempi paikka korsussa, paremmat tiivisteet kaasunaamariin, erilaiset saappaat tai parempi tiedusteluasema. Se kasvatti pelin kehittäneen RedLynxin muutamasta työntekijästä kolmen tiimin pelistudioksi. Kolme tiimiä mahdollisti useamman projektin samanaikaisen edistämisen. Pelin kehittäjien myöhemmin vuotamassa täysin pelattavassa versiossa pelaaja pääsee harrastamaan seksiä N-Gagen numeronappeja rämpyttämällä – kunhan on ensin ostanut muutamalla dollarilla huutokaupasta haluamansa opiskelijatytön palvelukset. Sen esittämä henkilökohtainen näkökulma on omaperäinen ja olisi ollut perinteistä sotastrategiaa paremmin sovitettavissa Nokian mobiililaitteille. Pocket Party oli sitä itseään. Konseptin keskiössä oli massiivimoninpeli, sillä pelin sotatilanteen haluttiin elävän jatkuvasti yksittäisistä pelaajista riippumatta. Samaan aikaan kun RedLynxillä aloiteltiin Pathway to Gloryn jatko-osan Ikusa Islandin ja High Seize -merirosvopelin tuotantoa, yhtiössä pohdittiin täysin uudenlaisten jatko-osien kehittämistä Pathway to Glorylle. Nokia rahoitti Pocket Partya lähes puolellatoista miljoonalla dollarilla
Yhtiö panosti myös pelien kehitykseen aikaisempaa enemmän ja Nokian julkaisemista N-Gage-peleistä alkoi löytyä jo omaperäisyyttä. Pelin kehitysversion sisältö oli huomattavasti ronskimpaa. Kulissien takana käynnissä oli ainakin kolme peleihin liittyvää tuoteprojektia: kolmannen sukupolven NGage, GD2-mobiilikonsoli sekä N-Gage-sovelluskauppa ja -palvelu. 7. Ruotsalaisen Jadestone-studion Spirits oli yksi kunnianhimoisimpia kaupallisia moninpeliprojekteja N-Gagelle. Myös Nokian tutkimuslaitoksessa työskennellyt, peleihin erikoistunut tutkimustiimi osallistui Spiritsin tekemiseen. Kuva: N-Gage QD Global Press Event Game Assets, Nokia 2004. Kuvat: Timo Weirich. Spiritsin juuret olivat vuonna 2002–2003 S60-laitteille kehitetyssä teknologiademossa, jonka pohjalta Nokia alkoi rahoittaa kaupallista peliä. Oman maailmamme ja elementaalimaailman yhteentörmäyksestä kertova Spirits yhdisteli massiivista moninpeliä (MMO) ja keräilykorttipeliä. Nokia julkaisi Pocket Partystä vain tämän promokuvan. Erityisesti Nokia innovoi mobiilin moninpelaamisen saralla. Keskiössä mobiili moninpeli Vuodet 2003–2005 olivat pelirintamalla Nokian energisimmät. N-Gagea ja sen pelejä tutkinut Timo Weirich teki jäljennöksen Spiritsin kotelosta käyttäen alkuperäisiä pelin kehittäjiltä saatuja suunnittelutiedostoja. Pelaajat keräilivät elementaaliolentoja, koostivat niistä kuuden olion tiimin ja kävivät kaksintaisteluja isometrisillä areenoilla. Pelin kehitykseltä putosi pohja, kun Nokia veti tukensa N-Gage-laitteilta vuonna 2006. Samaan aikaan niin Nokian teolliset muotoilijat kuin yhtiön tutkimusyksikön pelitiimi olivat kiinnostuneita mobiililaitteilla toteutetun moninpelin mahdollisuuksista
Toisin oli Tampereen yliopiston hypermedialaboratorion tekemän konseptipelin Pohjoisen laulut (2003–2004) kohdalla. Kuvassa Tribal eXchange J2ME Wireless Toolkit 2.2 -emulaattorissa. Pohjoisen Laulut ja Tribal eXchange ovat hyviä esimerkkejä siitä, kuinka Nokia tuki yliopistoissa tapahtuvaa mobiilipelaamisen tutkimusta. Moni akateeminen pelitutkija on aloittanut uransa hankkeessa, jonka taustajoukoissa hääri myös Nokia. Tiimin tutkimus painottui yhä enemmän siihen, millaisia uudenlaisia moninpelikokemuksia tällainen laite mahdollistaisi. Pohjoisen lauluja tehtiin Spiritsin tavoin yhteistyössä Nokian pelitutkimusyksikön kanssa. Pelissä oli toteutettu Pokemon Gon (2016) myöhemmin popularisoimia lisätyn todellisuuden elementtejä. Peliin vaikuttaneet oikean maailman paikat ja toiset pelaajat kuvattiin rummun päällä liikkuvina esineinä. Spirits oli yritys kaupallistaa tällaista moninpeliarkkitehtuuria. Spirits oli puhdas MMO, eikä se sisältänyt oikeaa fyysistä ympäristöä hyödyntäviä elementtejä. Kuva: Olli Leino. 2024.3 8. Kuva: Pohjoisen laulut -peliesite. luja ei saanut ilmaiseksi, vaan ne ansaittiin etsimällä oikeaan ympäristöön liimattuja kooditarroja. Kirjoittaja on peleihin erikoistunut his to rian tutkija, joka on työskennellyt Suomen pelimuseossa. Lisäksi pelitapahtumiin vaikuttaneet sääolosuhteet muuttuivat verkkopalveluista haetun oikean säädatan perusteella. Sen pelaamiseksi tuli liikkua Tampereen kaupunkiympäristössä. Tribal eXchangessa pelaajat valitsivat yhden kolmesta tiimistä, jotka kilpailivat maa-alan aitaamisella Rampartpeliklassikon tapaan (1990). Rampartista poiketen Tribal eXchangessa aitaamiseen käytettyjä muurinpaloja tai työkaPohjoisen Laulut teki N-Gagesta noitarummun. Yhtiö olikin merkittävässä roolissa varhaisessa suomalaisessa pelitutkimuksessa. Vuonna 2024 ilmestyi hänen esikoiskirjansa Fantastinen floppi — Nokian pelibisneksen käynnistys, ro mah dus ja perintö. Suomen pelimuseo / Tampereen historiallisten museoiden kokoelmat; TMT/D 2198. Nokian pelitutkijat olivat samoihin aikoihin niin ikään mukana Tribal eXchange -konseptipelissä, jota kehittivät Lappeenrannan teknillisen yliopiston sekä Lapin yliopiston tutkijat. Mobiilinetin rajoitukset tekivät sellaisen toteuttamisesta puhelimelle kuitenkin hyvin vaikeaa, joten tutkimustiimi pohti keinoja toteuttaa rajatun pelaajamäärän ”moninpelikuplia” tai instansseja jatkuvasti elävän pelimaailman yhteyteen. Tribal eXchangen dokumentaatiossa vuodelta 2005 esitetään, kuinka peli-idea johdettiin Rampartista. 2000-luvun alussa tutkijoille oli tullut selväksi, että puhelimesta tulisi jatkuvasti nettiin yhteydessä oleva, sensoreilla varustettu, henkilökohtainen ja kaikkialle mukana kulkeva laite. Massiivimoninpelit olivat tuolloin PC:llä erittäin suosittuja
Viime versiossa vedettiin aika monta mutkaa suoraksi, eikä sillä vielä viritetä kovinkaan hääppöisesti. Vertasin tuloksia myös edellisen artikkelin äänenkorkeuden perusteella toimivaan naiiviin metodiin. Tein alkuun pieniä itsenäisiä ohjelman pätkiä, jotka testasivat McLeodia ja Yinia. Epäilykseni olivat kuitenkin turhia, sillä sellainen löytyy. Luodun äänen voi myös tallentaa koneelle. Siksi olisi optimaalista, että äänet soitettaisiin valmiista äänitiedostoista. Artikkeli on jatkoa Skrolli-lehden 2023.3 artikkeliin ”Kitaran viritys Rustilla". Tähän työkaluun voi syöttää taajuuden, ja se tuottaa ladattavan äänitiedoston. Tällä tavoin ohjelmat kuulevat, mitä virtuaalimikrofonista tulee sisään, ja tietokoneelta soitettavat äänet lähtevät ulos virtuaalikaiuttimesta. Siinä hankaluutena oli se, että siinä piti keksiä itse paljon erinäisiä parametreja FFT-algoritmille. Teksti ja kuvat: Juha Hollanti Rust-logo: Rust Foundation (CC BY 4.0) E dellisellä kerralla toteutettiin Rust-ohjelma, joka kaappaa tietokoneen mikrofonin audiosignaalin ja tekee sille FFT-signaalimuunnoksen. Selviteltyäni sopivaa algoritmia sävelkorkeuden löytämiseksi googlettelemalla ja ChatGPT:ltä kysymällä käy ilmi, että on olemassa useampia soveltuvia ratkaisuja. Herää pieni epäilys, löytyykö sellaista työkalua valmiina. Testipenkki on nyt kunnossa, joten on aika siirtyä mielenkiintoisiin haasteisiin eli koodaamiseen ja algoritmien testaamiseen. BlackHoleohjelma tarjoaa virtuaalisen mikrofonin ja kaiuttimen tietokoneen fyysisten versioiden ohelle. Tällä kertaa yritetään päästä parempaan lopputulokseen. Ehkäpä tähän palataan myöhemmin, mikäli löytyy tarvetta. Suomen ilmastossa lämpötila heittelee, joten kitaran kielen vire elää jonkin verran normaalin löystymisen lisäksi. Tähän löytyykin oiva palvelu, Online Tone Generator. Asiaa sen enempää tutkimatta totean, että todennäköisesti paras keino hyvän algoritmin löytämiseksi on kokeilla, mitä kirjastoja Rust-kielelle löytyy valmiiksi. Sävelkorkeuden kaivamiseen äkkiseltään löytyneiden algoritmien, McLeodin ja Yinin lisäksi muitakin algoritmeja tuli vastaan. Tietokone ei tällöin päästä kuultavaa ääntä. Tämä tehdään kaikille kitaran kielten taajuuksille. Tästä voitiin kaivaa äänenvoimakkuuden perusteella vallitseva taajuus eli sävelkorkeus. Varsinkaan macOSille. 9. Vaikka se ei itseäni haittaa, perheeni mielestä sitä on sangen ärsyttävä kuunnella. Ennen algoritmien testaamista pitää rakentaa jonkinlainen testipenkki. Tähän on kaksi syytä: algoritmeja testatessa olisi liian työlästä soitella tietokoneen mikrofoniin kitaran kieliä, ja kitaran pitäisi olla testattaessa täydellisessä vireessä. Niistä ensimmäisinä tulee vastaan McLeodsekä vähemmän tunnettu Yin-algoritmi. Niistä ehkä mielenkiintoisimpia ovat koneoppimiseen perustuvat algoritmit, mutta sellaista ei heti löytynyt valmiina Rustkirjastona. Erinäisistä väärin asetetuista FFT-algoritmin asetuksista johtuen poimitut taajuudet olivat jonkin verran pielessä. SYVÄ PÄÄTY KOODI Harrastusprojektin anatomia Kitaran viritys Rustilla Osa 2. Pitäisi keksiä, miten äänitiedostoja voi soittaa ilman ääntä siten, että tietokoneen mikrofoni saa äänisignaalin kaapattua. Seuraava testipenkkiin liittyvä haaste paljastuu puuhatessani äänitiedostoilla hetken aikaa. Helpolta hommalta siis tuntuu. Mielenkiintoinen ongelma, joka äkkiseltään tuntuu kohtalaisen uniikilta. Tämä edellytti alTestiäänten luomista varten käytetty Online Tone Generator -sivusto tarjoaa kontrollit äänen korkeuteen ja aaltomuotoon
Algoritmit jatkokäsittelevät mahdollisten sävelkorkeuksien joukkoa päätyen lopulta valitsemaan todennäköisimmän taajuuden. Päädyin luomaan PitchFindTrait it boxin sisään, jotta niitä on helpompi välittää funktioiden välillä ja käyttää monisäikeisessä ympäristössä. Tämän lisäksi ajon aikana voidaan valita helposti eri toteutuksien välillä. Move-avainsanalla data-parametrin omistajuus siirretään data_callback-funktiolle. Algoritmeista jotain tietävät varmaan pyörittelevät silmiään. Rust-ohjelman main() -metodissa luetaan konfiguraatiot, valitaan niiden perusteella algoritmi ja annetaan sille parametrit. Smart pointer on muistiosoitin, mutta se hoitaa automaattisesti myös muistinhallintaan liittyvät asiat. let stream = device .build_input_stream( &config, move |data: &[T], _| { let f64_vals: Vec = data. Teen config.yaml -tiedoston jonka ohjelma lukee. Rakennan ohjelman niin, että yleiset asiat kuten audiosignaalin lukeminen ja tulosten tulkitseminen tehdään kerran, eikä erikseen joka algoritmille. Yin-algoritmi näyttäisi toimivan tarkemmin antaen tuloksia, jotka ovat hyväksyttävän lähellä alkuperäistä taajuutta. Cpal-kirjasto suorittaa stremin käsittelyssä säikeen kullekin syötteelle. Eli siis se, miten määritetään algoritmille konteksti sille, millaisia taajuuksia halutaan selvittää. Tehdään erillinen funktio, joka lukee sampleja käyttäen Cpal-kirjastoa ja syöttää samplet eteenpäin valitulle PitchFindTraitin toteutukselle. maybe_find_pitch(&f64_vals); if freq != None { let s_and_f = find_string_ and_distance(freq.unwrap()); output(freq.unwrap(), s_ and_f.0, s_and_f.1, s_and_f.2); } }, err_fn, ) .unwrap(); Tässä on huomioitavaa, että build_ input_stream -funktion toinen parametri mut data_callback: D on takaisinkutsufunktio. McLeodilla pääsee varmasti samoihin tarkkuuksiin, jos vain käyttäisi enemmän aikaa parametrien määrittelemiseen. Box on smart pointer, joka alustetaan heap-muistiin. Täten funktiokutsun rivi riviltä ajamisen sijaan build_input_ stream ajetaan samassa säikeessä, ja sisään saatu data välitetään data_ callback -funktiolle. Luodaan StreamConfig , joka on Cpal-kirjaston rakenne. Tämä käytännössä toteuttaa olioohjelmoinnistakin tutun konseptin, polymorfismin. Tämän voisi jatkossa parametrisoida tai antaa käyttäjän määrittää se käyttöliittymästä. Yksinkertaisempi lopputulos on yleensä hyvä valintaperuste. Siellä esimerkiksi pitch_detection -parametri valitsee halutun algoritmin. Tässä tapauksessa taajuuden tulkitseminen on rajapinta ja eri algoritmit ovat toteutuksia. 2024.3 10. Seuraava koodinpätkä lukee syöttövirrasta sampleja ja välittää ne edelleen output -funktiolle Virtuaalisten kaiutinten ja mikrofonien määrittäminen BlackHole-sovelluksella. Listaus config.yaml-asetustiedostosta. Box auttaa myös, kun haluamme ajon aikana määrittää käytettävän implementaation. Yhden metodin valitsemisen sijaan haluan tehdä ohjelman, jolle voi konfiguroida halutun metodin ja sen parametrit. McLeodja Yin-algoritmeissa parametreja on hallitumpi määrä, ja esimerkiksi Yin-algoritmin parametrit ”matalin taajuus” ja ”korkein taajuus” ovat erittäin selkeät. On toki tapauskohtaista, kannattaako asiat ratkaista polymorfismilla vai ifelse:llä. PitchFindTrait illa on yksi metodi: Yllä mainitussa funktion määrityksessä on huomattava box-rakenne. Sitä käytetään yleisesti polymorfisissa rakenteissa kuten PitchFindTrait in eri implementaatiot. Ilman sitä pitäisi sirotella if-else-ehtoja ympäri koodia, mikä ei ole toivottavaa. collect(); let freq = (*detector). Mikrofonia valittaessa käytetään vielä oletuksia, jolloin valikoituu ensimmäinen mikrofoni. Se kunnioittaa Rustin käytäntöjä tietorakenteiden omistajuuden suhteen taaten muistivuotojen ehkäisyn. Tässä vaiheessa käytetään vielä audiosignaalin puskurin koon oletusarvoa 1024. Ratkaisun ansiosta syntyy yksinkertaisempaa ja ylläpidettävämpää koodia. Datan omistajuuden siirtäminen funktioldetect_from_input_stream<T: Sample>(device: &Device, config: &StreamConfig, mut detector: Box<dyn PitchFindTrait>) fn maybe_find_pitch(&mut self, data: &[f64]) -> Option<f64>; Teen toteutuksen tälle traitille käyttäen Yinia, McLeodia ja alkuperäisessa artikkelissa esitettyä naiivia FFT-pohjaista algoritmia. goritmin syvällisempää ymmärrystä. Algoritmien eristäminen on kohtalaisen suorasukainen homma tehdä Rustissa käyttämällä traiteja, jotka tarjoavat yhdelle rajapinnalle useamman toteutuksen. iter().map(|x| x.to_f32() as f64). Tässä on vielä erikoisuus Box<> , joka soveltuu käyttötapauksiin, joissa on samalle traitille eri toteutukset ja eri structit. Tehdään PitchFindTrait -niminen trait, johon eristetään eri algoritmit. Mutta ne etsivät toistuvia, mahdollisia sävelkorkeuksia merkitseviä kuvioita. Karkeasti voisi sanoa, että Yinja McLeod-algoritmit toimivat suunnilleen samoilla periaatteilla
Jatkossa voisikin antaa käyttäjän ensin määrittää viritettävän kielen. Vain yksi funktio voi omistaa kirjoitusoikeudet. Lainaamisella on omat seurauksensa, esimerkiksi dataa lainaava funktio ei voi muokata sitä. Ilmeisesti McLeodDetector pitää sisällään tietueita, jotka eivät kulje säikeiden yli nätisti, joten Rust-kääntäjä ei salli luoda sitä maybe_find_pitch -funktion ulkopuolella. Itseäni erityisesti jäi harmittamaan McLeod-toteutus PitchFindTrait ille. Jätin sen kuitenkin näin, sillä en löytänyt tapaa luoda ja tallentaa tätä objektia structin konstruktorissa. Netistä löytyvistä virittimiin verrattuna ollaan vielä hieman pielessä. Kitaran saa aika hyvään vireeseen. Kirjoituslainan aikana omistaja ei samanaikaisesti omista kirjoitusoikeutta. Kitaralla voi kuitenkin soitella, ja se kuulostaa hyvältä. Päivitystaajuus voisi olla maltillisempi, mutta tähän hätään se kelpaa. find_string_and_distance(freq: f64) -> (f64, f64, String) lazy_static! { static ref GUITAR_STRINGS: HashMap<String, f64> = { let mut m = HashMap::new(); m.insert("E2".to_string(), 82.41); m.insert("A2".to_string(), 110.00); m.insert("D3".to_string(), 146.83); m.insert(“G3†.to_string(), 196.00); m.insert("B3".to_string(), 246.94); m.insert("E4".to_string(), 329.63); output(freq:f64, string_freq:f64, distance:f64, string_key:String) impl PitchFindTrait for McLeodPitchDetector { fn maybe_find_pitch(&mut self, data: &[f64]) -> Option { let mut mcleod = McLeodDetector::new(self.size, self.padding); let pitch = mcleod.get_ pitch(data, self.sample_rate, self.power_threshold, self. Yhteenvetona Rust-kääntäjä määrittää seuraavat muistinhallintaan liittyvät asiat: • Omistajuus (Ownership), yksinomainen luku-/kirjoitusoikeus tietoihin. Päädyn käyttämään Yin-algoritmia, koska se tuntui toimivan testatessa parhaiten. Vain yksi taho voi omistaa kirjoitusoikeuden tietoihin milloin tahansa, eikä muita lukutai kirjoituslainoja ole sallittu samanaikaisesti. Omistaja on vastuussa tiedon elinkaaresta. Koodissa lienee paljon asioita, joita voisi parannella ja jotka kokenut Rust-koodaaja huomaisi nopealla silmäyksellä. Koodauksen päätteeksi suoritetaan vielä käytännön testi. Useat tahot voivat lukea tietoa, mutta yksikään ei voi muokata sitä. Tämä ei välttämättä aina toimi esimerkiksi kitaran ollessa reilusti epävireessä. Tulokset näytetään output -funktion avulla: Tätä funktiossa yksinkertaisesti tulostaa konsoliin ohjeet miten kitaraa pitää virittää. clarity_threshold); if pitch.is_some() { return Some(pitch.unwrap(). Eli tarpeeksi hyvä! Seuraavalla kerralla on tarkoitus sukeltaa Web Assemblyyn ja rakennella vaihtoehto komentorivipohjaiselle käyttöliittymälle. Tässä lyhyesti koko toteutus: Tätä funktiota kutsutaan aina, kun saamme uuden samplen ja haluamme eristää siitä sävelkorkeuden. Ellei dataa siirretä, se ”lainataan”. Koska tätä funktiota kutsutaan usein, sen pitäisi olla mahdollisimman kevyt. Tämä funktio toimii puhtaasti seuraavan rakenteen pohjalta: m } }; Tässä siis kaivetaan lähin sävelkorkeutta vastaava kitaran kieli taajuuden perusteella. Palataan vielä yhteen harmituksen aiheeseen. Tällä siis lasketaan käyttäjälle ehdotus, miten kitaran kieltä pitäisi virittää. Rust-kääntäjä on erittäin tiukka. Kitara esiin, ruuvataan se hieman epävireeseen ja viritetään käyttäen juuri luotua kotitekoista työkalua. frequency); } return None } } Tämän funktion tehtävänä on etsiä, mitä kitaran kieltä lähimpänä sävelkorkeus on sekä kuinka kaukana oikeasta taajuudesta ollaan. Konsolin teksti päivittyy melko vinhaa vauhtia. Funktio tarkistaa, mikäli havaittu sävelkorkeus ja kitaran kieli ovat alle yhden hertsin päässä toisistaan, jolloin käyttäjälle ei näytetä lainkaan säätämisohjetta if distance.abs() > 0.9 . Lainatun datan voi myös määrittää kirjoitusoikeuksilla, mutta silläkin on omat käytäntönsä. let mut mcleod = McLeodDetector::new(self.size, self.padding); Linkit Lähdekoodi: github.com/jphollanti/ nofuzz-tuner/releases/tag/v.skrolli.2 Online Tone Generator: onlinetonegenerator.com BlackHole: github.com/ExistentialAudio/BlackHole Cpal: github.com/RustAudio/cpal pitch_detection (mm. le tuo monia hyötyjä, esimerkisi muistin turvallisuus, kopioiden välttäminen, selkeä tarkoituksen indikoiminen ja datan muokkaaminen. McLeod): github.com/alesgenova/pitchdetection Yin: https://github.com/saresend/yin 11. Ennen output -funktioon siirtymistä kutsumme funktiota: Cargo run -komennolla onnistuneesti käännetty ohjelma kertoo, kuinka lähelle tavoitetta kielen viritys osuu. Tässä kohtaa kuitenkin luodaan jokaisella kerralla kun funktiota kutsuttaessa uudelleen McLeodDetector -objekti: Ihannetapauksessa McLeodDetector luotaisiin vain kerran. • Kirjoituslaina (Write Borrow, &mut T ), yksinomainen kirjoitusoikeus. Harmillista, mutta tähän hätään ratkaisu kelpaa. • Laina, ”vain lukemislaina” (ReadOnly Borrow, &T ), jaettu lukuoikeus
Minua ilahduttaa se, kuinka helppoa Slowlyssa on löytää ihmisiä, jotka asuvat jossakin aivan muualla ja ovat vaikkapa ihan eri ikäisiä, mutta joiden kanssa kuitenkin löytää yhteistä jutunjuurta yllättävän helposti. SOFTA O len kirjoitellut sähköisesti ihmisten kanssa yli 25 vuotta. Profiilitietoihin voi kirjoittaa lyhyen vapaamuotoisen esittelytekstin Kirjeenvaihtosimulaattori kännykässä Slowly.app Hitaaseen viestintään panostava some Slowly hurmasi millenniaalitoimittajan – väkinäisestä jippoilustaan huolimatta. Suomalaisia olen tavannut parin kuukauden käytön aikana vain yhden, mutta hänkin asuu ulkomailla. Tähän mennessä olen keskustellut muun muassa konemusiikista turkkilaisen kanssa, matkustamisesta sanfranciscolaisen kanssa ja teestä srilankalaisen kanssa. Mobiilisovellus ja sosiaalinen media hitaan viestimisen ystäville. Ei ole kiusallista vastakkainasettelua studiopotrettien ja vessaselfieiden välillä. Luulin jo kokeneeni tällä saralla kaiken, mutta tänä kesänä tutustuin ihan uudenlaiseen viestisovellukseen, jollaista en ollut vielä koskaan kokeillut. Erottumaan pääsee enimmäkseen kirjoitustaidolla ja -halulla. Mitä kauempana vastaanottaja on maantieteellisesti, sitä kauemmin viestin kulku kestää: naapurikaupunkiin parikymmentä minuuttia, toiselle puolelle maailmaa kymmeniä tunteja. Suggestions for You -näkymässäni vilisee paljon eteläamerikkalaisia, turkkilaisia, kiinalaisia, taiwanilaisia, intialaisia ja muita eteläaasialaisia. Viesteillä ei toki ole vähimmäispituutta, mutta kun kirjeenvaihtokaverin vastausta joutuu odottamaan vuorokauden tai pari, on äkkiä väkisinkin mielekästä kirjoittaa samalla kertaa aika pitkät tarinat. Sovellus on hämmästyttävän epävisuaalinen: profiilikuvia ei ole, ja kaikki viestintä perustuu pitkiin teksteihin. Keväällä 2001 liityin IRC-Galleriaan, jossa oli ihan omanlaisensa fiilis. Rekisteröidyin muutamille foorumeille, joilta löytyi samoista asioista kiinnostuneita ihmisiä – joidenkin kanssa olen yhteyksissä edelleen. Kirjavasti ihmisiä eri puolilta maailmaa Olen törmännyt sovelluksessa yllättävän erilaiseen porukkaan kuin muissa someissa. iOS, Android ja webkäyttöliittymä: slowly.app Slowly on hongkongilaisen Slowly Communications Ltd:n palvelu, joka on perustettu 2017. Pidän siitä, että avatar-kuvat tekevät sovelluksen yleisilmeestä kovin seesteisen ja tasapainoisen: kaikkien käyttäjien naamat ilmaisevat itsensä saman visuaalisen kielen avulla ja ne ovat kaikki ikään kuin yhtä laadukkaita. Teksti: Ronja Koistinen Kuvat: Slowly, Matilda Smeds 2024.3 12. Kuvia ja ääntäkin voi lähettää, mutta siihen vaaditaan etukäteen molempien osapuolten suostumus. Sitä ehkä voi jo kutsua sosiaaliseksi mediaksi vähän samaan tapaan kuin myöhemmin Facebookia, Twitteriä ja muita. Jonkin verran on yhdysvaltalaisiakin. Profiilikuvan sijaan Slowlyssa rakennetaan valmiista piirroselementeistä avatar-kuva. Slowly on sovellus ja web-sivu, joka hidastaa tarkoituksella viestien perillemenoa. Tällaista maailmankansalaisuutta ja vapautta ahtaista algoritmeista en ollutkaan kokenut netissä pitkään aikaan! Muita käyttäjiä voi filtteröidä kiinnostuksen kohteiden ja kielitaidon perusteella. Alkuun soittelin modeemilla purkkeihin 1990-luvulla, ja vuosikymmenen lopulla liityin IRC-verkkoihin sekä otin käyttöön myös sähköpostin
Avointen kirjeiden käyttötarkoitus näyttää olevan esittäytyä maailmalle, kertoa jotaSain kirjeen mukavalta egyptiläiseltä opiskelijalta, joka harrastaa kirjallisuutta. Muiksi geososiaalisiksi verkoiksi voitaneen lukea esimerkiksi Jodel ja Foursquare sekä tietysti myös Tinder ja Grindr, vaikka niiden maantieteelliseen sijaintiin liittyvät ominaisuudet ovatkin ihan muunlaisia kuin Slowlyn. Vastausta kirjoittaessa voi kätevästi selata vastaanotettua kirjettä kirjoitusruudun yläpuolella. Turvallisinta lienee olettaa, että ne näkyvät ihan kaikille käyttäjille. Slowlyssa ei edes ulkonäkö haittaa menoa, kun ei valokuvia ole heti näkyvillä. Niistä ei oikein saa mitään otetta ja ne ovat keskenään samanlaisia. En ole varma, kuinka laajalle jakelulle avoimet kirjeet näkyvät ja millä logiikalla, joten kannattaa ehkä olla varovainen, mitä niihin laittaa. Muutama emoji ja huutomerkki sekaan. Sen sai ostaa myös lyhyemmäksi aikaa kerrallaan, mutta en enää saanut näkyviin tämän hintoja sovelluksesta enkä löytänyt niitä verkkosivultakaan. Jos haluaa oikein paljon kerjätä Slowlyssa huomiota, voi lähettää avoimen kirjeen. Näiden lisäksi on iso liuta erilaisia asiasanoja, joista voi ruksata itselleen kiinnostavat. Paikkatietoa sovelletaan luovasti Slowly solahtaa ongelmitta niin sanottujen geososiaalisten verkkojen käsitteen alle. Mitään erityisen kammottavia lähestymisiä en ole toistaiseksi saanut. Vastaan tulee paljon ihmisiä, joiden lähetetyt:vastaanotetut on luokkaa 50:3, joka on helppo tulkita niin, että he roiskivat paljon maailmalle lyhyitä ja mitäänsanomattomia kirjeitä, jotka eivät kiinnosta ketään. Kirjekaverilta saatua merkkiä voi myös jakaa eteenpäin toisille, ja kun monet merkit sisältävät jotakin kansallista kuvastoa, keräilyhammasta alkaa äkkiä kolottaa. Postimerkkejä näpäyttämällä ne saa myös näkyviin vähän suurempana kuvaa selittävän tekstin kera. Sovellusta voi käyttää ilmaiseksi, mutta siinä tapauksessa se näyttää aika tiuhaan mainoksia. Olen kokenut kaikkein turhauttavimmiksi sellaiset lyhyet, yhden kappaleen mittaiset viestit, joissa kirjoittaja vain kertoo kotimaansa ja olevansa kiinnostunut tutustumaan ihmisiin. Hänen viestinsä poistin tekemättä suurta numeroa, vaikka saatoin hieman tuhahdella ja kurtistaa kulmiani. Horoskooppimerkki tuntuu olevan vahvasti läsnä: sen sovellus päättelee syntymäajasta suoraan, mutta sen voi myös piilottaa muilta. Slowlyn hurmaavin juju ovat virtuaaliset postimerkit. sekä syntymäajan ja sukupuolen (kolme vaihtoehtoa). Kiinnitän myös paljon huomiota profiilien metatiedoissa näkyvään suhdelukuun lähetetyistä ja vastaanotetuista viesteistä. Viestissä oli viisi kertaa sana ”mature”, enkä minä ole vielä edes neljääkymmentä. Selvästikin jonkinlainen heittäytyminen ja paneutuminen viesteihin palkitaan Slowlyssa. Plus-tilauksen yhteydessä saa tietyn määrän virtuaalikolikoita, joilla merkkejä ostetaan postimerkkikaupasta, ja kolikoita voi ostaa myös erikseen. 13. Postimerkit eivät kuitenkaan ole analogisten esikuviensa tapaan kertakäyttöisiä. Kun virtuaalisen merkin on kerran saanut tai ostanut, sitä voi käyttää loputtomiin uudelleen ja uudelleen. Tässä lienee jotain samaa kuin deittisovelluksissakin: jos asettautuu hieman haavoittuvaiseksi ja laittaa itsensä likoon, näyttäytyy kiinnostavana ja lähestyttävänä. Se on siis some, jolla on jonkinlainen käyttäjien maantieteelliseen paikantamiseen liittyvä arvo tai toiminnallisuus. Jokaiseen kirjeeseen pitää kiinnittää postimerkki, ja sovelluksessa on sisäinen postimerkkikauppa! Merkkejä saa myös ilmaiseksi palveluun liityttäessä ja erilaisia ”saavutuksia” suorittaessa. Syntymäajan voi piilottaa kokonaan tai näyttää esimerkiksi vain vuoden tarkkuudella. Pohjat veti 22-vuotias kenialaismies, joka kertoi minulle kukkean polveilevasti viehätyksestään ”kypsiin naisiin”. Itse ostin mainoksettoman plus-ominaisuuden vuodeksi 30,99 eurolla
Slowly tekee toimintalogiikassaan pari myönnytystä, jotka rikkovat kirjeenvaihtoilluusion sieltä täältä, mutta kokonaisuus on erittäin puhutteleva. Olenkin nykyään hiljentänyt suurimman osan Slowlyn ilmoituksista, koska tuntui turhalta saada ilmoitus, että joku on lähettänyt minulle kirjeen Venezuelasta, mutta voin lukea sen vasta 30 tunnin päästä. Sovellus näyttää ilmoituksen, jonka avaamalla saa eteensä kartan, johon on (hieman satunnaistettuna) merkitty, kuka on laittanut kirjeen matkaan ja mistä. En ole saanut vastausta palautteeseeni. Samaten näkyy tieto siitä, milloin se on ”perillä”. Tervetuloa mukaan! 2024.3 14. Samaten tuntuu kummalliselta, että kukin kirje ”kulkee” matkallaan täsmälleen algoritmin etäisyyden perusteella määrittämän ajan, eikä sekuntiakaan kauemmin. Slowlya voi käyttää myös tietokoneella web-selaimen kautta – onneksi, sillä pitkien kirjeiden naputtelu puhelimen kosketusnäytöllä ei pidemmän päälle ole mukavaa. Ehkä ilman näitä ennakkoilmoituksia liian moni käyttäjä roiskisi muutaman kirjeen sinne tänne, odottaisi seuraavaan päivään ja hämmentyisi, kun vastauksia ei kuulu. Kiva tietää näin kolmelta aamuyöstä. Web-versiossa ei kuitenkaan jostain syystä ole kaikkia ominaisuuksia! Siinä voi lähinnä selata olemassa olevia kirjekavereita, lukea vanhoja viestejä ja kirjoittaa uusia. Minusta se on aika outo. Siitä seuraa, että kirjeitä voi kilahdella sovellukseen mihin kellonaikaan tahansa ja moneen kertaan pitkin päivää. Sehän voisi kenties hyvinkin johtaa turhautumiseen ja sovelluksen poistamiseen ennen vastausten saapumista, varsinkin nuorempien käyttäjien kohdalla, jotka eivät ehkä koskaan ole lähettäneet postissa fyysisiä kirjeitä. Kaiken kaikkiaan Slowly on erittäin kiinnostava ja tervetullut, omaperäinen some. Lähetin ylläpidolle kehitysehdotuksen, jossa pyysin mahdollisuutta kytkeä pois päältä tämä ominaisuus. Tämä sopii minulle oikein mukavasti, sillä kirjoitan toisinaan edelleen myös niitä paperisia kirjeitä kynällä, ja kyseinen kansanperinne on oikein lähellä sydäntäni. Tuntemattomia käyttäjiä tai avoimia kirjeitä ei web-näkymässä voi selata. Pyysin samaisessa palautteessani myös sellaista ominaisuutta, että kirjeet voisi vastaanottaa kerran päivässä jollakin itse valitsemallaan kellonlyömällä, aivan niin kuin oikeakin postinkantaja käy korkeintaan kerran päivässä. kin omasta kotimaastaan tai vaikkapa heittää ilmoille kysymys, johon toivoo maailmalta vastauksia. Vastaukset eivät ole julkisia, vaan ne menevät vain avoimen kirjeen lähettäneelle käyttäjälle. Simulaatio ei ole täydellinen Eräs outo ominaisuus Slowlyssa on se, että kun joku lähettää sinulle kirjeen, saat tiedon siitä heti
Kertoimelle 0,8 ei oikein ole mitään järkevää syytä – ehkä ajattelin, että freimin laskeskeluun ja piirtämiseen kuluu jokin aika, joten olisi hyvä jättää vähän välystä. Tätä kirjoittaessani vasta tajuan, että olen unohtanut kertoa frameDelay-arvoni tuhannella, eli käytännössä olen syöttänyt setInterval() -funktiolle viiveeksi noin nolla millisekuntia. 0,133. Kirjoitan oppimispäiväkirjan kaltaisesti muistiinpanoja opinnoistani ja otan sinut kyytiin. Tyhmä vakiointervalli Aluksi tein tietoisesti naiivin yksinkertaistuksen, nimittäin toteutin pelisilmukan setInterval() -funktiolla. Siitä näkyy, kuinka funktiolle annetaan argumenteiksi anonyymi funktio sekä this.frameDelay . Katsotaan sitä sekä muutamaa muuta olennaista koodipätkää listauksessa 2. Tämä ei ole tyyppimielessä ongelma, sillä Typeja JavaScriptissä liukuluvut ja kokonaisluvut ovat kuitenkin samaa number-tietotyyppiä. TypeScript on Microsoftin kehittämä kieli, joka lisää JavaScriptin päälle erittäin monipuolisen staattisen tyypityksen. HÖYRYÄVÄ HÖYRYÄVÄ KUPILLINEN KUPILLINEN ??tt::tä tä Kesäkoodaamisen aika alkaa loppua, mutta viimeistellään pimenevien iltojen ratoksi vielä pelisilmukan ajastus. Seuraa mietiskelyä ja hupsista saatanaa, mutta toivottavasti saavutetaan myös uutta ymmärrystä. Listaus 1. Argumenteiksi annetaan haluttu funktio ja aikaväli millisekunteina: esimerkiksi setInterval(() => console.log(’Hello World’), 1000) tulostaa selaimen tai Node.js:n konsoliin kerran sekunnissa merkkijonon ”Hello World”. Sitä ei voi ajaa suoraan selaimessa eikä myöskään backendissä Node.js-tulkissa, vaan se pitää ensin kääntää JavaScriptiksi TypeScript-kääntäjällä. Jos setIntervalin poistaa kokonaan ja runttaa pelisilmukkaa oikeasti täysillä, koko selaimen välilehti menee juntturaan. Kokeilin vaihtaa setInterval() -silmukan tilalle yksinkertaisen while(true) -silmukan: peli lakkasi toimimasta ja selain antoi varoituksen ”This page is slowing down Firefox. Juttu vaatinee jonkin verran perehtyneisyyttä ohjelmointiin, sillä koodilistauksia on luvassa. Lopputuloksena syntyi pieni selaimessa pelattava Tetris-klooni, jolle annoin mielikuvituksettoman nimen TS Tetris. Freimiviiveeksi tuli siis 1 / 60 × 0,8 . Teksti: Ronja Koistinen Kuva: Mitol Meerna 2024.3 16. En ollut koskenut JavaScript-juttuihin oikeastaan ollenkaan sitten 2000-luvun. Se on JavaScriptin toiminto, jolla määrätään jokin toinen funktio ajettavaksi tietyin määräajoin. Putoamiskoodia Ensimmäisen listauksen GameState.Running -haarassa kutsutaan doFall() -metodia. // game.ts: // Game-luokan metodi play(): void { // arvotaan palikat setInterval(() => { // erinäistä valmistelua switch (this.state) { case GameState.Menu: // piirretään alkuruutu break; case GameState.Running: if (this.isPieceLanded()) { // käsitellään laskeutunut palikka } else { this.doFall(); } // piirretään pelin tila break; case GameState.GameOver: // piirretään game over -ruutu break; case GameState.Paused: // piirretään pause-ruutu break; } }, this.frameDelay); } Listauksessa 1 näkyvä this.frameDelay saa Game-luokan konstruktorissa arvokseen (1 / FRAMES_PER_SECOND) * 0.8 . AIKASARJA : 1 : 2 : 3 : 4 :0 5 : 6 :0 7 :0 8 :0 9: 10 :1 1 :1 2 :1 3 :1 4: 15 : 16 : 1 7 : 1 8 : 1 9 : 2 : 2 1 : 2 2 : 2 3 : KOODI T ällä kertaa Aikasarjassa ollaan sen verran kirjoittajan mukavuusalueen reunamilla, että jutun sävy poikkeaa totutusta. FRAMES_ PER_SECOND on toisaalla koodissa (ks. listaus 2) määrittämäni vakio, jonka arvona oli 60. Homman jujuna on, että kääntäjä huomaa tyyppivirheet, ennen kuin koodia ajetaan ollenkaan, jolloin lopputuloksena saadaan helpommin turvallisempaa ja virheettömämpää koodia. Grafiikka piirretään HTML:n canvas-elementille. Tänä kesänä oli aikaa harrastuskoodailla, joten päätin opetella lisää peliohjelmointia ja samalla kertaa uutta ohjelmointikieltä, TypeScriptiä. To speed up your browser, stop this page.” Se käy järkeen, sillä vaikka dokumentaation mukaan oletusintervallikin on ms, käytännössä selaimet käyttävät jotakin hieman suurempaa minimiviivettä, esimerkiksi 4 ms. Tervetuloa mukaan delta-aikamatkalle. Katso karsittu esitys alkuperäisestä pelisilmukastani listauksesta 1
muut näppäimet } } handleKeyUp(event: KeyboardEvent): void { switch (event.code) { case "ArrowDown": this.softDrop = false; event.preventDefault(); break; } } maybeNextLevel(lines: number): void { this.levelProgress += lines; if (this.levelProgress >= LINES_PER_LEVEL) { this.level++; this.levelProgress = 0; this.gravity = Math.min(MAX_GRAVITY, this.gravity * LEVEL_UP_GRAVITY_FACTOR); } } // constants.ts: // 1 rivi / n freimiä export const STARTING_GRAVITY = 1 / 128; // tason noustessa kerrotaan painovoima tällä export const LEVEL_UP_GRAVITY_FACTOR = 1.4; export const SOFTDROP_GRAVITY = 1/8; // tetrispala ei voi koskaan pudota koko pelikentän korkeutta pidemmälle // yhden freimin aikana export const MAX_GRAVITY = PLAYFIELD_HEIGHT; Listauksesta 2 nähdään alkuperäinen mallini tetrispalojen putoamiselle. Toisaalta lapsuudessani 1990-luvulla kohtasin usein hankaluuksia vanhojen 1980-luvun DOS-pelien kanssa, koska ne oli koodattu paljon hitaammille tietokoneille. Niitä oli mahdotonta pelata, sillä ne pyörivät ihan liian nopeasti. IBM PC:ssä olisi kyllä jo 80-luvulla ollut myös PIT-keskeytyksiä (programmable interrupt timer), joilla freimejä olisi voinut tahdistaa, mutta tätä ei syystä tai toisesta aina käytetty. Kun pelaaja etenee pelissä ja saa lisää tasoja, gravity-muuttujaa kasvatetaan. Jos taas painovoima on suurempi kuin 1, pyöristetään se ensin alaspäin. // game.ts: // Game-luokan metodeja doFall(): void { if (this.gravity < 1.0) { this.currentPiece.position[1] += this.softDrop && this.gravity < SOFTDROP_GRAVITY . Periaatteessa pelilogiikan sitominen suoraan freimeihin tällä tavalla ei kuitenkaan ole hyvä käytäntö, erityisesti vähänkään raskaammissa tai monimutkaisemmissa peleissä. 17. Maksimipainovoima on pelikentän korkeus: olisi mieletöntä, että pala putoaisi yhden freimin aikana pidemmän matkan kuin yläriviltä pohjalle asti. Freimeihin oli esimerkiksi lisätty tietty määrä viivettä busy-waitilla eli tyhjällä silmukalla, jota ajettiin sopiva määrä toistoja, mutta nopeammalla suorittimella toistot hujahtivat nopeammin, joten peli pyöri liian nopeasti. Tällöin peli vaihtaa voimassa olleen painovoiman tilalle toisen, nopeamman painovoiman, joka on määritetty constants.ts -tiedostossa muuttujassa SOFTDROP_GRAVITY. Sitten pudotetaan palikkaa pyöristämällä saadun kokonaisluvun verran rivejä alaspäin, jos mahdollista. Todennäköisesti pelini toimisi tällaisenaankin aivan hyvin kaikilla nykytietokoneilla, joilla sitä joku saattaisi pelata. riviä per freimi. Sen arvona on . Kun pelaaja painaa nuoli alas -näppäimen pohjaan, peli asettaa softDrop -nimisen lipun. position[1] += remainderG; } } handleKeyDown(event: KeyboardEvent): void { switch (event.code) { case "ArrowDown": if (this.state != GameState.Running) return; if (this.gravity < 1) { this.softDrop = true; } if (this.isPieceLanded()) this.lockPiece(); event.preventDefault(); break; // ... Muutoin palikan putoaminen tapahtuu samoin kuin normaalistikin. SOFTDROP_GRAVITY : this.gravity; } else { const maxRows = Math.floor(this.gravity); let counter; for (counter = 0; counter < maxRows && !this. Luin koodatessani Tetris.wikiä 1 , josta sain käsityksen, että gravity on tässä merkityksessä laajalti käytetty käsite tetrispiireissä. Palikkaa ei voi sijoittaa suoraan pystysuunnassa painovoima-arvon verran alemmas, koska välissä voi olla roskaa tiellä. Jokin tietokone saattaisi esimerkiksi olla huomattavasti nopeampi tai hitaampi kuin se, jolla peli on laadittu tai testattu. Kyseessä ei ole putoamiskiihtyvyys eikä mikään voima, vaan yksinkertaisesti vakio, joka lisätään joka freimillä palikan pystysuuntaiseen sijaintiin (tai vähennetään siitä, jos pelin koordinaatisto on koodattu toisinpäin). Niiden pelimekaniikka oli koodattu siten, että asioiden liikkeet ja muutokset oli suhteutettu suoraan suoritinsykleihin, eikä oikeaan ajan kulumiseen, joka taas on ihmispelaajalle paljon mielekkäämpi rajapinta. Listaus 2. Jos freimien valmistelussa ja piirtämisessä kestäisikin paljon kauemmin kuin koodaaja on suunnitellut, kaikki asiat tapahtuisivat hitaammin kuin koodaaja tarkoitti. Painovoimaa ajatellaan sen suhteen, kuinka monta riviä pala putoaa jokaista freimiä kohden. Mikä on vikana. Palan sijainti x-akselilla on kokonaisluku, ja sitä muutetaan välittömästi yksi sarake oikealle tai vasemmalle, aina kun pelaaja painaa nuolinäppäintä. Y-akselilla sijainti on sen sijaan liukuluku. Lopuksi saatuun uuteen sijaintiin y-akselilla lisätään vielä alaspäin pyöristämisestä yli jäänyt gravity-arvon murto-osa. Tässä pitää ehkä huomauttaa, että koodissa käytetään gravityeli painovoima-käsitettä täysin eri tavalla kuin fysiikassa. Metodissa move() on logiikkaa roskan tunnistamiseen ja palikan pysäyttämiseen. Ensimmäistä haaraa käytetään, kun painovoima on pienempi kuin 1: siis kun palikka putoaa hitaammin kuin yhden kokonaisen rivin per freimi. isPieceLanded(); counter++) this.move(Move.Down); const remainderG = this.gravity counter; if (!this.isPieceLanded()) this.currentPiece. Tällöin vain lisätään palikan y-koordinaattiin painovoimamuuttujan arvo. 1980-luvun lopulta 90-luvun puolivälin tienoille PC-koneiden koteloissa oli usein Turbo-nappula, jonka tarkoitus oli monille epäselvä. Painovoima pannaan täytäntöön metodissa doFall() , jonka logiikka on jaettu kahteen haaraan. Sillä saattoi pudottaa suorittimen kellotaajuuden 80-luvun Intel 8086:n taajuudelle 4,77 megahertsiin tai niille main – juuri sellaisia ohjelmia varten, jotka olivat käyttökelvottomia liian nopeissa koneissa
Tällainen järjestely hämmensi minua alkuun, mutta nähtävästi JavaScript-tulkit on laadittu sillä tavalla, että tästä ei koidu mitään pinon ylivuotoa, vaikka pelisilmukkaa ajettaisiin pitkänkin aikaa. Aluksi otetaan now-muuttujaan talteen aikaleima millisekunteina; TypeScriptissä tyyppi on DOMHighResTimeStamp . Delta-aika siis muuttuu ja elää koko ajan freimistä toiseen. Listaus 3. Pelimoottorien yhteydessä delta-aika tarkoittaa yksinkertaisesti aikaa, joka kunkin freimin laskemiseen ja piirtämiseen kuluu: ”paljonko kello on nyt miinus paljonko kello oli edellisellä freimillä”. Tietueessa meanDt asustaa yksinkertainen rengaspuskuri, jossa säilytetään parinkymmenen viimeisimmän freimin kestoja sekunteina. Monissa 80-luvun laitteissa oli toisaalta yleistä tahdistaa freimit suoraan kuvasignaalin virkistystaajuuteen. Kiinteää askelta käyttämällä valitaan tietty askeleen pituus, ja joka freimillä lasketaan, montako askelta delta-ajan sisälle mahtuu. Tietue lastFrame taas sisältää edellisen freimin ajankohdan millisekunteina. Tästä syystä monet Commodore 64:n, Nintendon ja Amigan pelit pyörivätkin hieman eri nopeuksilla koneiden PALja NTSC-versioilla, sillä PALsignaalin taajuus on 50 Hz ja NTSC:n 60 Hz. Näin pelin logiikka saadaan toimimaan yhteneväisesti riippumatta siitä, päivittyykö käyttäjän näyttö 30, 60 tai vaikkapa 144 kertaa sekunnissa. Tämä on yksinkertaisempi toteuttaa, mutta jos delta-aika sattuu välillä venymään kovin pitkäksi, pelin simulaatio saattaa rikkoutua yllättävillä tavoilla. Monissa valmiissa pelimoottoreissa delta-aikaa ei tarvitse itse laskea, vaan sen voi poimia suoraan moottorin ohjelmointirajapinnasta, esimerkiksi Unityssä muuttujasta Time. Ensin mainittu palauttaa tammikuun alusta 1970, jälkimmäinen taas ajanhetkestä Performance.timeOrigin kuluneiden millisekuntien määrän. Delta-aika syötetään rengaspuskuriin ja annetaan alempana argumentiksi doFall()metodille. deltaTime . Haluamme edelleen pitää suurimman sallitun putoamisnopeuden määritelmänä sitä, että palikka putoaa koko ruudun korkeuden yhden freimin aikana, mutta emme tiedä yhden freimin pituutta etukäteen, joten tämä ei olekaan enää vakio. Seuraavilla freimeillä update() -metodi kutsuu aina lopuksi itseään uudelleen requestAnimationFrame() -funktion kautta ikään kuin rekursiivisesti. Hienoissa pelimoottoreissa voi myös ajaa pelin simulaatiota, syötteiden keräystä, kuvan piirtoa, verkkoliikennettä, äänen miksausta ynnä muuta rinnakkain kokonaan eri säikeissä, mutta ei mennä siihen nyt ollenkaan. // constants.ts: // riviä sekunnissa export const STARTING_GRAVITY = 1.5; // tason noustessa kerrotaan painovoima tällä export const LEVEL_UP_GRAVITY_FACTOR = 1.4; export const SOFTDROP_GRAVITY = STARTING_GRAVITY * 16; Nyt emme enää määrittele vakiota MAX_GRAVITY . Delta-aika käyttöön Freimien kestolle agnostinen pelilogiikka saadaan aikaan käyttämällä delta-aikaa. Monotoninen aika tarkoittaa ajanlaskua, johon eivät vaikuta sellaiset asiat kuin karkauspäivät, karkaussekunnit, kesäja talviaika, aikavyöhyke tai tietokoneen kellonajan muutokset joko manuaalisesti tai NTP:n kautta. Monotonisesta kellosta on tapana ottaa pelkistettyjä kiintopisteitä aikavertailuja varten, kun kellonajalla tai päivämäärällä ei itsessään ole merkitystä, vaan ajankulun lineaarinen jatkuvuus on pääasia. Delta-aika voidaan toteuttaa joko kiinteällä tai muuttuvalla simulaatioaskeleella. Aluksi pitää määritellä kaikki nopeudet uudestaan sekunnin suhteen. Yksinkertaisuuden nimissä valitsemme TS Tetrikselle muuttuvan simulaatioaskeleen. Listauksesta 4 nähdään, että pelisilmukka on siirretty play() -metodista erilliseen update() -metodiin. Tetriksessä asialla ei ole juuri merkitystä, koska jokaisen freimin kesto on käytännössä aina sama, mutta monimutkaisemmissa peleissä erilaiset koneet, pelitilanteet ja kulloinkin ruudulla olevat assetit voivat tuottaa eripituisia freimejä. Tehdään asiallisempi pelisilmukka käyttämällä JavaScriptin funktiota requestAnimationFrame() , joka ottaa ainoaksi argumentikseen funktion, joka halutaan ajaa seuraavalla freimillä. Meidän ei tarvitse tietää, milloin seuraava freimi on tai kuinka usein freimejä on saatavilla, vaan selain hoitaa tämän kaiken meidän puolestamme. Sitten simuloidaan peliä niin monta askelta kuin voidaan. Jotta pelimaailman logiikka toimii aina samalla nopeudella riippumatta olosuhteista, pelin lainalaisuudet pitää käsitteellistää uudelleen niin, että ne eivät pohjaudu vakioina yksi yhteen suhteessa freimeihin, vaan oikeasti kuluviin sekunteihin. Nyt pelin käynnistyessä play() -metodi vain kutsuu requestAnimationFrame() -funktiota ja antaa sille parametriksi metodin this.update . Game-luokkaan on lisätty tietueet meanDt ja lastFrame . Muuttuvan askeleen mallissa taas delta-aikaa käytetään suoraan simulaatioaskeleen pituutena. Amigan aikaa käsiteltiinkin Aikasarjassa aiemmin Skrollissa 2023.3. Yksi freimi, kiitos No niin, asiaan. Delta-aikaan saattaa sisältyä myös teknisistä syistä, esimerkiksi pelin asetuksissa säädetystä maksimiruutunopeudesta tai vsyncistä johtuvaa odottelua. Monotoninen kello Aivan update()-metodin alussa pelisilmukkaan on tuotu mukaan pari uutta juttua. En ymmärrä, miten tämä toimii, mutta yritän suhtautua tyyneydellä. Kreikkalainen kirjain . Listauksessa 3 on uudet vakiot. Meitä ei kiinnosta varsinainen kellonaika, joten emme käytä metodia Date.now() vaan niin sanottua monotonista aikaa tarjoavaa metodia performance.now() . Update() -metodissa lasketaan muuttuja dt (deltatime) kaavalla dt = (now this.lastFrame) / 100 0, eli yksinkertaisesti nykyisen ja edellisen freimin aikaleimojen erotus jaetaan tuhannella. Selain tietää, kuinka nopeasti päivittyvä näyttö käyttäjällä on, ja ajastaa haluamamme funktion täysin läpinäkyvästi aina seuraavana tahdissa olevalle freimille. 2024.3 18. eli delta on matematiikasta ja fysiikasta tuttu käsite, joka tarkoittaa muutosta
arvotaan palikat requestAnimationFrame(this.update); } update(): void { const now = performance.now(); const dt = (now this.lastFrame) / 1000; this.meanDt.push(dt); this.lastFrame = now; // ... Matka lasketaan valitsemalla oikea painovoiman arvo sen perusteella, onko softDrop -lippu voimassa, ja kertomalla arvo delta-ajalla. ENSI KERTAAN! Huolestuttavatko lopun ajat tai ajan loput. Alempana putoamismatka lisätään palikan y-koordinaattiin. lastFrame: DOMHighResTimeStamp; meanDt: MeanBuffer; // ... gravity); const maxRows = Math.floor(totalDistance); let counter; for (counter = 0; counter < maxRows && !this. isPieceLanded(); counter++) this.move(Move.Down); const fractionalDistance = totalDistance counter; if (!this.isPieceLanded()) this.currentPiece.position[1] += fractionalDistance; } maybeNextLevel(lines: number): void { this.levelProgress += lines; if (this.levelProgress >= LINES_PER_LEVEL) { this.level++; this.levelProgress = 0; const maxGravity = this.pf.height / this.meanDt. play(): void { // ... // game.ts: class Game { // ... piirretään alkuruutu break; case GameState.Running: if (this.isPieceLanded()) { // ... Listaus 5. Pelin koko koodi on nähtävillä Skrollin GitHub-tilillä, jonka löydät osoitteesta github.com/skrollilehti. Nimesin myös muuttujia uudelleen, toivoakseni hieman helppolukuisempaan suuntaan. Myöhemmin tajusin, että koko if-lause onkin turha, sillä kun totalDistance < 1 , lauseke Math.floor(totalDistance) == , joten alempana olevaa for-silmukkaa ei ajeta ollenkaan, eli samalla koodilla hoituvat molemmat arvovälit. getMean(); this.gravity = Math.min(maxGravity, this.gravity * LEVEL_UP_GRAVITY_FACTOR); } } Listaus 5: aiemmin mainitun meanDt -rengaspuskurin toteutus. Math.max(this.gravity, SOFTDROP_GRAVITY) : this. Tule juttelemaan aiheesta Skrollin lukijakanaville: skrolli.fi/lukijakanavat DoFall() -metodia on muokattu. piirretään pelin tila break; case GameState.GameOver: // ... piirretään game over -ruutu break; case GameState.Paused: // ... piirretään pause-ruutu break; } requestAnimationFrame(this.update); } doFall(dt: number): void { const totalDistance = dt * (this.softDrop . Listaus 4. Delta-ajasta olisi paljon enemmänkin puhuttavaa – tämä juttu käsitteli vain yksinkertaisinta lineaarisen liikkeen laskemista delta-ajan avulla, eikä edes erityisen havainnollisesti, koska Tetris-palikka ei valu sulavasti vaan nytkähtelee rivi kerrallaan. käsitellään laskeutunut palikka } else { this.doFall(dt); } // ... Skrolli-kollegani Mikko Rasa huomautti tarkkanäköisesti, että palikan putoama matka kannattaa laskea jo ennen if-lauseketta, joten siirsin ensin tämän pari riviä ylemmäksi. Epälineaarisille liikkeille aihe on vähän mutkikkaampi, mutta eteenpäin pääsee katsomalla Freya Holmérin erinomaisen videon Lerp smoothing is broken 2 , joka valottaa seikkaperäisesti delta-ajan ja interpoloinnin välisiä pulmia. // types.ts: export class MeanBuffer { times: number[]; idx: number = 0; constructor(len: number) { this.times = Array(len); let tmp = performance.now(); let count = len; const init = () => { if(count-> 0) { const now = performance.now(); this.push((now tmp) / 1000); tmp = now; requestAnimationFrame(init); } }; requestAnimationFrame(init); } getMean(): number { return this.times.reduce((acc, curr) => acc + curr) / this.times.length; } push(x: number): void { this.times[this.idx] = x; this.idx = (this.idx + 1) % this.times.length; } } Tässä jutussa on käsitelty vain ne kohdat koodia, jotka liittyvät delta-ajan toteuttamiseen, ja paljon on jätetty ulkopuolelle. erinäistä valmistelua const drawTiles = this.pf.overlay(this.currentPiece); switch (this.state) { case GameState.Menu: // ... VIITTEET 1 Tetris.wiki tetris.wiki 2 Holmér Freya: Lerp smoothing is broken (Guadalindie 2024) youtu.be/LSNQuFEDOyQ 19. Metodissa maybeNextLevel() lasketaan nyt maksimipainovoima edellä mainitun rengaspuskurin keskiarvon perusteella lausekkeessa const maxGravity = this.pf.height / this.meanDt.getMean() , joka tarkoittaa maxPainovoima = pelikentänKorkeus / nFreiminDt
Kiitti Sony, mutta en osta Unchartedia enää kertaakaan uusiksi. Tämän voi todeta helposti kuuntelemalla 80ja 90-luvuilla tehtyjä CD-prässäyksiä klassikkolevyistä: LP:tä varten tehty nauhoitus kuulostaa sellaisenaan CD:lle siirrettynä ohuelta, koska bassoja pitää vaimentaa. Pidin ratkaisua tuolloin vähän erikoisena, vaikka monet päinvastoin intoilivat siitä kovasti. Ne olivat Anirog Softwaren Bongo ja Skramble. Pelien puolella kyse on kuitenkin varsin usein siitä, että otetaan jokin moderni teknologia-alusta, pulautetaan vanha peli sille ja kutsutaan tätä remasteroinniksi. Filmin rakeisuutta on tässä yhteydessä saatettu siivota koneellisesti, ja osa ohjaajista ei ole voinut vastustaa kiusausta muuttaa joitakin kohtauksia, mutta periaatteessa kyse on samasta teoksesta kuin alkujaankin. Tällä on useimmiten myönteinen vaikutus äänenlaatuun, sillä esimerkiksi LP-levyä varten masterointi on pitänyt tehdä eri tavalla kuin CD-levylle. En tiennyt, että olin nähnyt varhaisen demoversion tulevaisuudesta, vaikkei kukaan vielä puhunut muodikkaasti remasteroinneista. Commodore 64:stä seurasin sitä normaalia suomalaisen polkua Amiga 500:aan ja huomasin, että monesta tutusta pelistä oli saatavilla myös Amigaversiot. PELIT K un sain joulun alla vuonna 1985 Commodore 64:n, siirsin siihen VIC-20:n kasettiaseman ja peliohjaimen. Lopputulos voi vaihdella hurjasti sen mukaan, kuka hommasta on vastuussa: parhaassa tapauksessa pelin alkuperäinen tekijä pyrkii tuottamaan mahdollisimman tyydyttävän elämyksen sekä vanhalle että uudelle yleisölle, huonoimmillaan puikoissa on joku halvimman tarjouksen tehnyt koodipaRemasteroikaa keskenänne. Hemmetin Nintendo Ryhtyessäni konsolipelaajaksi totuin siihen, että uudelle laitteelle tuli, tai ainakin luvattiin, uusi osa tuttua pelisarjaa – Nintendolle Mario, Segalle Sonic ja niin edespäin. Tekniikka eteni Teksti: Mikko Heinonen Kuvankäsittely: Manu Pärssinen Kuvat: Sony (SIEE) aimo harppauksin, joten uusin ja hienoin rauta sai vanhat pelit näyttämään vähän käpyisiltä, vaikka niihinkin tuli kyllä vielä palattua. Kumpikaan ei ollut mikään varsinainen klassikko, mutta oli silti mukava yllätys huomata, että omistin jo valmiiksi vähän ohjelmistoa uudelle koneelleni. 2024.3 20. Lisäksi aikanaan ei ole ollut käytössä yhtä hyviä äänen digitointimahdollisuuksia kuin nykyisin. Super Nintendon julkaisun aikaan Nintendo päivitti sille NESin Mario-pelit Super Mario All-Stars -kokoelmana, jossa vanhojen pelien logiikan päälle oli tehty uudet grafiikat. Samoin huomasin, että Amigan koreammasta grafiikasta huolimatta C64-versiot olivat usein monella tavalla parempia ja pelattavampia. Paikallisen kirjakauppiaan taktiikka oli onnistunut, sillä halvalla ostettu VIC oli sytyttänyt kipinän mikroiluun. Käydessäni pelikasetteja läpi huomasin, että kahdessa VICille ostetussa pelissä oli itse asiassa C64-versio kääntöpuolella. Äänitteiden puolella remasterointi tarkoittaa yleensä sitä, että kaivetaan esiin alkuperäiset studionauhoitukset, käsitellään ne uudelleen ja julkaistaan modernilla medialla. Nykyisin taas tuntuu, ettei muusta puhutakaan, vaikka termi on oikeastaan väärä. Elokuvissa remasteroinnilla taas on perinteisesti tarkoitettu sitä, että alkuperäinen filmikopio digitoidaan paremmalla laadulla ja siirretään uusimmalle digitaaliselle medialle – kuten nyt vaikka Blu-ray-levylle 4K-tarkkuudella. Pelaillessani niitä isä tuli huoneeseen, ja kun selitin tilanteen, hän kysyi saanko ”parannettua” kaikki vanhat pelini samalla tavalla. Nyt saimme hieman alennusta ostaessamme sen kanssa osittain yhteensopivan Kuusnelosen ilman näitä lisälaitteita, vaikka pitkän pennin isä koneesta silti maksoi. Tilanne onneksi muuttui, kun pelitalot alkoivat kehittää pelejä etupäässä 16-bittisille. Minusta NESin pelit kuuluivat NESille juuri sellaisina kuin ne olivat, ja uudelle Nintendolle piti saada uudet Mariot – kuten toki saatiinkin. Pettymys oli käsin kosketeltavaa kun totesin, että kyllä ne pitää enimmäkseen ostaa uudelleen