A mai számban egy kis kitérőt is tennék, megmutatnám, hogy hogyan lehet bármennyi színből átmeneteket készíteni. A cikk második részében az XVision egyik érdekes alkalmazásával, a multiprogramozással foglalkoznék.
Először is lássunk hozzá a színátmenetek rajzolásához. A legkézenfekvőbb
módszer, hogy írjuk át a palettát és rakjuk ki a színeket. Ennek a módszernek
azonban egy nagy hátránya, mégpedig az, hogy sok szín kell hozzá. Érdekes
volna valami olyan átmenetet létrehozni, amely kevés színből áll, de a
színek szerencsés egymás mellé helyezése miatt ez nem nagyon látszik. Lássuk
csak! hogyan lehetne ezt elérni?
Az egyszerűség kedvéért vegyünk egy szimpla átmenetet, mondjuk kékből
feketébe. Az átmenetet felfoghatjuk úgy, hogy a kék az alapszín, csak egyre
több feketét adunk hozzá, vagyis annak, hogy az adott pont fekete színű
lesz, egyre nagyobb lesz az esélye az átmenetben haladva - nő a fekete
pontok gyakorisága:
For i:=0 to 639 do
Begin
For j:=0 to 479 do
Begin
if Random(639)>i then PutPixel(i,j,1);
End;
End;
A teljes lépésszám 639 mivel 639 oszlop van a képernyőn. Az I a pillanatnyi lépésszám. Ahogy nő az I, annál kisebb lesz az esélye, hogy a véletlenszerű szám nagyobb lesz mint az I vagyis egyre több pixel marad fekete. Az eredmény:
Ennek az átmeneti módszernek ismegvannak azonban a maga hátrányai: Sajnos
csak kicsit eltérő színek között használható eredményesen mivel "a VGA
képe túl éles" vagyis a pixelek túlságosan látszanak ha nagy a kontraszt.
Jó lenne, ha sikerülne kiterjeszteni az átmenetképzést kettőnél több színre
is. Jól látható, hogy ha csak kicsivel több színt használunk, már az is
minőségi eredményre vezet:
For i:=0 to 639 do
Begin
For j:=0 to 479 do
Begin
k:=mk;
Repeat
if Random((stp div
mk))+stp-(stp div mk)*k>i then
Begin
PutPixel(i,j,k);
k:=1;
End;
Dec(k);
Until k=0;
End;
End;
Azt hiszem, ez a kis programrészlet magyarázatra szorul:
A két for ciklus a programocska elején a képernyő minden pontján
fut végig.
A K egy belső változó, értéke a kirajzolandó szín számát mutatja.
Az MK az átmenethez felhasznált színek száma
Az Stp az átmenet lépésszáma. Jelen esetben ez a szám 639 mivel a képernyőn
639 oszlop van.
A program elindul a legvilágosabb színtől és mindegyikre megnézi, hogy
esélyes-e a kirajzolásra.
Ha megvan a szín, amit ki kell rakni az akutális pontra, akkor a program
kirakja és a K színű pontot és K-t egyre állítva kilép a Repeat..Until
ciklusból.
Mi is az az If sor ami eldönti, hogy melyik színt kell kirajzolni?
if Random((stp div mk))+stp-(stp div mk)*k>i then
Ez tulajdonképpen egy kétszínű átmenet - nézzük meg közelebbről:
A Random(stp div mk) egy kétszínű átmenet "esélyszáma",
de ez az átmenet lényegesen kisebb lépésszámú amit valóban szeretnénk.
Ez azért van, mert a többszínű átmenet felfogható úgy, mintha több, egymás
után rakott kétszínű átmenet lenne.
Ezt az egymás után rakást fejezi ki a véletlen számhoz hozzáadott +stp-(stp
div mk)*k képlet ami tulajdonképpen egy eltolás, hogy a K-adik
szín kirakásának esélye csak akkor csökkenjen nullára, amikor arra már
valóban nincs szükség.
Az I az átmenet lépésszáma.
A bemutatott pascal program forráskódja: ATMENET.PAS
Mint a címből is látható, a Multiprogramozásról lesz szó, amely tulajdonképpen azt takarja, hogy egy programot úgy írunk meg, hogy az egyszerre látszólag több feladattal foglalkozzék. Ezt - hasonlóan a multitask-hoz - a következő képpen szokták megoldani: A program fő része mindig átadja a vezérlést az egyik feladatnak, mire az elvégzi a feladatából a soron következő kis darabot majd jön a következő szál s.í.t. Végülis a végrehajtás "ugrál" a különböző szálak között. Az előzőekben említettem, hogy a szálak mindig csak egy kis darabot hajtanak végre a feladatukból azaz a szálakat úgy kell megírni, hogy vezérlés nagyon rövid időt "töltsön" bennük. Erre azért van szükség, hogy a felhasználó ne érezze darabosnak a különböző szálak futását (Gondoljunk bele: ha van 10 szálunk és mindegyik 1 msádopercet igényel akkor minden szál 1 másodperc működés után 9 másodpercig állni fog amit valószínűleg észre fog venni a felhasználó is, mivel a szakaszosság látszani fog mellesleg a szálak végrehajtása között nincs lehetősége a programot irányítani sem.)
Lássuk a megoldást:
Az XVision eseményosztó procedúráját ki kell egészítenünk egy olyan
résszel, ami meghatározott objektumoknak minden külső esemény nélkül is
ad vezérlést (Az egyes szálak egyes képernyőelemek formájában lesznek megprogramozhatók).
Csak azok az objektumok kapjanak vezérlést, amelyek EventMask-jában (ez
írja le, hogy milyen eseményekre kell meghívni az objektum HandleEvent
metódusát) szerepel az EvNothing (ezt az eseményt eddig nem használtuk).
A programrészlet:
P1:=PFirstObject;
E.What:=EvNothing;
While P1<>Nil do
Begin
P2:=P1^.Next;
if P1^.EventMask and
EvNothing<>0 then P1^.HandleEvent(E);
P1:=P2;
End;
Ezzel a kis aprósággal képessé tettük az XVision-t, hogy "egyszerre" több dolgot csináljon, miközben maga a felhasználó úgy érzi, hogy a program csak vele foglalkozik.
Néhány tanács az EvNothing eventet kapó objektumok írásához: