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:

A nagyított ábrán jól látható, hogy valóban a jobboldal felé a fekete pontok egyre sűrűbben helyezkednek el. Most már csak az a kérdés, hogy hogyan lehetne ezt a gyakoriság növekedést programban megírni.
Tulajdonképpen borzasztó egyszerű:
Egy megadott tartományban generált véletlen szám elvileg ugyanakkora gyakorisággal veszi fel a tartomány bármelyik értékét tehát ha azt vizsgálom, hogy a véletlen szám milyen gyakorisággal lesz nagyobb egy tetszőleges számnál, azt láthatom, hogy a gyakoriság csak a tetszőleges szám nagyságától függ (minél nagyobb számot veszek, annál kisebb lesz az esélye, hogy a véletlen szám nála nagyobb legyen).
Mivel ez így van, azt, hogy az X. lépésben fekete vagy kék színt kell-e kiraknunk, egyszerűen eldönthetjük úgy, hogy a teljes lépésszámon veszünk egy véletlen számot és megnézzük, hogy az X kisebb vagy nagyobb-e nála. Lássuk ezt a gyakorlatban (itt az egyszerűség kedvéért fekete az alapszín és kék lesz az, amit hozzáadunk): 

For i:=0 to 639 doBegin   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:

A felső átmenet 5 színből, az alsó átmenet 2 színből áll. Az hiszem, látható a különbség.
Mi is a különbség a 2 és a többszínű átmenetek között?
A kétszínű átmenetek között csak 2 variáció között kell dönteni míg a a többszínű átmenetben több variáció közül kell kiválasztanunk a megfelelőt.
Tegyük fel, hogy a paletta egymás után, világossági sorrendben tartalmazza a felhasználandó színeket.
Itt is azt csináljuk, amit a kétszínű átmenetekben, nevezetesen itt is esélyeket fogunk latolgatni, de azzal az aprócska különbséggel, hogy itt a szín használatának esélye nem csak a lépésszámtól függ, hanem a szín számától is.
Lássuk a gyakorlatban: 

For i:=0 to 639 doBegin   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. 


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 doBegin   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:

  • Az objektum rövid időt töltsön a HandleEvent metódusban
  • Lehetőleg ne rajzoljon minden meghívási alkalommal, hiszen az egeret minden rajzolás előtt kapcsolgatni kell tehát ha a program minden alkalommal rajzol, az egeret szinte sohasem fogjuk látni. (Ez megoldható a TOldObject DrawIt metódusának átírásával, de ez csak akkor működik, ha mi rajzoljuk ki az egérkét.:


  • Procedure TOldObject.DrawIt;Begin   if IsInArea(HiMouseX,HiMouseY,x-30,y-30,w+60,h+60) then Mouse_Hide;   Draw;   Mouse_Show; End;
Itt a vége, fuss el véle