10.12.2002
|
Obsahom dnešnej prednášky je riešenie 2 úloh
zo skúšky v školskom roku 2001/2002. Odporúčam,
aby ste si preriešili čo najviac minuloročných
úloh. Zadania sú na stránke Skúška.
1. príklad: sovy poštárky
Napíšte program, pomocou ktorého sa budeme
môcť zahrať nasledujúcu hru:
- Harry Potter má dostať pozvánku do čarodejníckej
školy. Ako je tu zvykom, listy od čarodejníkov prinášajú
sovy. Muklovia, u ktorých Harry býva, tušia, že v tomto liste
bude pre Harryho niečo dôležité a preto sa snažia tento list
zlikvidovať. Ak by sa totiž aspoň jeden list dostal do rúk Harryho,
odíde od nich. Pani Muklová chytila metlu a snaží sa
pozametať všetky listy pre Harryho, ktoré prinesú sovy. Ak
nejaký list dopadne na úplný spod obrazovky, pani Muklová
tam metlou nedočiahne, list sa dostane Harrymu a teda pani Muklová
bude nešťastná.
- Hracia plocha je veľkosti aspoň 600x500 pixelov a celá je pokrytá
(vykachličkovaná) bitmapou dlazka.bmp. V hornej časti plochy
(nie nižšie ako 100 pixelov) náhodne prilietajú sovy buď zľava doprava alebo
sprava doľava. Sova je animovaná dvoma bitmapami sova1.bmp
a sova2.bmp. Sova drží v pazúroch list (bitmapa list.bmp)
a počas letu niekde, nie bližšie ako 100 pixelov od okraja plochy, list pustí.
Takýto list pomaly padá smerom nadol plochy. Ak sa dostane
aspoň 50 pixelov od spodného okraja plochy, hra končí a vypíše
sa správa, že list sa nám nepodarilo odstrániť a dostal
sa k Harrymu.
- V ploche sa nachádza metla (bitmapa metla.bmp), ktorou
môžeme zametať padajúce listy. Metlu riadime pohybmi myši (zrejme
v udalosti onMouseMove), pričom musíme zabezpečiť, aby sa táto
nedostala vyššie ako 200 pixelov od horného okraja a nižšie ako 50
pixelov od dolného okraja plochy. Keď sa metlou dotkneme nejakého
padajúceho listu, tak tento zmizne. Pozíciou metly rozumieme
stred dolného okraja obrázka metly a dotyk s listom označuje
napr., že metla je od listu vzdialená aspoň 20 pixelov.
- Ak hráč zvládne pozametať nejaký konkrétny
počet listov (napr. konštanta max=100), ďalšie sovy s listami už neprilietavajú
a hra končí pochvalnou správou.
- Všetky bitmapy (okrem dlazka.bmp) majú priesvitné
časti označené farbou biela.
- Sovy sa objavujú v náhodných intervaloch a naraz
by ich nemalo byť v ploche viac ako 10. Lietajú rôznou rýchlosťou
a v náhodnej výške. Krok pohybu nech je náhodné
číslo napr. od 8 do 16. Pri každom tiknutí časovača sa vykreslia
inou fázou animácie. Kým list putuje so sovou, má
zrejme tú istú rýchlosť. Keď ho sova pustí,
zmení sa jeho smer pohybu na zvislý a nastaví sa mu nejaká
náhodná rýchlosť.
- Časovač nastavte napr. na 100 milisekúnd. Pri každom tiknutí
časovača zrealizujte všetky pohyby a prekreslite celú plochu:
- pohnite sovami (odletené sovy z plochy odstráňte z
evidencie)
- ak má nejaká sova pustiť list, tak tento presuňte
do poľa padajúcich listov
- pohnite všetkými listami (môžete testovať, či nejaký
nepreletel do dolnej časti)
- pripadne vygenerujte novú sovu s listom
- vytvorte pozadie (z bitmapy dlazka.bmp)
- nakreslite všetky sovy, listy a na záver metlu
- Pri pohybe myši zabezpečte korektné odstránenie pozametaných
listov z evidencie.
- Vo vašom programe zadefinujte triedy THra, TList
a TSova v samostatnej programovej jednotke (napr. Unit2.pas), pričom sa
tento unit môže odvolávať (uses) len na štandardné delphi-unity
a nesmú v ňom byť definované žiadne globálne premenné.
Štruktúra týchto tried by mala byť približne takáto:
TList = class
...
bmp:TBitmap;
constructor Create(...);
procedure kresli(...);
procedure posun;
end;
TSova = class
...
bmp:array[0..1] of TBitmap; // dve fázy animácie
list:TList; // list, ktorý práve nesie
constructor Create(...);
procedure kresli(...);
procedure posun;
end;
THra = class
private
...
s:array of TSova; // zoznam lietajúcich sov
l:array of TList; // zoznam padajúcich listov
procedure kresli;
public
constructor Create(...);
procedure tik(...); // volaná z časovača
procedure mys(...); // volaná pri onMouseMove
end;
- túto štruktúru si môžete prispôsobiť
podľa vlastných potrieb, resp. môžete vytvoriť nové
triedy. Trieda THra nesmie mať definované žiadne public
stavové premenné.
- Váš program s hlavným formulárom
zrejme zadefinuje jednu premennú - inštanciu triedy THra a pracovať
s ňou bude len pomocou jej metód.
Súbory na testovanie môžete
stiahnuť z udaje.zip
|
// unit1.pas
// obsahuje: Image1 a Timer1 s intervalom 100 milisekúnd
uses
HraUnit;
var
h:THra;
procedure TForm1.FormCreate(Sender: TObject);
begin
randomize;
h:=THra.Create(Image1.Canvas,Image1.Width,Image1.Height);
DoubleBuffered:=true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
h.Free;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
h.tik;
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
h.mys(X,Y);
end;
|
HraUnit.pas:
|
unit HraUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TList = class
bmp:TBitmap;
x,y,dx,dy:integer;
constructor Create(xx,yy,ddx,ddy:integer);
destructor Destroy; override;
procedure kresli(c:TCanvas);
procedure posun;
end;
TSova = class
bmp:array[0..1] of TBitmap; // dve fázy animácie
list:TList; // list, ktorý práve nesie
x,y,dx,p,f:integer;
constructor Create(xx,yy,ddx,pp:integer);
destructor Destroy; override;
procedure kresli(c:TCanvas);
procedure posun;
end;
THra = class
private
s:array of TSova; // zoznam lietajúcich sov
l:array of TList; // zoznam padajúcich listov
c:TCanvas;
bmp,metla:TBitmap;
mx,my,sir,vys,poc:integer;
ok:boolean;
procedure kresli;
public
constructor Create(cc: TCanvas; ssir, vvys: integer);
destructor Destroy; override;
procedure tik;
procedure mys(xx,yy:integer);
end;
implementation
const
maxpoc=100;
{ TList }
constructor TList.Create(xx, yy, ddx, ddy: integer);
begin
x:=xx; y:=yy; dx:=ddx; dy:=ddy;
bmp:=TBitmap.Create;
bmp.LoadFromFile('list.bmp');
bmp.Transparent:=true;
end;
destructor TList.Destroy;
begin
bmp.Free;
end;
procedure TList.kresli(c: TCanvas);
begin
c.Draw(x-bmp.Width div 2,y-bmp.Height div 2,bmp);
end;
procedure TList.posun;
begin
inc(x,dx); inc(y,dy);
end;
{ TSova }
constructor TSova.Create(xx, yy, ddx, pp: integer);
begin
x:=xx; y:=yy; dx:=ddx; f:=0; p:=pp;
bmp[0]:=TBitmap.Create;
bmp[0].LoadFromFile('sova1.bmp');
bmp[0].Transparent:=true;
bmp[1]:=TBitmap.Create;
bmp[1].LoadFromFile('sova2.bmp');
bmp[1].Transparent:=true;
list:=TList.Create(xx,yy+25,ddx,0);
end;
destructor TSova.Destroy;
begin
bmp[0].Free; bmp[1].Free; list.Free;
end;
procedure TSova.kresli(c: TCanvas);
begin
if list<>nil then list.kresli(c);
c.Draw(x-bmp[f].Width div 2,y-bmp[f].Height div 2,bmp[f]);
end;
procedure TSova.posun;
begin
f:=1-f; inc(x,dx); dec(p);
if list<>nil then list.posun;
end;
{ THra }
constructor THra.Create(cc: TCanvas; ssir,vvys:integer);
begin
c:=cc; sir:=ssir; vys:=vvys; ok:=false;
bmp:=TBitmap.Create;
bmp.LoadFromFile('dlazka.bmp');
metla:=TBitmap.Create;
metla.LoadFromFile('metla.bmp');
metla.Transparent:=true;
kresli;
end;
destructor THra.Destroy;
var
i:integer;
begin
bmp.Free; metla.Free;
for i:=0 to high(s) do s[i].Free;
for i:=0 to high(l) do l[i].Free;
end;
procedure THra.kresli;
var
x,y,i:integer;
begin
y:=0;
while y<vys do begin
x:=0;
while x<sir do begin
c.Draw(x,y,bmp); inc(x,bmp.Width);
end;
inc(y,bmp.Height);
end;
for i:=0 to high(l) do l[i].kresli(c);
for i:=0 to high(s) do s[i].kresli(c);
c.Draw(mx-metla.Width div 2,my-metla.Height,metla);
end;
procedure THra.mys(xx, yy: integer);
begin
mx:=xx; my:=yy;
if my<200 then my:=200;
if my>vys-50 then my:=vys-50;
end;
procedure THra.tik;
var
i,j,dx:integer;
begin
if ok then exit;
if (maxpoc=poc)and(l=nil)and(s=nil) then begin
ok:=true; ShowMessage('hura');
end;
if (poc<maxpoc) and (length(s)<10) and (random(20)=0) then begin
SetLength(s,Length(s)+1); dx:=8+random(8); inc(poc);
if random(2)=0 then
s[high(s)]:=TSova.Create(0,30+random(70),dx,10+random((sir-200) div dx))
else
s[high(s)]:=TSova.Create(sir,30+random(70),-dx,10+random((sir-200) div dx));
end;
j:=0;
for i:=0 to high(l) do
with l[i] do begin
posun;
if y>vys-20 then begin
dy:=0; ok:=true; ShowMessage('zle je - nechytil si list');
end;
if sqr(mx-x)+sqr(my-y)<400 then Free
else begin l[j]:=l[i]; inc(j); end;
end;
SetLength(l,j);
j:=0;
for i:=0 to high(s) do
with s[i] do begin
posun;
if p=0 then begin
SetLength(l,Length(l)+1);
list.dx:=0; list.dy:=3+random(10);
l[high(l)]:=list; list:=nil;
end;
if (x<0)or(x>sir) then Free
else begin s[j]:=s[i]; inc(j) end;
end;
SetLength(s,j);
kresli;
end;
end.
|
2. príklad: koráliky
Hermione - Harryho spolužiačke a najlepšej kamarátke sa rozsypali
korále. Našťastie Harry pozná veľmi pekné kúzlo:
"zoberie dlhú niť a prechádza jej začiatkom okolo
jednotlivých korálikov - tieto sa samé navliekajú
- postupne putujú až na koniec nite a tam sa ukladajú tesne
vedľa seba"
Napíšte program, v ktorom budeme môcť predviesť toto Harryho
kúzlo.
- Pri štarte programu sa v grafickej ploche na náhodných
pozíciách vygeneruje 40 rôznofarebných guľôčok
- korálikov.
- Hráč má k dispozícii nekonečnú niť. Táto
sa začne odvíjať po zatlačení ľavého tlačidla myši
a odvíja sa počas ťahania myši - v grafickej ploche sa niť zobrazuje
tenkou čiarou (t.j. pomocou myši kreslíme v ploche nejakú
čiaru). Ak sa jej momentálny začiatok (na pozícii myši)
ocitne nad nejakým korálikom, tento sa navlečie na nakreslenú
niť tak, že poputuje zo svojej momentálnej pozície po dráhe
niti až na jej voľný koniec. Navliekať sa môžu aj viaceré
koráliky naraz a počas toho je možné ťahať niť ďalej.
- Keď ukončíme ťahanie nite, t.j. pustíme ľavé tlačidlo
myši, navlečené koráliky ešte doputujú na svoje pozície
a my už môžeme začať ťahať novú niť a navliekať ďalšie koráliky.
Raz navlečený korálik na nejakú niť, sa už znovu navliekať
nedá (treba si to zapamätať napr. v nejakej množine).
- Niť v programe reprezentujte dynamickým poľom bodov (array
of TPoint), pričom počas ťahania nite si doňho zapamätávajte
iba tie body, ktoré sú od svojho predchádzajúceho
suseda vzdialené aspoň 10 grafických bodov (body, ktoré
by boli veľmi nahusto, sa ignorujú). Navliekajúce
sa koráliky potom skáču po týchto bodoch v opačnom
poradí, pričom prvý korálik nite putuje do posledného
bodu (do miesta, kde sme začali ťahať myš), druhý do predposledného
miesta, tretí do predpredposledného atď. Zrejme na ďalšiu
niť opäť putujú koráliky až na jej koniec.
- Koráliky v programe reprezentujte korytnačkami triedy TKoralik
(odvodenej od TKor), pričom všetky sú uložené v polymorfnom
poli k triedy TVelaKor (nevytvárajte žiadne iné pole
korytnačiek). Korytnačky "vizualizujte" farebným kruhom
s polomerom 10 (zafarbené náhodne). Triedu TKoralik by ste mali zadefinovať približne takto:
type
pole = array of TPoint;
TKoralik = class(TKor)
xy:pole;
...
constructor Create;
procedure start(pxy:pole);
procedure pohni;
procedure kresli;
end;
- každá korytnačka si zapamätať svoje pole bodov popisujúce
časť nite, po ktorej putuje (metóda start dostane toto
pole ako parameter vtedy, keď niťou prejdeme popri koráliku). Metóda pohni bude volaná z časovača (Timer), ktorý
hýbe všetky navlečené koráliky - každý putuje po
svojej dráhe (svojom poli xy). Keď už je korálik na svojej cieľovej pozícii, tak táto
metóda nerobí nič.
- Niť môžete kresliť pomocou nejakej pomocnej korytnačky, ktorá nie je inštanciou
triedy TKoralik.
|
// unit2.pas
// obsahuje Image1 a Timer1 s intervalom 100
uses
KorUnit, VelaKorUnit;
type
pole = array of TPoint;
TKoralik = class(TKor)
xy:pole;
ix:integer;
treba:boolean;
constructor Create(xx,yy:integer);
procedure start(pxy:pole);
procedure pohni;
procedure kresli;
end;
{ TKoralik }
constructor TKoralik.Create(xx,yy:integer);
begin
inherited Create(xx,yy);
PH; FP:=RGB(random(100)+128,random(100)+128,random(100)+128);
treba:=true;
end;
procedure TKoralik.kresli;
begin
with Form1.Image1.Canvas do begin
Brush.Color:=FP;
Brush.Style:=bsSolid;
Pen.Color:=FP;
Pen.Width:=1;
Ellipse(round(x)-10,round(y)-10,round(x)+10,round(y)+10);
end;
end;
procedure TKoralik.pohni;
begin
if ix<0 then xy:=nil;
if xy<>nil then begin
ZmenXY(xy[ix].X,xy[ix].Y);
dec(ix);
end;
kresli;
end;
procedure TKoralik.start(pxy: pole);
begin
xy:=pxy; ix:=high(xy); treba:=false;
end;
/////////////////////////////////////////////////
var
v:TVelaKor;
nite:array of pole;
tahaj:boolean;
poc:integer;
procedure TForm1.FormCreate(Sender: TObject);
var
i:integer;
begin
zmaz; randomize;
v:=TVelaKor.Create;
for i:=1 to 40 do begin
v.UrobKor(TKoralik.Create(random(sirka),random(vyska)));
end;
tahaj:=false;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
v.Free;
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
i:integer;
begin
i:=Length(nite);
SetLength(nite,i+1);
SetLength(nite[i],1);
nite[i,0].x:=X;
nite[i,0].y:=Y;
tahaj:=true; poc:=0;
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
k,i,j:integer;
begin
if not tahaj then exit;
i:=high(nite); j:=high(nite[i]);
if sqr(nite[i,j].x-x)+sqr(nite[i,j].y-y)<100 then exit;
inc(j); SetLength(nite[i],j+1); nite[i,j].x:=x; nite[i,j].y:=y;
for k:=0 to v.pk-1 do
if (poc<=j) and v.k[k].Blizko(X,Y) and TKoralik(v.k[k]).treba then begin
TKoralik(v.k[k]).start(copy(nite[i],poc,maxint)); inc(poc);
end;
end;
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
tahaj:=false;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
i:integer;
begin
zmaz;
with Image1.Canvas do begin
Pen.Color:=clBlack; Pen.Width:=3;
for i:=0 to high(nite) do Polyline(nite[i]);
end;
for i:=0 to v.pk-1 do
TKoralik(v.k[i]).pohni;
end;
|
Nasledujúce príklady sú zo starších
ročníkov. Korytnačie úlohy veľmi často
využívajú tvar korytnačky, ktorý
je ale v súčasnej triede TKor zrušený.
1. príklad: skladanie rozstrihaného
obrázka
- Napíšte program,
ktorý nám umožní poskladať
rozstrihaný obraz. Na začiatku hry
je v ploche rozstrihaný nejaký
veľký obrázok na rôzne
veľké kúsky - obdĺžniky, pričom
sa tieto kúsky vôbec neprekrývajú.
Úlohou hráča je posúvaním
týchto kúskov ťahaním
myšou poskladať pôvodný obraz.
Program mu pritom nedovolí, aby žiaden
kúsok "vypadol" z plochy
- okraje hracej plochy sú pri ťahaní
prekážkou a teda ťahanie sa na ňom
zastaví. Kúsky obrazu sa môžu
v priebehu hry prekrývať.
- Všetky vstupné informácie
sú v textovom súbore obraz.txt,
ktorý obsahuje:
- v prvom riadku je meno bitmapového
súboru s ešte nenastrihaným
obrazom
- v druhom riadku súboru
sú dve čísla, ktoré
definujú šírku a výšku
hracej plochy (napr. komponentu
triedy TImage) - v tejto ploche
sa budú posúvať nastrihané
kúsky obrazu
- nasledujúce riadky súboru
obsahujú po 6 celých
čísel - sú to informácie
o rozstrihaných kúskoch
- obdĺžnikoch: prvé štyri
čísla popisujú obdĺžnik
v obraze a to súradnice x
a y a veľkosť obdĺžnika: šírku
a výšku; posledné
dve čísla sú súradnice
obdĺžnika umiestneného v
hracej ploche
- môžete predpokladať, že
súbor je zadaný korektne
a obraz je celý rozstrihaný
na disjunktné obdĺžniky
- na "vystrihnutie"
obdĺžnika z obrazu môžete
využiť metódu CopyRect
alebo Draw
- Kúsky obrazu v programe realizujte
ako inštancie triedy TKusok,
napr. s takouto deklaráciou (môžete
niečo pridať, alebo mierne pozmeniť):
TKusok = class
bm:TBitmap;
x,y,sirka,vyska:integer;
constructor Create(...);
destructor Destroy; override;
procedure kresli(c:Tcanvas; ...); // nakreslí ho aj s rámikom
function klik(xx,yy:integer):boolean; // zistí, či sa doň kliklo
procedure posun(dx,dy:integer);
end;
- Samotnú hru realizujte triedou
THra, ktorej deklarácia
by mala vyzerať približne takto:
THra = class
k:array of TKusok;
...
constructor Create(...);
destructor Destroy; override;
procedure pridaj(kk:TKusok); // pridá nový kúsok do poľa
procedure kresli(c:Tcanvas); // nakreslí všetky kúsky
procedure MouseDown(x,y:integer);
procedure MouseMove(x,y:integer);
procedure MouseUp;
end;
- THra si musí pamätať,
ktorý kúsok sa momentálne
ťahá myšou. Tento bude vykresľovaný
ako posledný zo všetkých
a teda bude nad všetkými ostatnými
kúskami. Navyše bude počas ťahania
orámovaný červeným
rámikom (toto zabezpečia obe
metódy kresli).
- Program nemusí zisťovať,
či už je celý obraz poskladaný.
- Stavové premenné tried
TKusok a THra môžete
používať len v metódach
týchto tried.
Súbory na testovanie môžete
stiahnuť z skuska.zip
|
type
TKusok = class
bm:TBitmap;
x,y,sirka,vyska:integer;
constructor Create(bmp:TBitmap; xvbmp,yvbmp,nsirka,nvyska,nx,ny:integer);
destructor Destroy; override;
procedure kresli(c:Tcanvas; sel:boolean);
function klik(xx,yy:integer):boolean;
procedure posun(dx,dy:integer);
end;
constructor TKusok.Create(bmp:TBitmap; xvbmp,yvbmp,nsirka,nvyska,nx,ny:integer);
begin
bm:=TBitmap.Create;
sirka:=nsirka; vyska:=nvyska; x:=nx; y:=ny;
bm.Width:=sirka; bm.Height:=vyska;
{ bm.Canvas.CopyRect(Rect(0,0,sirka,vyska),bmp.Canvas,
Rect(xvbmp,yvbmp,xvbmp+sirka,yvbmp+vyska));}
bm.Canvas.Draw(-xvbmp,-yvbmp,bmp);
end;
destructor TKusok.Destroy;
begin
bm.Free;
end;
function TKusok.klik(xx,yy:integer):boolean;
begin
Result:=(xx>=x) and (xx<x+sirka) and (yy>=y) and (yy<y+vyska);
end;
procedure TKusok.kresli(c:Tcanvas; sel:boolean);
begin
c.Draw(x,y,bm);
if sel then begin
c.Brush.Style:=bsClear;
c.Pen.Color:=clRed;
c.Pen.Width:=3;
c.Rectangle(x+1,y+1,x+sirka-1,y+vyska-1);
end;
end;
procedure TKusok.posun(dx,dy:integer);
begin
inc(x,dx); inc(y,dy);
end;
////////////////////////////////////////////////////////////////////////////////
type
THra = class
k:array of TKusok;
x0,y0,sirkaPlochy,vyskaPlochy,sel:integer;
constructor Create(subor:string);
destructor Destroy; override;
procedure pridaj(kk:TKusok);
procedure kresli(c:Tcanvas);
procedure MouseDown(x,y:integer);
procedure MouseMove(x,y:integer);
procedure MouseUp;
end;
constructor THra.Create(subor:string);
var
t:TextFile;
s:string;
bmp:TBitmap;
x1,y1,sir,vys,x2,y2:integer;
begin
AssignFile(t,subor); Reset(t);
readln(t,s);
bmp:=TBitmap.Create;
bmp.LoadFromFile(s);
readln(t,sirkaPlochy,vyskaPlochy);
while not eof(t) do begin
readln(t,x1,y1,sir,vys,x2,y2);
pridaj(TKusok.Create(bmp,x1,y1,sir,vys,x2,y2));
end;
bmp.Free;
CloseFile(t);
sel:=-1; // žiaden nie je oselektovaný
end;
procedure THra.pridaj(kk:TKusok);
begin
SetLength(k,Length(k)+1);
k[High(k)]:=kk;
end;
destructor THra.Destroy;
var
i:integer;
begin
for i:=0 to High(k) do
k[i].Free;
end;
procedure THra.kresli(c:Tcanvas);
var
i:integer;
begin
c.Brush.Style:=bsSolid;
c.Brush.Color:=clLtGray;
c.FillRect(Rect(0,0,sirkaPlochy,vyskaPlochy));
for i:=0 to High(k) do
if i<>sel then
k[i].kresli(c,false);
if sel>=0 then // aby bol vykreslený nad všetkými ostatnými
k[sel].kresli(c,true);
end;
procedure THra.MouseDown(x,y:integer);
begin
sel:=High(k);
while (sel>=0) and not k[sel].klik(x,y) do dec(sel);
x0:=x; y0:=y;
end;
procedure THra.MouseMove(x,y:integer);
begin
if sel>=0 then begin
k[sel].posun(x-x0,y-y0);
if k[sel].x<0 then k[sel].x:=0;
if k[sel].x+k[sel].sirka>sirkaPlochy then k[sel].x:=sirkaPlochy-k[sel].sirka;
if k[sel].y<0 then k[sel].y:=0;
if k[sel].y+k[sel].vyska>vyskaPlochy then k[sel].y:=vyskaPlochy-k[sel].vyska;
x0:=x; y0:=y;
end;
end;
procedure THra.MouseUp;
begin
sel:=-1;
end;
////////////////////////////////////////////////////////////////////
var
hra:THra;
procedure TForm1.FormCreate(Sender: TObject);
begin
hra:=THra.Create('obraz.txt');
Image1.Width:=hra.sirkaPlochy; Image1.Height:=hra.vyskaPlochy;
hra.kresli(Image1.Canvas);
DoubleBuffered:=true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
hra.Free;
end;
procedure TForm1.Image1MouseDown(...);
begin
hra.MouseDown(x,y);
hra.kresli(Image1.Canvas);
end;
procedure TForm1.Image1MouseMove(...);
begin
hra.MouseMove(x,y);
hra.kresli(Image1.Canvas);
end;
procedure TForm1.Image1MouseUp(...);
begin
hra.MouseUp;
hra.kresli(Image1.Canvas);
end;
|
2. príklad: práca s korytnačkami
Napíšte program,
ktorý umožní zahrať sa takúto
hru:
- zospodu grafickej plochy vyletujú
smerom nahor rôznou rýchlosťou
rôzne zafarbené balóny
- úlohou hráča je triafať
tieto balóny šípkou -
každý trafený balón
praskne a na jeho mieste sa napíše
text BUM
- balóny sú reprezentované
korytnačkami, ktorých tvar je
farebný šesťuholník so
stranou 30 - pre toto zadefinujte triedu
TBalon:
TBalon = class(TKor)
k:real;
constructor Create;
procedure Dopredu(d:real); override;
end;
- stavová premenná k
slúži ako koeficient pre metódu
Dopredu - vďaka tomuto koeficientu
bude môcť korytnačka "chodiť
trochu pomalšie"
- konštruktor Create vytvorí
korytnačku na náhodnej pozícii
ale na dolnej hrane plochy, natočenú
na sever tvaru farebného balóna
(metódy ZmenTvar, ZmenFarbuTvaru),
pričom nastaví stavovú
premennú k na náhodnú
hodnotu z intervalu <0.5,1>
- všetky tieto balóny budete
uchovávať v polymorfnom poli
triedy TVelaKor
- samotná šípka bude
tiež korytnačka (môže mať tvar
trojuholníka), ktorá je
stále natočená smerom
na východ - objaví sa
na mieste kliknutia myšou ale len, ak
sa kliklo nie viac ako 100 od ľavého
okraja plochy. Kliknúť môžeme
kedykoľvek, ak šípka ešte neodletela
mimo plochy, tak sa presunie na miesto
kliknutia.
- šípka sa stále rovnomerne
pohybuje smerom na východ a ak
pri svojom pohybe prejde cez nejaký
balón, tak tento praskne a zanechá
nápis BUM - nemusíte si
všímať situáciu, ak šípka
uletí von z plochy - zrejme novým
kliknutím sa znovu objaví
v ploche
- všetky balóny, ktoré
prasknú, alebo vyletia z plochy
von, by sa z poľa korytnačiek mali zrušiť
metódou ZrusKor
- v náhodných časových
intervaloch, ale za podmienky, že balónov
nie je viac ako 20, sa stále
generujú nové balóny
- pohyb šípky, pohyb balónov,
ale aj náhodné generovanie
balónov a aj rušenie balónov
budete robiť pomocou časovača (TTimer)
|
type
TBalon = class(TKor)
k:real;
constructor Create;
procedure dopredu(d:real); override;
end;
constructor TBalon.Create;
const
f:array[0..5] of TColor = (clRed, clBlue, clGreen, clYellow, clPurple, clBlack);
begin
inherited Create(random(sirka-100)+100,vyska);
ZmenTvar([90,15,60,30,60,30,60,30,60,30,60,30,60,15]);
ZmenFarbuTvaru(f[random(Length(f))]);
PH; Ukaz;
k:=0.5+random(6)/10;
end;
procedure TBalon.dopredu(d:real);
begin
inherited dopredu(d*k);
end;
var
sip:TKor;
balony:TVelaKor;
procedure TForm1.FormCreate(Sender: TObject);
begin
randomize; zmaz;
sip:=TKor.Create(sirka,0,90);
sip.PH;
sip.ZmenTvar([0,50,135,10,0,-10,90,10]);
balony:=TVelaKor.Create;
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if X<100 then begin
sip.ZmenXY(X,Y); sip.Ukaz;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
i:integer;
begin
sip.Dopredu(10);
if (balony.pk<20) and (random(2)=0) then
balony.UrobKor(TBalon.Create);
balony.Dopredu(10);
with balony do begin
for i:=0 to pk-1 do
if k[i].vzd(sip.X,sip.Y)<50 then begin
ZrusKor(i);
sip.Pis('BUM');
end
else if k[i].Y<0 then ZrusKor(i);
Uprac;
end;
Image1.Repaint;
end;
|
Ďalšie zadania z
predminulého roku nájdete na stránke
Zadania
|