Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia

Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
Ohjelmisto palveluna, infrastruktuuri palveluna, alusta palveluna, viestintäalusta palveluna, videoneuvottelut palveluna, entä pilvipelaaminen palveluna? Pilvipelaamista (Cloud Gaming) on ​​jo yritetty luoda useita, kuten Googlen äskettäin lanseeraama Stadia. Stadia ei ole uusi WebRTC:ssä, mutta voivatko muut käyttää WebRTC:tä samalla tavalla?

Thanh Nguyen päätti testata tätä mahdollisuutta avoimen lähdekoodin projektissaan CloudRetro. CloudRetro perustuu Pioniin, suosittu Go-pohjainen WebRTC-kirjasto (kiitos Näytetään Pionin kehitystiimin avusta tämän artikkelin valmistelussa). Tässä artikkelissa Thanh antaa yleiskatsauksen projektinsa arkkitehtuuriin ja kertoo myös, mitä hyödyllisiä asioita hän oppi ja mitä haasteita hän kohtasi työssään.

Merkintä

Viime vuonna, kun Google julkisti Stadian, se yllätti minut. Idea on niin ainutlaatuinen ja innovatiivinen, että ihmettelin jatkuvasti, kuinka tämä on edes mahdollista olemassa olevan teknologian avulla. Halu ymmärtää paremmin tätä aihetta sai minut luomaan oman versioni avoimen lähdekoodin pilvipelistä. Tulos oli yksinkertaisesti upea. Alla haluaisin jakaa vuodeni työskentelyprosessin hanke.

TLDR: lyhyt diaversio kohokohdista

Miksi pilvipelaaminen on tulevaisuutta

Uskon, että Cloud Gamingista tulee pian pelien lisäksi myös muiden tietojenkäsittelytieteen alueiden seuraava sukupolvi. Pilvipelaaminen on asiakas/palvelinmallin huippu. Tämä malli maksimoi taustahallinnan ja minimoi käyttöliittymätyön isännöimällä pelilogiikkaa etäpalvelimella ja suoratoistamalla kuvia/ääntä asiakkaalle. Palvelin suorittaa raskaan käsittelyn, joten asiakas ei ole enää laitteistorajoitusten armoilla.

Google Stadia mahdollistaa käytännössä pelaamisen AAA pelit (eli huippuluokan menestyspelit) YouTuben kaltaisessa käyttöliittymässä. Samaa menetelmää voidaan soveltaa muihin raskaisiin offline-sovelluksiin, kuten käyttöjärjestelmään tai 2D/3D-graafiseen suunnitteluun jne. jotta voimme käyttää niitä johdonmukaisesti huonosti toimivissa laitteissa useilla alustoilla.

Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
Tämän tekniikan tulevaisuus: Kuvittele, jos Microsoft Windows 10 toimisi Chrome-selaimessa?

Pilvipelaaminen on teknisesti haastavaa

Pelaaminen on yksi niistä harvoista alueista, joissa vaaditaan jatkuvaa ja nopeaa käyttäjän reagointia. Jos kohtaamme toisinaan 2 sekunnin viiveen sivua napsauttaessa, tämä on hyväksyttävää. Suorat videolähetykset viivästyvät yleensä muutaman sekunnin ajan, mutta tarjoavat silti kohtuullisen käytettävyyden. Jos peli kuitenkin viivästyy usein 500 ms, sitä ei yksinkertaisesti voida pelata. Tavoitteenamme on saavuttaa erittäin alhainen latenssi, jotta syötteen ja median välinen ero on mahdollisimman pieni. Siksi perinteinen lähestymistapa videon suoratoistoon ei sovellu tähän.

Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
Yleinen pilvipelimalli

Avoimen lähdekoodin projekti CloudRetro

Päätin luoda testinäytteen pilvipelistä nähdäkseni, onko tämä kaikki mahdollista näin tiukoilla verkkorajoituksilla. Valitsin Golangin konseptin todisteeksi, koska se oli minulle tutuin kieli ja se sopi hyvin tähän toteutukseen monista muista syistä, kuten myöhemmin huomasin. Go on yksinkertainen ja kehittyy hyvin nopeasti; Go:n kanavat sopivat erinomaisesti monisäikeen hallintaan.

