Je tu další díl seriálu pro všechny, kteří ještě nemají s programováním žádné zkušenosti. Tentokrát si velice detailně ukážeme, jak by mohlo vypadat primitivní animované menu do případné hry.
Vykreslování v DelphiX
Díl pátý – Tvoříme první větší program
Všichni dobře víte, že tento seriál je pro skutečně největší začátečníky. Ukážeme si proto velice podrobně a krok za krokem jednoduché animované menu do případné počítačové hry.
Funkční menu do počítačové hry
Naprogramujeme si plnohodnotné a hlavně funkční menu do počítačové hry, kterou si po přečtení celého seriálu bude schopna naprogramovat většina z Vás. Výsledky kliknutí na jednotlivé položky budou sice pouze provizorní, ale Vám nic nebrání vyvolat situaci jinou. A v rámci přehlednosti a pochopitelnosti budu pracovat bez cyklů, procedur a funkcí.
Ještě než se pustíme do práce, ukážeme si, jak by mohlo toto menu vypadat (nelekejte se té příšerné grafiky, ta je provizorní a dělal jsem ji už před několika lety; záleží na její funkci):
obr. 1: Naše menu (kliknutím zobrazíte celý obrázek)
1) Nejprve si přepneme program do FullScreenu (celoobrazovkového režimu)
Označte si DXDraw a v Object Inspectoru, pod položkou Options, si přepněte doFullScreen na True. Pokud jste dodrželi to, co jsme si určili v prvním díle, bude vše perfektně fungovat.
2) Nadefinujeme si proměnné (všechny globální). Budou to tyto:
- Integer:
- alpha
- pro průhlednost loga
- ph
- pro periodu zvlnění loga
- angle
- pro natočení ukazatele zvolené položky (pokud jste si zobrazili obrázek, je to takové to sluníčko, které se točí u naposledy aktivního tlačítka)
- pnttop
- pro určení výšky ukazatele zvolené položky
- status
- proměnná, která určí, jestli se má logo skrývat, nebo naopak zneprůhledňovat (mimochodem, je to jedna z možností řešení jednoho domácího úkolu z druhé části tohoto seriálu)
- TRect:
- opt1, opt2, opt3
- obdélníky sloužící jako vykreslovací plocha všech tří tlačítek
3) Na řadě jsou obrázky, které budeme potřebovat. Všechny si přidejte do DXImageListu pod těmito jmény:
- Back:
- Pozadí o rozměrech 640 × 480 pixelů (rozlišení musí být rovno rozměrům DXDraw, jinak bude vpravo a dole černý prostor)
- DelphiX:
- Logo hry (u mě 202 × 84 pixelů – pokud se budete vždy držet mých rozměrů, nebudete muset měnit kód)
- Opt1, Opt2, Opt3:
- Jednotlivá tlačítka v menu, přičemž první 2 jsou volby, třetí ukončuje program (u mě 100 × 50 pixelů)
- Pntr:
- Ukazatel zvolené položky (50 × 50 pixelů)
- Cursor:
- Grafický kurzor, který bude zastávat v programu ten windowsowský (30 × 30 pixelů)
Pokud je nechcete kreslit, stáhněte si moje (formát BMP).
4) Teď si ukážeme nové příkazy, které budu používat:
- ptinrect(obdélník, bod);
- Tento příkaz vrací hodnotu typu boolean (ano, nebo ne), která určí, zda je uvedený bod (typu TPoint – například mouse.cursorPos) v daném obdélníku (TRect)
- showmessage('Text');
- Zobrazí okno s textem. Tento příkaz však nemá s DX nic společného. U nás bude sloužit jako náhrada za volanou akci po kliknutí na tlačítko.
5) A teď Vám budu postupně ukazovat kód a vysvětlovat funkci jednotlivých částí. Hlavně se nelekejte. Pro Vás, začátečníky, to může vypadat složitě, ale sami zjistíte, že je to vlastně jednoduché:
Co se děje po startu (událost onCreate našeho formuláře):
procedure TForm1.FormCreate(Sender: TObject);
begin
opt1.Left:=50; // následujících 12 řádků určí rozměry jednotlivých obdélníků; přizpůsobte si je proto rozměrům svých tlačítek
opt1.Right:=150;
opt1.Top:=175;
opt1.Bottom:=225;
opt2.Left:=50;
opt2.Right:=150;
opt2.Top:=250;
opt2.Bottom:=300;
opt3.Left:=50;
opt3.Right:=150;
opt3.Top:=325;
opt3.Bottom:=375;
pnttop:=200; // určí výchozí výšku ukazatele vybrané položky
angle:=0; // určí výchozí natočení ukazatele vybrané položky
ph:=0; // určí výchozí periodu zvlnění loga
alpha:=0; // určí výchozí průhlednost loga
showcursor(false); // schová windowsovský kurzor
end;
Reakce na kliknutí (událost onClick komponenty DXDraw):
procedure TForm1.DXDraw1Click(Sender: TObject);
begin
if ptinrect(opt1, mouse.cursorpos) then showmessage('Volba 1 byla úspěšně potvrzena. Stiskněte ENTER!'); // po kliknutí dovnitř obdélníku opt1 se zobrazí okno s textem
if ptinrect(opt2, mouse.cursorpos) then showmessage('Volba 2 byla úspěšně potvrzena. Stiskněte ENTER!'); // tohle se stane po kliknutí na opt2
if ptinrect(opt3, mouse.cursorpos) then close; // po kliknutí do obdélníku opt3 se program ukončí
end;
Vykreslování (událost onTimer komponenty DXTimer):
procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
if not dxdraw1.CanDraw then exit; // ošetříme chyby kreslení
dxdraw1.Surface.Fill(0); // vyplníme plochu černě
inc(ph, 3); // navýší ph o 3
if ph>255 then ph:=0; // ošetří chybu s překročením integeru
inc(angle); // navýší angle o 1
if angle>255 then angle:=0; // ošetří chybu
if status=0 then // pokud je na řadě zviditelňování loga, udělej toto
begin
inc(alpha); // navýší alpha
if alpha>255 then status:=1; // pokud je logo plně viditelné, přepne se na skrývání
end
else
begin
dec(alpha); // odečte 1 z alpha
if alpha<1 then status:=0; // pokud je logo na hranici viditelnosti, začne se opět zviditelňovat
end;
dximagelist1.Items.find('Back').Draw(dxdraw1.surface, 0, 0, 0); // vykreslí pozadí
dximagelist1.Items.find('DelphiX').DrawWaveXAlpha(dxdraw1.surface, 25, 25, 202, 84, 0, 3, 30, ph, alpha); // vykreslí schovávající se a vlnící se logo
if ptinrect(opt1, mouse.cursorpos) then // pokud je kurzor na tlačítku Volba 1, udělej toto
begin
dximagelist1.Items.find('Opt1').DrawAlpha(dxdraw1.surface, opt1, 0, 255); // zobraz plně viditelné tlačítko
pnttop:=200; // přesuň ukazatel vybrané položky na úroveň tlačítka
end
else dximagelist1.Items.find('Opt1').DrawAlpha(dxdraw1.surface, opt1, 0, 150); // v opačném případě zobraz tlačítko poloprůhledné
if ptinrect(opt2, mouse.cursorpos) then // totéž co v předchozím případě, ale s tlačítkem Volba 2
begin
dximagelist1.Items.find('Opt2').DrawAlpha(dxdraw1.surface, opt2, 0, 255);
pnttop:=275;
end
else dximagelist1.Items.find('Opt2').DrawAlpha(dxdraw1.surface, opt2, 0, 150);
if ptinrect(opt3, mouse.cursorpos) then // totéž co v předchozích případech, ale s tlačítkem pro ukončení
begin
dximagelist1.Items.find('Opt3').DrawAlpha(dxdraw1.surface, opt3, 0, 255);
pnttop:=350;
end
else dximagelist1.Items.find('Opt3').DrawAlpha(dxdraw1.surface, opt3, 0, 150);
dximagelist1.Items.find('Pntr').DrawRotate(dxdraw1.surface, 185, pnttop, 50, 50, 0, 0.5, 0.5, angle); // vykreslí otáčející se ukazatel vybrané položky na spočítané místo
dximagelist1.Items.find('Cursor').Draw(dxdraw1.surface, mouse.CursorPos.x, mouse.CursorPos.y, 0); // vykreslí grafický kurzor
dxdraw1.flip; // a vše to zobrazíme
end;
Ať to vypadá jakkoli složitě a ať je to jakkoli nepřehledné, musíte uznat, že je to vlastně úplně jednoduché. Pokud si chcete něco stáhnout, udělejte to tady (dnes je toho o něco málo víc):
- Výsledný program (již zkompilovaný, nepotřebujete Delphi; je to normální spustitelný exe soubor)
- Zdrojové kódy (opět v Delphi5 – to budou zřejmě pořád)
- (pro ty, co přehlédli výše přítomný odkaz; je to stejná grafika jako v obrázku nahoře)
A tím bych dnešní (myslím, že zatím nejzajímavější) díl ukončil. Zkušení to, doufám, nečtou, začátečníci by měli být spokojeni díky psaní krůčku za krůčkem. Jinak příště se podíváme na vykreslování světel a stínů (DrawSub, DrawAdd a jejich kombinace). Těším se na Vás!