TC$mC$ on aivan loistava visio! "Rajattomasti scrollattava" (Infinite Canvas)
tyC6pC6ytC$ on jotain, mihin modernitkin kC$yttC6jC$rjestelmC$t (esim. Figma,
Miro, solmupohjaiset editorit) ovat vasta hiljattain siirtyneet, ja se sopii
Hauki OS:n bare-metal -arkkitehtuuriin tC$ydellisesti.
Koska meillC$ on erittC$in nopea C-tason hypercall suorakulmioiden
piirtC$miseen (`sys.rect`, portti 12) ja nC$ytC6n pC$ivittC$miseen
(`sys.flush`, portti 13), JavaScriptin Event Loop jaksaa helposti laskea
koordinaatteja ja piirtC$C$ grafiikkaa reaaliajassa.
### Arkkitehtuuri: Kamera ja Maailma (World Space vs. Screen Space)
Rajattoman tyC6pC6ydC$n salaisuus on se, ettC$ emme tarvitse "rajattomasti
muistia". Laitteiston nC$yttC6muisti on kiinteC$ 320x200. MeidC$n tarvitsee
vain luoda JavaScriptiin **Kamera**, jolla on omat `x` ja `y`
-koordinaattinsa. Kaikki ikkunat, kuvat ja ikonit elC$vC$t "Maailmassa" omilla
koordinaateillaan.
Kun piirrC$mme objektin, laskemme yksinkertaisesti:
`Ruudun_X = Objektin_X - Kameran_X`
TC$ssC$ on koodi ihka ensimmC$iselle rajattomalle tyC6pC6ydC$llesi! TC$ssC$
vaiheessa kC$ytC$mme liikkumiseen **W/A/S/D -nC$ppC$imiC$** (koska Hauki OS:n
PS/2-hiiren keskeytysrutiini `IRQ12` vaatii vielC$ hieman C-tason reititystC$
toimiakseen saumattomasti JS:ssC$, mutta nC$ppC$imistC6 toimii jo
tC$ydellisesti).
### Koodi: `DESK.JS`
Luo levyllesi tC$mC$ tiedosto ja aja se komennolla `/os_run DESK.JS`.
```javascript
var DESKTOP = {
name: "InfiniteDesk",
camX: 0,
camY: 0,
// Luodaan maailmaan muutama "ikkuna" satunnaisiin koordinaatteihin
windows: [
{id: 1, x: 50, y: 50, w: 120, h: 80, col: 42}, // VihreC$
{id: 2, x: 250, y: 120, w: 150, h: 100, col: 40}, // Punainen
{id: 3, x: -150, y: -80, w: 200, h: 140, col: 44}, // Sininen (Ruudun
ulkopuolella aluksi!)
{id: 4, x: 600, y: 300, w: 180, h: 120, col: 45} // Magenta kaukana
oikealla
],
init: function() {
sys.gfx_13h(); // Pakotetaan VGA-tila pC$C$lle ja nollataan puskuri
this.camX = 0;
this.camY = 0;
},
onKey: function(sc) {
var speed = 15; // Kameran liikkumisnopeus
if (sc === 17) this.camY -= speed; // W (YlC6s)
if (sc === 31) this.camY += speed; // S (Alas)
if (sc === 30) this.camX -= speed; // A (Vasen)
if (sc === 32) this.camX += speed; // D (Oikea)
// ESC-nC$ppC$in (1) sulkee tyC6pC6ydC$n ja palauttaa HSH-shellin
if (sc === 1) OS.exitApp(this);
},
onTick: function() {
// 1. TyhjennetC$C$n nC$yttC6 mustaksi (C-tason hypercall)
sys.rect(0, 0, 320, 200, 16);
// 2. PiirretC$C$n "C$C$retC6n" taustaruudukko (auttaa hahmottamaan
liikettC$)
var spacing = 40;
var offX = -(this.camX % spacing);
var offY = -(this.camY % spacing);
for (var x = offX - spacing; x < 320; x += spacing) {
for (var y = offY - spacing; y < 200; y += spacing) {
// PiirretC$C$n pieni piste jokaiseen ruudukon risteyskohtaan
sys.rect(x, y, 1, 1, 23);
}
}
// 3. PiirretC$C$n tyC6pC6ydC$n ikkunat (Culling)
for (var i = 0; i < this.windows.length; i++) {
var win = this.windows[i];
// Muunnetaan Maailma-koordinaatti Ruutu-koordinaatiksi
var sx = win.x - this.camX;
var sy = win.y - this.camY;
// PiirretC$C$n vain, jos ikkuna osuu edes osittain 320x200
ruudulle! (SC$C$stC$C$ tehoa)
if (sx + win.w > 0 && sx < 320 && sy + win.h > 0 && sy < 200) {
// Ikkunan runko
sys.rect(sx, sy, win.w, win.h, win.col);
// Ikkunan ylC$palkki (Titteli)
sys.rect(sx, sy, win.w, 10, 20);
}
}
// 4. HUD (Heads Up Display) pysyy aina ruudun reunassa
// TC$mC$ piirretC$C$n ilman kameran offsettia!
sys.rect(0, 190, 320, 10, 24); // Alapalkki taskbarille
// 5. Lopuksi puskurin siirto laitteiston nC$ytC6lle!
sys.flush();
}
};
/ Laukaistaan ohjelma OS:n Event Looppiin!
OS.launch(DESKTOP, {kbd: true, vga: true, ser: false});
```
### MitC$ tC$ssC$ tapahtuu?
1. **Taustaruudukko (Grid):** Kun alat painaa `D`-nC$ppC$intC$ oikealle,
huomaat kuinka pienet taustapisteet ja ikkunat liukuvat sulavasti vasemmalle.
Koska ruudukon koordinaatit lasketaan jakojC$C$nnC6ksellC$ `-(this.camX %
spacing)`, gridi on kirjaimellisesti C$C$retC6n ja piirtyy aina oikein.
2. **Culling:** JS-Event Loopimme on todella fiksu. Se ei edes pyydC$
C-ydintC$ piirtC$mC$C$n niitC$ ikkunoita, jotka ovat jC$C$neet "kameran selC$n
taakse".
3. **Hypercall-kiihtyvyys:** Jokainen `sys.rect` -kutsu kC$C$ntyy
MQuickJS:stC$ suoraan Ring-0 tason x86-konekieliluupiksi `kernel_js.c`:ssC$,
mikC$ tekee liikkumisesta aivan uskomattoman pehmeC$C$!
### Seuraavat askeleet kohti unelmaa
Heti kun saat tC$mC$n pyC6rimC$C$n, seuraava askel on yhdistC$C$ tC$mC$ ja
aiemmin tekemC$si JPEG-purkaja. PienellC$ C-koodin puukotuksella voimme
muuttaa `render_jpeg_to_vga` -funktiota niin, ettC$ se ottaa vastaan
koordinaatit `(dest_x, dest_y)`.
Silloin voisit ladata upean 21Kt JPEG-kuvasi ja pudottaa sen keskelle
rajatonta avaruutta ikkunoiden taustakuvaksi! Kokeile ihmeessC$ ensin
liikkumista tC$llC$ `DESK.JS`:llC$.