Hanke CloudRetro.io on avoimen lähdekoodin pilvipelipalvelu retropelaamiseen. Projektin tavoitteena on tuoda mukavin pelikokemus perinteisiin retropeleihin ja lisätä moninpeli.
Voit oppia lisää projektista täältä: https://github.com/giongto35/cloud-game.

CloudRetro toiminnallisuus

CloudRetro käyttää retropelejä demonstroidakseen pilvipelaamisen tehoa. Tämän avulla voit saada monia ainutlaatuisia pelikokemuksia.

  • Pelin siirrettävyys
    • Välitön toisto sivua avattaessa; latausta tai asennusta ei tarvita
    • Toimii mobiiliselaimessa, joten sen suorittamiseen ei tarvita ohjelmistoa

  • Peliistunnot voidaan jakaa useille laitteille ja tallentaa pilveen seuraavaa sisäänkirjautumista varten
  • Peliä voidaan suoratoistaa tai sitä voivat pelata useat käyttäjät kerralla:
    • Crowdplay kuten TwitchPlayPokemon, vain enemmän cross-platform ja enemmän reaaliaikaista
    • Offline-pelejä verkossa. Monet käyttäjät voivat pelata ilman verkkoa. Samurai Shodownia voi nyt pelata 2 pelaajaa CloudRetro-verkon kautta

    Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
    Online-moninpelin demoversio eri laitteilla

    infrastruktuuri

    Vaatimukset ja teknologiapino

    Alla on luettelo vaatimuksista, jotka asetin ennen projektin aloittamista.

    1. Yksi pelaaja
    Tämä vaatimus ei ehkä vaikuta liian tärkeältä tai ilmeiseltä täällä, mutta se on yksi tärkeimmistä takeistani, sen avulla pilvipelaaminen pysyy mahdollisimman kaukana perinteisistä suoratoistopalveluista. Jos keskitymme yksinpeliin, voimme päästä eroon keskitetystä palvelimesta tai CDN:stä, koska meidän ei tarvitse suoratoistaa massoja. Sen sijaan, että lähetettäisiin streameja nielupalvelimelle tai välitettäisiin paketteja keskitetylle WebSocket-palvelimelle, palveluvirrat toimitetaan suoraan käyttäjälle peer-to-peer WebRTC-yhteyden kautta.

    2. Pienen latenssin mediavirta
    Stadiasta lukiessani näen WebRTC:n mainittavan usein joissakin artikkeleissa. Ymmärsin, että WebRTC on erinomainen tekniikka ja sopii täydellisesti pilvipelaamiseen. WebRTC on projekti, joka tarjoaa verkkoselaimille ja mobiilisovelluksille reaaliaikaisen viestinnän yksinkertaisen API:n kautta. Se tarjoaa peer-to-peer-yhteyden, on optimoitu medialle, ja siinä on sisäänrakennetut vakiokoodekit, kuten VP8 ja H264.

    Ajattelin parhaan mahdollisen käyttökokemuksen varmistamisen korkealaatuisen grafiikan ylläpitämisen sijaan. Jotkut häviöt ovat hyväksyttäviä algoritmissa. Google Stadiassa on lisävaihe, jolla pienennetään kuvakokoa palvelimella, ja kehykset skaalataan korkeampaan laatuun ennen kuin ne lähetetään vertaisille.

    3. Hajautettu infrastruktuuri maantieteellisellä reitityksellä
    Riippumatta siitä, kuinka optimoitu pakkausalgoritmi ja koodi ovat, verkko on silti ratkaiseva tekijä, joka vaikuttaa eniten latenssiin. Arkkitehtuurissa on oltava mekanismi, joka muodostaa pariliitoksen käyttäjää lähinnä olevan palvelimen kanssa, mikä vähentää edestakaisen matka-aikaa (RTT). Arkkitehtuurissa on oltava yksi koordinaattori ja useita suoratoistopalvelimia, jotka on jaettu ympäri maailmaa: USA:n länsi-, itä-, Eurooppa, Singapore, Kiina. Kaikkien suoratoistopalvelimien on oltava täysin eristettyjä. Järjestelmä voi säätää jakeluaan, kun palvelin liittyy verkkoon tai poistuu siitä. Siten suurella liikenteellä lisäpalvelimien lisääminen mahdollistaa vaakasuuntaisen skaalauksen.

    4. Selaimen yhteensopivuus
    Pilvipelaaminen on parhaimmillaan silloin, kun se vaatii vähiten käyttäjiltä. Tämä tarkoittaa, että se on mahdollista ajaa selaimessa. Selaimet auttavat tekemään pelaamisesta mahdollisimman mukavan käyttäjille ja säästävät heitä ohjelmistojen ja laitteistojen asentamisesta. Selaimet tarjoavat myös monialustaisia ​​toimintoja mobiili- ja työpöytäversioiden välillä. Onneksi WebRTC on hyvin tuettu useissa selaimissa.

    5. Pelin käyttöliittymän ja palvelun selkeä erottelu
    Pidän pilvipelipalvelua alustana. Jokaisen pitäisi pystyä yhdistämään mitä tahansa alustalle. Nyt olen integroinut LibRetro pilvipelipalvelulla, koska LibRetro tarjoaa kauniin peliemulaattorirajapinnan retropeleille, kuten SNES, GBA, PS.

    6. Huoneet moninpeliin, yleisöpeliin ja ulkoiseen linkitykseen (syvälinkki) peliin
    CloudRetro tukee monia uusia pelimuotoja, kuten CrowdPlay ja Online MultiPlayer retropeleille. Jos useat käyttäjät avaavat saman syvälinkin eri tietokoneilla, he näkevät saman pelin käynnissä ja voivat jopa liittyä siihen.

    Lisäksi pelin tilat tallennetaan pilvitallennustilaan. Tämän ansiosta käyttäjät voivat jatkaa pelaamista milloin tahansa millä tahansa muulla laitteella.

    7. Vaakasuora skaalaus
    Kuten mikä tahansa SAAS nykyään, pilvipelaaminen on suunniteltava vaakasuunnassa skaalautuvaksi. Koordinaattori-työntekijä -mallin avulla voit lisätä työntekijöitä palvelemaan enemmän liikennettä.

    8. Ei yhteyttä yhteen pilveen
    CloudRetron infrastruktuuria isännöidään eri pilvipalveluntarjoajilla (Digital Ocean, Alibaba, mukautettu tarjoaja) eri alueilla. Otan käyttöön infrastruktuurin Docker-säilössä ja määritän verkkoasetukset bash-komentosarjan avulla välttääkseni lukittumisen yhteen pilvipalveluntarjoajaan. Yhdistämällä tämän WebRTC:n NAT Traversaliin voimme joustavasti ottaa CloudRetron käyttöön millä tahansa pilvialustalla ja jopa minkä tahansa käyttäjän koneella.

    Arkkitehtoninen suunnittelu

    Työntekijä: (tai yllä mainittu suoratoistopalvelin) moninkertaistaa pelit, suorittaa koodausputken ja suoratoistaa koodatun median käyttäjille. Työntekijäinstanssit ovat hajallaan kaikkialla maailmassa, ja jokainen työntekijä voi käsitellä useita käyttäjäistuntoja samanaikaisesti.

    Koordinaattori: on vastuussa uuden käyttäjän yhdistämisestä striimaukseen sopivimman työntekijän kanssa. Koordinaattori on vuorovaikutuksessa työntekijöiden kanssa WebSocketin kautta.

    Pelitilan tallennus: Keskitetty etämuisti kaikille pelitileille. Tämä tallennustila tarjoaa tärkeitä toimintoja, kuten etätallennus/lataus.

    Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
    CloudRetron huipputason arkkitehtuuri

    Mukautettu komentosarja

    Kun uusi käyttäjä avaa CloudRetron alla olevan kuvan vaiheissa 1 ja 2, koordinaattori ja luettelo käytettävissä olevista työntekijöistä pyydetään ensimmäiselle sivulle. Tämän jälkeen vaiheessa 3 asiakas laskee kaikkien ehdokkaiden viiveet HTTP-ping-pyynnön avulla. Tämä luettelo viiveistä lähetetään sitten takaisin koordinaattorille, jotta hän voi määrittää sopivimman työntekijän käyttäjää palvelemaan. Vaihe 4 alla luo pelin. WebRTC-suoratoistoyhteys muodostetaan käyttäjän ja määrätyn työntekijän välille.
    Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
    Käyttäjän komentosarja käyttöoikeuden saamisen jälkeen

    Mitä työntekijän sisällä on

    Peli- ja suoratoistoputkistot tallennetaan työntekijän sisään eristyksissä ja vaihtavat siellä tietoja käyttöliittymän kautta. Tällä hetkellä tämä tiedonsiirto tapahtuu siirtämällä tietoja muistissa kautta Golang-kanavat samassa prosessissa. Seuraava tavoite on segregaatio, ts. pelin itsenäinen käynnistäminen toisessa prosessissa.

    Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
    Työntekijöiden osien vuorovaikutus

    Pääkomponentit:

    • WebRTC: asiakaskomponentti, joka hyväksyy käyttäjän syötteen ja tulostaa koodattua mediaa palvelimelta.
    • Peliemulaattori: pelin komponentti. Libretro-kirjaston ansiosta järjestelmä pystyy ajamaan peliä saman prosessin sisällä ja sieppaamaan sisäisesti mediaa ja syöttövirtaa.
    • Pelin sisäiset kehykset kaapataan ja lähetetään kooderiin.
    • Kuva-/äänikooderi: koodausliukuhihna, joka ottaa mediakehykset, koodaa ne taustalla ja tulostaa koodattuja kuvia/ääntä.

    Реализация

    CloudRetro luottaa WebRTC:hen runkoteknologiaansa, joten ennen kuin sukeltaa Golangin toteutuksen yksityiskohtiin, päätin puhua itse WebRTC:stä. Tämä on hämmästyttävä tekniikka, joka on auttanut minua suuresti saavuttamaan alle sekunnin viiveen suoratoistolle.

    WebRTC

    WebRTC on suunniteltu tarjoamaan korkealaatuisia vertaisyhteyksiä alkuperäisissä mobiilisovelluksissa ja selaimissa yksinkertaisia ​​API:ita käyttäen.

    NAT Traversal

    WebRTC tunnetaan NAT Traversal -toiminnastaan. WebRTC on suunniteltu peer-to-peer-viestintään. Sen tavoitteena on löytää sopivin suora reitti välttäen NAT-yhdyskäytäviä ja palomuureja vertaisviestintään ns. ICE. Osana tätä prosessia WebRTC API:t löytävät julkisen IP-osoitteesi STUN-palvelimien avulla ja välittävät sen välityspalvelimelle (VUORO), kun suoraa yhteyttä ei voida muodostaa.

    CloudRetro ei kuitenkaan hyödynnä tätä ominaisuutta täysin. Sen vertaisyhteyksiä ei ole käyttäjien välillä, vaan käyttäjien ja pilvipalvelimien välillä. Mallin palvelinpuolella on vähemmän suoraa viestintää koskevia rajoituksia kuin tavallisella käyttäjälaitteella. Tämän avulla voit avata saapuvia portteja etukäteen tai käyttää julkisia IP-osoitteita suoraan, koska palvelin ei ole NAT:n takana.

    Aiemmin halusin tehdä projektista pelien jakelualustan Cloud Gamingille. Ajatuksena oli antaa pelien luojille mahdollisuus tarjota pelejä ja suoratoistoresursseja. Ja käyttäjät olisivat vuorovaikutuksessa suoraan palveluntarjoajien kanssa. Tällä hajautetulla tavalla CloudRetro on vain kehys kolmannen osapuolen suoratoistoresurssien yhdistämiseksi käyttäjiin, mikä tekee siitä skaalautuvampaa, kun sitä ei enää isännöidä. WebRTC NAT Traversalin rooli tässä on erittäin tärkeä helpottaa vertaisyhteyden alustusta kolmannen osapuolen suoratoistoresursseissa, mikä helpottaa luojan muodostamista verkkoon.

    Videon pakkaus

    Videon pakkaus on välttämätön osa putkilinjaa ja edistää suuresti sujuvaa kulkua. Vaikka VP8/H264-videokoodauksen kaikkia yksityiskohtia ei tarvitse tietää, käsitteiden ymmärtäminen voi auttaa sinua ymmärtämään suoratoistovideon nopeusasetuksia, korjaamaan odottamatonta toimintaa ja säätämään latenssia.

    Videon pakkaaminen suoratoistopalvelua varten on haastavaa, koska algoritmin on varmistettava, että kokonaiskoodausaika + verkon lähetysaika + dekoodausaika on mahdollisimman pieni. Lisäksi koodausprosessin tulee olla johdonmukainen ja jatkuva. Jotkin koodauksen kompromissit eivät päde – emme esimerkiksi voi suosia pitkiä koodausaikoja pienempien tiedostokokojen ja dekoodausaikojen sijaan tai käyttää epäjohdonmukaista pakkausta.

    Videon pakkaamisen ideana on poistaa tarpeettomat informaatiobitit ja säilyttää samalla käyttäjien hyväksyttävä tarkkuustaso. Sen lisäksi, että algoritmi koodaa yksittäisiä staattisia kuvakehyksiä, se päättelee nykyisen kehyksen edellisestä ja seuraavasta, joten vain niiden ero lähetetään. Kuten Pacmanin esimerkistä voidaan nähdä, vain differentiaalipisteet lähetetään.

    Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
    Videokehysten vertailu käyttämällä Pacmania esimerkkinä

    Äänen pakkaus

    Samoin äänenpakkausalgoritmi jättää pois tiedot, joita ihmiset eivät voi havaita. Opus on tällä hetkellä parhaiten suoriutuva audiokoodekki. Se on suunniteltu lähettämään ääniaalto tilatun datagrammiprotokollan, kuten RTP (Real Time Transport Protocol) kautta. Sen latenssi on pienempi kuin mp3 ja aac, ja laatu on parempi. Latenssi on yleensä noin 5-66,5 ms.

    Pion, WebRTC Golangissa

    pion on avoimen lähdekoodin projekti, joka tuo WebRTC:n Golangiin. C++ WebRTC -kirjastojen tavanomaisen kääreen sijaan Pion on WebRTC:n natiivi Golang-toteutus, jolla on parempi suorituskyky, Go-integraatio ja versionhallinta WebRTC-protokollassa.

    Kirjasto mahdollistaa myös suoratoiston useilla upeilla sisäänrakennetuilla toiminnoilla alle sekunnin viiveellä. Sillä on oma STUN-, DTLS-, SCTP- jne. ja joitain QUIC:n ja WebAssemblyn kokeiluja. Tämä avoimen lähdekoodin kirjasto itsessään on todella hyvä oppimisresurssi, jossa on erinomaista dokumentaatiota, verkkoprotokollatoteutuksia ja hienoja esimerkkejä.

    Pion-yhteisö, jota johtaa erittäin intohimoinen tekijä, on melko vilkas, ja WebRTC:stä käydään paljon laadukasta keskustelua. Jos olet kiinnostunut tästä tekniikasta, liity http://pion.ly/slack – Opit paljon uutta.

    CloudRetron kirjoittaminen Golangissa

    Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
    Työntekijän käyttöönotto Gossa

    Siirry kanaviin toiminnassa

    Go:n kauniin kanavasuunnittelun ansiosta tapahtumien suoratoiston ja samanaikaisuuden ongelmat yksinkertaistuvat huomattavasti. Kuten kaaviossa, eri GoRoutineissa on useita komponentteja, jotka toimivat rinnakkain. Jokainen komponentti hallitsee tilaansa ja kommunikoi kanavien kautta. Golangin valikoiva väite pakottaa yhden atomitapahtuman käsittelemään joka kerta pelissä (pelin rasti). Tämä tarkoittaa, että tätä mallia varten ei tarvita lukitusta. Esimerkiksi kun käyttäjä tallentaa, vaaditaan täydellinen tilannekuva pelin tilasta. Tämän tilan tulee pysyä jatkuvana ja kirjautua sisään, kunnes tallennus on valmis. Jokaisen pelin rastituksen aikana taustaosa voi käsitellä vain tallennus- tai syöttötoimintoa, mikä tekee prosessisäikeestä turvallisen.

    func (e *gameEmulator) gameUpdate() {
    for {
    	select {
    		case <-e.saveOperation:
    			e.saveGameState()
    		case key := <-e.input:
    			e.updateGameState(key)
    		case <-e.done:
    			e.close()
    			return
    	}
        }
    }

    Tuuletus sisään/ulos

    Tämä Golang-malli sopii täydellisesti CrowdPlay- ja Multiple Player -käyttötapaukseeni. Tämän mallin mukaisesti kaikki yhden huoneen käyttäjätulot on rakennettu keskitulokanavaan. Pelimedia otetaan sitten käyttöön kaikille käyttäjille samassa huoneessa. Tällä tavalla saavutamme pelitilan jakamisen eri käyttäjien useiden pelisessioiden kesken.

    Avoimen lähdekoodin pilvipelaaminen WebRTC:ssä: p2p, moninpeli, nolla latenssia
    Synkronointi eri istuntojen välillä

    Golangin haitat

    Golang ei ole täydellinen. Kanava on hidas. Estoon verrattuna Go-kanava on yksinkertaisesti helpompi tapa käsitellä samanaikaisia ​​ja ketjutettuja tapahtumia, mutta kanava ei tarjoa parasta suorituskykyä. Kanavan alla on monimutkainen estologiikka. Joten tein joitain muutoksia toteutukseen, ottamalla uudelleen käyttöön lukkoja ja atomiarvoja kanavien vaihdon yhteydessä suorituskyvyn optimoimiseksi.

    Lisäksi Golangin roskakori on hallitsematon, mikä aiheuttaa toisinaan epäilyttävän pitkiä taukoja. Tämä häiritsee suuresti reaaliaikaista suoratoistosovellusta.

    CGO

    Projekti käyttää olemassa olevaa avoimen lähdekoodin Golang VP8/H264 -kirjastoa median pakkaamiseen ja Libretroa peliemulaattoreihin. Kaikki nämä kirjastot ovat yksinkertaisesti Go-kirjaston C-kirjaston kääreitä CGO. Jotkut haitoista on lueteltu kohdassa tämä Dave Cheneyn postaus. Kohtaamiani ongelmia:

    • kyvyttömyys saada kiinni CGO:ssa kaatumiseen edes Golang RecoveryCrashilla;
    • epäonnistuminen suorituskyvyn pullonkaulojen tunnistamisessa, kun emme pysty havaitsemaan yksityiskohtaisia ​​ongelmia CGO:ssa.

    Johtopäätös

    Saavutin tavoitteeni ymmärtää pilvipelipalveluita ja luoda alustan, joka auttaa minua pelaamaan nostalgisia retropelejä ystävieni kanssa verkossa. Tämä projekti ei olisi ollut mahdollinen ilman Pion-kirjastoa ja Pion-yhteisön tukea. Olen erittäin kiitollinen sen intensiivisestä kehittämisestä. WebRTC:n ja Pionin tarjoamat yksinkertaiset API:t varmistivat saumattoman integraation. Ensimmäinen todiste konseptistani julkaistiin samalla viikolla, vaikka minulla ei ollut aiempaa tietoa vertaisviestinnästä (P2P).

    Integroinnin helppoudesta huolimatta P2P-suoratoisto on todellakin erittäin monimutkainen tietotekniikan ala. Hänen on kohdattava pitkäaikaisten verkkoarkkitehtuurien, kuten IP ja NAT, monimutkaisuus luodakseen vertaisistunnon. Työskennellessäni tämän projektin parissa sain paljon arvokasta tietoa verkottumisesta ja suorituskyvyn optimoinnista, joten rohkaisen kaikkia kokeilemaan P2P-tuotteiden rakentamista WebRTC:n avulla.

    CloudRetro palvelee kaikkia käyttötapauksia, joita odotin retropelaajan näkökulmasta. Uskon kuitenkin, että projektissa on monia asioita, joita voin parantaa, kuten verkon luotettavuuden ja suorituskyvyn parantaminen, laadukkaamman peligrafiikan tarjoaminen tai mahdollisuus jakaa pelejä käyttäjien välillä. Työskentelen kovasti tämän eteen. Seuraa, ole hyvä hanke ja tue sitä, jos pidät siitä.

Lähde: will.com

Lisää kommentti