Az úgy volt, hogy békés, délutánba nyúló szombati ebédem közepette felhívott R4S (főszerkesztő), hogy ugyanmár vasárnapra vigyem má' a két cikket. (Igaz, hogy már két hete emlegette, de nem szoktaml komolyan venni). Szóval így esett, hogy teli hassal, befeküdtem a számítógép elé, és elkezdtem igen aktívan gondolkozni, ugyan mit is kéne csinálni. Aktív, szunyálásokkal tűzdelt gondolkodásom közben, mi történik? Elindult a Dos Navigátor egyik screensavere. Tudod, az a pontforgatós, szövegírogatós. Endzsoj dos navigator, meg ilyenek. Na, ilyet én is tudok! Aztán már csináltam is. Igy esett, hogy most ez lesz a téma. Olvasói levelek is érkeztek ám hozzám, ezúttal is köszi, a d3d-ről, meg ilyenekről érdeklődtek. Az a helyzet hogy ilyen nagy lélegzetű témákhoz most nem éreztem elég erőt magamban. (más szóval még nem sok közöm van hozzá) De az ötlet jó, majd igyekszem jobban belemélyedni a témába. Most azonban jöjjön aminek jönnie kell.
Az az ominózus screen saver.
Mit is csinál ez a progi. Van egy ponthalmaz, amit térben forgat, és vele együtt egy kicsit sinusz hullámozó pörgő forgó kifele úszó térbeli szöveget. Meg közben van egy kis motion blur is. Sima Liba. Mit is nézzünk először. Mondjuk a legegyszerűbbet.
A motion Blur ról már volt szó. Akkor a paletta sötétítésével próbáltam megoldani a problémát, mondjuk lehet hogy hülyeség volt. Most más módszert nézünk. Végigmászunk az egész képernyőn, és ahol nem nulla a szín, ott kivonunk belőle egyet. Nem nehéz rájönni, hogy így megspóroltuk a képernyőtörlést. A következő fázist, pedig simán felnyomjuk a képre. Ehez egy világosodó paletta kell. Most az egyszerűség kedvéért 4 színű palettát használtam. Ja, gondolom mindenki örömére szolgál, hogy a progi ezúttal pascalban született. Tehát egy olyan rutin ami ezt elvégzi:
procedure blur; assembler;
asm
push ds
mov ds, ScreenSeg
xor si,si
mov cx,64000
mov al,0
@cik:
cmp [si],al
jz @tov
mov ah,[si]
dec ah
mov [si],ah
@tov:
inc si
loop @cik
pop ds
end;
Ez egyszerű. Modjuk a rutin enyhén szólva nincs optimalizálva, de legalább működik.
A ponthalmaz kirakása is nagyon egyszerű. az ember fog egy tömböt, ami a pontok koordinátáit tartalmazza, megforgatja, egymás után kirakja. A koordináták tárolására olyan rekordot használok, ami egyszerre tartalmazza az eredeti 3d-s, megforgatott 3d-s, és a leképezett képernyőkoordinátákat.
Type
T3d=Record
x : longint;
y : longint;
z : longint;
end;
T2d=Record
x : longint;
y : longint;
end;
Tpoint = Record
map : T3d; {eredeti }
coords : T3d; {forgatott}
ScreenCoords : T2d; {lekepezett}
end;
A pontok feltöltése simán randommal megy, nem kell rajta sokat vacakolni. Két kitüntetett pont van, az 1. és a 2. ezekre majd akkor lesz szükség, mikor a szöveget rá kell illeszteni a ponthalmazra.
Magát a forgatást nem magyarázom el, ugyanaz, ahogy eddig csináltuk.
Ami viszont érdekes, hogy honnan lesz fontkészletünk, amivel írogatni tudunk. Lehet eltároni külön file-ban, vagy belelinkelni az exe-be. De legegyszerűbb lekérdezni a BIOS-tól. mondjuk a 8X8-asat.
Procedure GetCharSet(buffer
: word); Assembler;
asm
push ds
push es
push bp
mov ax,1130h
mov bh,03h
int 10h
mov cx,2048
mov si,bp
pop bp
push es
push ds
pop es
pop ds
mov di,buffer
rep movsb
pop es
pop ds
end;
Ez a Get EGA Information nevű funkció.
ax= 1130
bh=fontkészlet (0,1-aktuális fontkészlet, 2-8X14, 3-8X8,
5-9X14)
Az es:bp-n kapjuk meg a kért készlet címét, amit nem árt gyorsan megmenteni magunknak. A bp-vel vigyázni kell, hiszen a magasszintű nyelvek ezzel címzik a paramétereket, ezért, ha paraméterre hivatkozunk előtte vissza kell állítani.
Az érdekes az, hogy hogyan tudunk a kétdimenziós bittérképből 3 dimenziós objektumot csinálni:
const ztab : array[1..8] of integer=(8,6,3,2,2,3,6,8);
function bitset(d : byte;
b : byte) : boolean;
begin
if (d and (1
shl b))<>0 then bitset:=true else bitset:=false;
end;
procedure buildtext;
var
cnx,cny,actchar : integer;
chx,chy,tp :integer;
begin
cny:=4;
cnx:=-160;
tp:=1;
for actchar:=1
to length(szoveg[actsor]) do
begin
for chx:=1
to 8 do
for chy:=1
to 8 do
begin
if bitset(charset[8*word(szoveg[actsor][actchar])+chy],chx) then
begin
text[tp].map.x:=(actchar*8-chx)*4-cnx;
text[tp].map.y:=(chy-1)*4-cny;
text[tp].map.z:=ztab[chx];
tp:=tp+1;
end;
end;
end;
tpoints:=tp-1;
end;
Végig kell menni az adott karakter bitmapjén, ahol az adott bit 1, ott mi is beleteszünk egy pontot a 3d-s tömbünkbe. A z koordinátáját pedig egy előzőleg feltöltött tömbből vesszük. A karakteren belül minden oszlopban ugyanannyi a Z, mivel a tömbben egy 'púp' van, így a betűk térben egy kicsit púposak lesznek. Persze nem egy karakert tárolunk egyben, hanem egy sort. A szöveg kitolása is egyszerűbb így, hiszen mindig elég csak a map-mezők x-ét növelni.
A szöveg kirakása, forgatása így már majdnem ugyanúgy történik, mint a pontoké, azzal a különbséggel, hogy itt egy pont nem egy pont, hanem egy olyan nagy gümecs, hogy a betűk tényleg térbeliek legyenek.
És forgatásnál beleteszünk egy kis sinust.
Asszem ennyi.