V tomto díle se naučíme rotaci obrázku a zvlnění. Tyto příkazy nevyžadují přítomnost obdélníku, na který se má vykreslovat. Vystačíme si se souřadnicemi jako u standardního vykreslování. Ale na druhou stranu, trochu přitlačíme ve výpočtech.
Vykreslování v DelphiX
Díl třetí – Otáčení a Zvlnění
V tomto díle se naučíme rotaci obrázku a zvlnění. Tyto příkazy nevyžadují přítomnost obdélníku, na který se má vykreslovat. Vystačíme si se souřadnicemi jako u standardního vykreslování. Ale na druhou stranu trochu přitlačíme ve výpočtech.
- Otáčení obrázku
Tento příkaz se nám bude hodit nejen u otáčejících se log, ale třeba i u závodních her viděných ze shora, kde můžeme natočit auto do směru jízdy. Parametry příkazu jsou tentokrát trochu složitější, a vše vypadá strašně složitě, ale já věřím, že s mými vysvětlivkami vše pochopíte bez problémů a zjistíte, že je to vlastně primitivní. Rozeberme tedy příkaz DrawRotate:
TDXImageList.Items[x].DrawRotate(plocha, pozice_x, pozice_y, šířka, výška, část obrázku, střed_x, střed_y, úhel);
pozice_x: Tímto neurčíte vzdálenost okraje, ale vzdálenost středu otáčení (na ose x, takže zleva) - o ose otáčení se dozvíte více v poznámkách
pozice_y: Určí vzdálenost středu otáčení shora; platí to, co u pozice_x
výška: Totéž co u šířky, jenže s výškou
střed_x: Určí výškový střed otáčení (viz poznámka u hvězdičky)
střed_y: Určí šířkový střed otáčení (viz poznámka u hvězdičky)
úhel: Sem dosadíte číslo (nebo proměnnou, která ho obsahuje), které určí natočení obrázku (viz poznámka u dvou hvězdiček)
(*) Sem se nezadává číslo v pixelech, podle vzdálenosti od okraje, ale desetinné číslo odvozené od zlomku. Nebojte se toho, vše vám vysvětlím. Pokud například chcete střed otáčení přesně uprostřed (tedy v jedné polovině), vezmete si zlomek 1/2 a vyčíslíte ho (normálně 1:2). Vyjde Vám číslo 0,5, které dosadíte. Takže pokud chcete střed otáčení ve dvou třetinách, vyčíslíte zlomek 2/3 a vyjde Vám 0,66, a je to. Jednoduché, že? Ale má to háček. V angličtině se nepoužívá desetinná čárka, ale tečka. V praxi to znamená, že dosadíme třeba 0.5 nebo 0.66 apod. My si dosadíme do obou středů otáčení 0.5, aby se nám obrázek otáčel hezky od prostředka.
(**) Úhel není v tomto případě určen stupni, ale jakýmsi indexem, který se pohybuje od 0 do 255. Výpočet je jednoduchý. (255 / 360) * úhel_ve_stupních. Třeba 45 stupňů má tedy po tomto výpočtu ((255 / 360) * 45) a po zaokrouhlení na celé číslo (to je nutné) index 32. Pokud tedy dosadíte 32, bude obrázek natočen o 45 stupňů.
A tady máme konkrétní příklad:
dximagelist1.Items.find('DelphiX').DrawRotate(dxdraw1.surface, 200, 200, 202, 84, 0, 0.5, 0.5, 32); // obrázek se zobrazí natočený přibližně o 45 stupňů (200px odshora a zleva)
Zkuste si to, jak to šlape, měli byste vidět natočený obrázek. A co když chceme, aby se obrázek otáčel pořád? To bude náplní dnešního konkrétního příkladu. Vytvořte si proměnnou „angle“ typu Integer a nastavte ji hodnotu 0 hned po po startu programu (to už umíte z minula - událost onCreate našeho formuláře). Tak. A tady je obsah procedury onTimer:
procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
if not dxdraw1.CanDraw then exit;
dxdraw1.Surface.fill(0);
inc(angle); // navýšíme index úhlu o jeden
if angle>255 then angle:=0; // pokud přesáhne 255, vrátíme ho na nulu (viz poznámka u tří hvězdiček)
dximagelist1.Items.find('DelphiX').DrawRotate(dxdraw1.surface, 200, 200, 202, 84, 0, 0.5, 0.5, angle); // a nakreslíme si to
dxdraw1.flip;
end;
(***) Tento krok není vysloveně nutný, jelikož program to pochopí, a bude pořád otáčet. Jenže může se stát, pokud bude v nějaké aplikaci například neustále rotovat logo, že hodnota proměnné angle přesáhne horní mez Integeru, a program spadne. Pokud ho tedy budeme pravidelně vracet na nulu, této chybě předejdeme.
To je radost! Náš obrázek se krásně točí. Pokud někdo pořád nemá jasno, přikládám opět zdrojový kód programu v Delphi 5.
-A otáčivé obrázky
obr. 1: natočení o 45 stupňů
obr. 2, 3: průběh otáčení obrázku
- Zvlnění obrázku
Doufám, že jste překousli DrawRotate bez větších problémů; teď totiž jdeme na zvlnění. Tento příkaz trochu prověří Váš fyzikální um z doby, kdy jste probírali sinusoidu. To je totiž, jak jistě víte, základ každé vlnovky. A tady si krásně pohrajeme s amplitudou, periodou a šířkou vlny. Drobný rozbor příkazu:
TDXImageList.Items[x].DrawWaveX(plocha, pozice_x, pozice_y, šířka, výška, část obrázku, amplituda, šířka_vlny, perioda);
pozice_x: Zde už opět určuje pozici levého okraje obrázku od levého okraje dxdraw
pozice_y: Totéž, ale od horního okraje
amplituda: Rozdíl, mezi nejvyšším bodem vlny a nejnižším; tedy jde o to, jak bude vlna vysoká (vzhledem k tomu, že se vlní do šířky, tak vlastně dlouhá) - viz nákres
šířka_vlna: Určí, jak bude vlna široká - viz nákres
perioda: Určí stádium zvlnění (pokud tedy budeme toto číslo navyšovat jako u otáčení, bude se obrázek pravidelně vlnit)
obr. 1: schéma vlny - celý tento obrázek představuje jednu periodu
A jako vždy, konkrétní příklad:
dximagelist1.Items.find('DelphiX').DrawWaveX(dxdraw1.surface, 33, 33, 202, 84, 0, 5, 30, 0); // ...a obrázek se zvlní
Je to jasné? Možná jste očekávali, že bude zvlnění animované. A k tomu právě slouží poslední parametr - perioda. Pomocí jejího navyšování dosáhneme neustále se vlnícího obrázku. A to je účelem našeho nového prográmku. Vytvořte si proměnnou „ph“ typu Integer a na onCreate ji nastavte nulu. Samotný zdrojáček vlnění je zde:
procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
if not dxdraw1.CanDraw then exit;
dxdraw1.Surface.Fill(0);
inc(ph, 3); // toto je pro vás možná novinka, navyšuji číslo o tři (kvůli rychlosti)
if ph>255 then ph:=0; // nezbytné ošetření chyby
dximagelist1.items.find('DelphiX').DrawWaveX(dxdraw1.surface, 33, 33, 202, 84, 0, 5, 30, ph); // a vykreslení s vypočítanou periodou
dxdraw1.flip;
end;
Myslím, že i když se to na začátku nezdálo, byla i tato lekce velmi jednoduchá. Než skončím, přidám zdrojový kód (Delphi 5).
-A otáčivé obrázky
obr. 1: detail zvlněného obrázku
obr. 2, 3: průběh animace zvlnění
That's all, folks. Dotazy pište na ICQ#299-545-993 nebo do diskuse. Nashledanou u čtvrtého dílu!