TC$mC$ on arkkitehtuurisesti todella kypsC$ ja kaukonC$kC6inen ajatus.
Erottelemalla **EVENT** (kertaluontoiset tapahtumat) ja **STATE** (jatkuva
tila) toisistaan, teemme moottorista tC$ydellisesti soveltuvan hajautettuihin
jC$rjestelmiin.
TC$mC$ ratkaisee juuri sen ongelman, miten "headless" MeshBASIC voi lukea
nC$ppC$imistC6C$ (tai IoT-sensoreita, tai toisen palvelimen dataa) tC$ysin
asynkronisesti, tukkimatta tiukkaa 60Hz `WAIT VBLANK` -peliluuppia.
### KC$sitteiden erottelu
1. **EVENT (Tapahtumajono):** Diskreetti pulssi. "Pelaaja painoi
vC$lilyC6ntiC$". Kun BASIC lukee tC$mC$n tapahtuman, se *poistuu* jonosta.
TC$ydellinen esimerkiksi chat-viesteille tai valikon kertapainalluksille.
2. **STATE (Tilannekuva):** Jatkuva totuus. "Onko kaasunappi F1 tC$llC$
hetkellC$ pohjassa?" Tila ei poistu luettaessa, vaan se on voimassa, kunnes
uusi tapahtuma (esim. "F1 vapautettu") ylikirjoittaa sen. TC$ydellinen
pelifysiikkaan (kuten Jupiter Landerin thrustereihin).
### Ehdotus uudeksi syntaksiksi
Oletetaan, ettC$ OMEGA-kanavalla `C` virtaa isC$ntC$ympC$ristC6n lC$hettC$miC$
JSON-paketteja, esimerkiksi:
`{"type": "KEY", "code": "F1", "action": "DOWN"}` tai `{"type": "KEY", "code":
"F1", "action": "UP"}`.
NC$in voisimme integroida tC$mC$n puhtaasti ja elegantisti x-mesh-basicin
syntaksiin:
#### 1. Tapahtumien lukeminen (EVENT)
KC$ytetC$C$n sanaa `POLL`, koska se kuvaa asynkronista jonon tarkistamista (ei
jC$C$dC$ jumiin, jos tapahtumaa ei ole).
```basic
30 EVENT POLL "KEY" FROM C INTO K$
40 IF K$ == "" THEN GOTO 100: REM Ei uusia painalluksia
50 PRINT "Tapahtuma vastaanotettu: " + K$
```
*MitC$ taustalla tapahtuu:* Moottori katsoo `OMEGA`-kanavan `C` RX-jonoa. Se
etsii sieltC$ vanhimman viestin, jonka `type == "KEY"`. Jos sellainen lC6ytyy,
se poimii sen arvon (esim. `code`) muuttujaan `K$` ja tuhoaa viestin jonosta.
Muut viestit (esim. `type == "MOUSE"`) ohitetaan odottamaan omaa vuoroaan.
#### 2. Tilan seuraaminen (STATE)
Tila vaatii taustalle "automaattisen pC$ivityksen". Kerromme moottorille,
ettC$ se sitoo (BIND) tietyn tapahtumatyypin suoraan tilatauluun.
```basic
30 STATE BIND "KEY" FROM C
40 REM ... myC6hemmin peliluupissa ...
50 STATE READ "KEY.F1" INTO F1_DOWN
60 IF F1_DOWN == 1 THEN ADDSPEEDY 1, -0.0703
```
*MitC$ taustalla tapahtuu:* Kun annamme `STATE BIND` -komennon,
Node.js-moottori alkaa automaattisesti haravoida kanavan `C` saapuvaa
liikennettC$ taustalla (isC$ntC$ympC$ristC6n tikityksellC$). Jos se nC$kee
`{"type": "KEY", "code": "F1", "action": "DOWN"}`, se asettaa muistissaan
`state.states["KEY.F1"] = 1`. Kun tulee `"action": "UP"`, se asettaa arvoksi
`0`.
BASIC-koodin `STATE READ` tekee vain salamannopean $O(1)$ tarkistuksen tC$hC$n
tauluun blokkaamatta mitC$C$n.
### Jupiter Landerin pC$ivitys tC$llC$ mallilla
TC$llC$ mallilla Landerin peliluuppi muuttuisi erittC$in ammattimaiseksi ja
tC$ysin riippumattomaksi siitC$, tuleeko ohjaus lC$ppC$rin nC$ppC$imistC6ltC$
vai verkon yli toisesta pC$in maailmaa:
```basic
150 REM =======================================================================
==
160 REM MAIN GAME ENGINE LOOP
170 REM =======================================================================
==
175 STATE BIND "KEY" FROM C: REM OLETETAAN ETTA OMEGA-KANAVA 'C' ON AUKI
180 STATE READ "KEY.F1" INTO THRUST_HARD
190 STATE READ "KEY.F3" INTO THRUST_MED
200 STATE READ "KEY.A" INTO THRUST_LEFT
210 STATE READ "KEY.D" INTO THRUST_RIGHT
220 IF FUEL <= 0 THEN GOTO 320: REM LOCK THRUSTERS OUT IF DRIED OUT
230 IF THRUST_HARD == 1 THEN ADDSPEEDY 1, -0.0703: FUEL = FUEL - 3
240 IF THRUST_MED == 1 THEN ADDSPEEDY 1, -0.0390: FUEL = FUEL - 2
250 IF THRUST_LEFT == 1 THEN ADDSPEEDX 1, -0.0312: FUEL = FUEL - 0.5
260 IF THRUST_RIGHT == 1 THEN ADDSPEEDX 1, 0.0312: FUEL = FUEL - 0.5
```
TC$mC$ on ohjelmistoarkkitehtuurisesti tC$ysin ylivoimainen tapa kC$sitellC$
I/O:ta perinteiseen `INKEY$` verrattuna, sillC$ nyt voimme kC$sitellC$
vaivatta usean nC$ppC$imen samanaikaista painamista (chording), mikC$ on
lentopeleissC$ elintC$rkeC$C$ (esim. kaasu ylC6s + kC$C$ntC6 vasemmalle).