Image
20.6.2016 0 Comments

Stretnutie s Pascalom II. /8.časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Ak ste si stiahli z redakčného webu potrebné súbory a preložili ste si panáčika, iste vás napadlo, že pokiaľ ide o animáciu, ešte to nie je to pravé orechové. To preto, že panák sa síce zväčšuje a zmenšuje, posúva všetkými smermi alebo rotuje, ale nechodí! Áno, prvok chodenia, teda kroku, dáva animácii ten pravý nádych. Preto si dnes ukážeme, ako naše objekty rozhýbeme a rozchodíme.
Podstatu plynulého pohybu možno rozdeliť na dva problémy:
- valivý pohyb na kolesách,
- presun dvoch alebo viacerých končatín v jednom cykle – krok.

Valivý pohyb na kolesách by sme aj teraz dokázali zrealizovať. Typickým príkladom je autíčko. Najprv nadeklarujeme koleso ako potomka PieChartu, podobne ako u panáčika. Toto koleso sa bude na základe pohybu myši alebo povelu z klávesnice otáčať požadovaným smerom. Už z predchádzajúcej časti vieme, že kruh je jediný objekt, ktorého otáčanie nevidíme. Aby otáčanie kolesa bolo zjavné, vyplníme koleso čiarami, ktoré budú predstavovať osi - špice, tak ako napr. na bicykli alebo na starom veteráne. Potom deklarujeme autíčko, ktoré je tiež potomkom PieChartu. Samozrejme, musí obsahovať aj už deklarované kolesá. Karosériu auta vytvoríme z úsečiek a oblúka. Vlastné telo programu obsahuje voľby veľkosti kolies a počtu osí kolesa a metódy Init, Show, Drag, a Done. Kompletný výpis programu AUTICKO.PAS je na listingu č. 1. Ostatné prvky pohybu, zmenšenie či zväčšenie autíčko zdedilo od svojich predkov, takže toto je vaše jediné auto, ktoré si môžete zväčšovať podľa momentálnych potrieb.

Problém kroku je obdobný ako v bežnom svete. Najprv musí mať náš objekt nejaké nožičky. Tie mu vykreslíme pomocou grafických procedúr, ako sme na to zvyknutí. Zložitejšie to je už s grafickým vyjadrením kroku. Tu musíme nadefinovať postupné prekresľovanie polohy nôh so striedaním pravej a ľavej nohy. Nesmieme pritom zabudnúť, že pohyb sa skladá z odklonu a rotácie nožičky o určitý uhol, a to všetko v jednom jedinom kroku. Aby to bolo možné, vytvoríme si jednotku MyFeet.

Jednotka MyFeet je dodatkom k našej MyFigs, umožňujúcej objekty rozchodiť. Implementuje jednak akúsi šablónu pre "dvojnožcov" v podobe objektového typu BiPed, a jednak šablónu pre "n-nožce" v podobe objektového typu NPed. Ako tieto objektové typy vyzerajú, vidíte na listingu č. 2.

Typ BiPed obsahuje ukazovatele na ľavú a pravú nohu, maximálny uhol odklonu nohy od zvislej polohy, uhol rotácie nohy v jednom kroku cyklu chôdze a ukazovateľ na procedúru, ktorá sa vykonáva pri každom kroku cyklu chôdze (napr. pípnutie).
Pri type NPed sa dvojica nôh pridáva jednoducho ako jeho komponenty typu BiPed. Pri chôdzi "n-nožca" sa preberie zoznam komponent a pri tých, ktoré sú typu BiPed, sa vykoná patričná rotácia končatín.

Najvhodnejším predstaviteľom typu BiPed je kuriatko. Má dve nožičky, ktorými prepletá a vie sa pohybovať dopredu aj dozadu. A má aj zobáčik, ktorý môže otvárať, prípadne vydávať pípavý zvuk. Na listingu č. 3 je program KURCA.PAS, ktorý demonštruje práve spomínané vlastnosti (pohyb a zvuk) kuriatka.

Typickým predstaviteľom viacnožca je stonožka. Ako sme už naznačili, využíva obdobné metódy na vykreslenie pohybu viacerých končatín naraz v jednom smere. Na listingu č. 4 je program STONOZKA.PAS, ktorý demonštruje kráčanie stonožky. Keďže stonožka nepípa, táto naša vie "grúliť" očami.

Jadro programu má zase voľby veľkosti stonožky a počtu článkov tela. Ak určíme extrém, kde stonožka má iba jeden článok, veľmi sa objektovo (nie fyzicky!!!) podobá na kuriatko.

Kroky obidvoch zvieratiek sa ovládajú z klávesnice, a to súčasným stlačením klávesov pravý Shift + Enter (krok dopredu) a ľavý Shift + Enter (krok dozadu).

Ak sa vám zdajú programy pomerne zložité a teórie je málo, predpokladám, že už máte určité skúsenosti. A ak nie, tak skúšajte meniť rôzne parametre a laďte a krokujte, skúšajte a testujte. Lebo len takto sa dá naučiť programovať.

LISTING Č. l
program Auticko;
 
{ Auto, ktore jazdi iba doprava a ktoremu sa automaticky otacaju
kolesa }
{ podla ubehnutej vzdialenosti }
 
uses MyFigs, Graph, Crt;
 
type
  KolesoPtr = ^Koleso;
 
  Koleso = object(PieChart)
    Radius: Number;
    constructor Init(InitX, InitY, InitRadius: Number;
                  InitN: Byte);
end;
 
AutoPtr = ^Auto;
 
Auto = object(PieChart)
  LKoleso, PKoleso: KolesoPtr;
  LAlpha, PAlpha: Real;
  dAngle: Integer;
  SX, SY: Number;   { Pozicia auta pri poslednom otacani kolies }
 
  constructor Init(InitX, InitY, D: Number;
                 InitLKoleso, InitPKoleso: KolesoPtr);
  procedure Rotate; virtual;   
  procedure Draw; virtual;
end;
 
constructor Koleso.Init(InitX, InitY, InitRadius: Number;
                        InitN: Byte);
var I: Byte;
begin
  PieChart. Init(InitX, InitY);
  Radius := InitRadius;
  Add(New(CirclePtr, Init(LightRed,0,0,Radius)) ,0,0);
  for I := 1 to InitN do
   begin
    Add(New(LinePtr,Init(Random(16),0,0,0,2*Radius)),O,-Radius);
    RotateLeft(180 div InitN);
   end;
end;
 
constructor Auto.Init(InitX, InitY, D: Number;
                         InitLKoleso, InitPKoleso: KolesoPtr);
var LR, PR, LR2, PR2, R2: Number;
begin
  PieChart.Init(InitX, InitY);
  LKoleso := InitLKoleso;
  PKoleso := InitPKoleso;
  SX := InitX;
  SY := InitY;
  LR := LKoleso^.Radius; -
  PR := PKoleso^.Radius;
  LAlpha := 180/Pi/LR;
  PAlpha := 180/Pi/PR;
LR2 := 2*LR + 2*D;
PR2 := 2*PR + 2*D;
R2 := (LR2 + PR2)/2;
 
  Add(LKoleso, -D - LR, 0);
  Add(PKoleso, D + PR, 0) ;
  Add(New(LinePtr, Init(14,0,0,2*D,0)) ,-D,0);
  Add(New(LinePtr, Init(14,0,0,D,0)),-LR2,0);
  Add(New(LinePtr, Init(14,0,0,-D,0)),PR2,0);
  Add(New(ArcPtr, Init(14,0,0,R2,0,180)),-LR2+R2,0);
  dAngle := round(180/Pi*arctan((PR-LR)/(PR+LR+2*D)));
  RotateLeft(dAngle);
end;
 
procedure Auto.Draw;
begin
  if GetColor<>GetBkColor then Rotate;
  PieChart.Draw;
end;
 
procedure Auto.Rotate;
var T: Real;
NX, NY: Number; A: Integer; begin
NX := GetX; NY := GetY;
T := VectorLength(NX-SX,NY-SY); { Ubehnut vzdialenost }
A := VectorAngle(PKoleso^.GetX-LKoleso^.GetX,PKoleso^.6etY-
LKoleso^.GetY)-dAngle
-VectorAngle(NX-SX,NY-SY); { uhol medzi starou a novou pozi-
ciou }
 
  sound(round(10+T*5)) ;
  LKoleso^.RotateRight(round(LAlpha*T));
  PKoleso^.RotateRight(round(PAlpha*T));
  RotateRight(A);
  nosound;
  SX := NX;
  SY := HY;
end;
var A: Auto;
 LK, PK: KolesoPtr;
 LR, LO, PR, PO, Roz: Byte;
 gd.gm: integer;
BEGIN
Write(' Polomer laveho kolesa : '); ReadLn(LR);
Write(´ Pocet os laveho kolesa : '); ReadLn (LO);
Write(' Polomer praveho kolesa : '); ReadLn(PR);
Write(' Pocet os praveho kolesa: '); ReadLn(PO);
Write(' Rozpatie kolies       : '); ReadLn(Roz);
gd := detect;
InitGraph(gd,gm,'');
LK := New(KolesoPtr, Init(0,0,LR,LO));
PK := New(KolesoPtr, Init(0,0,PR,PO)); »
A.Init(200,200,Roz,LK,PK);
A.Show;
A.Drag(10);
A.Done;
CloseGraph;
END.
LISTING Č. 2
unit MyFeet; {umoznuje rozchodit objekty}
INTERFACE
uses MyFigs;
type StepProcedure = Procedure;
 
type
BiPedPtr = ^BiPed;
 
BiPed = object (PieChart)
{ Color: Byte; }
{ X,Y: Number; }
{ Visible: Boolean; }
{ PieSlices: PieSlicePtr; }
LFoot, RFoot: PieSlicePtr;
MaxFootAngle, RotAngle: Integer;
StepProc: StepProcedure;
constructor Init(InitX, InitY: Number;
InitLFoot, InitRFoot: FigurePtr;
FeetRX, FeetRY: Number;
InitMaxFootAngle, InitRotAngle: Integer;
InitStepProc: StepProcedure);
 
{ destructor Done; virtual; }
{ procedure Drav; virtual; }
{ procedure Show; virtual; }
{ procedure Hide; virtual; }   
{ function GetX: Number; }
{ function GetY: Number; }
{ function IsVisible: Boolean; }   
{procedure MoveTo(NewX, NewY: Number); }
{ procedure Drag(DragBy: Number); virtual; }
{ procedure Expand(ExpandBy: Real); virtual; }
{ procedure Contract(ContractBy: Real); virtual; }
{ procedure RotateLeft(Alpha: Integer); virtual; }
{ procedure RotateRight(Alpha: Integer); virtual; }
{ procedure Add(Item: FigurePtr; RX, RY: Number); }
procedure ChangeFeet;
procedure StepRight; virtual;
procedure StepLeft; virtual;
end;
NPedPtr = ^NPed;
NPed = object (PieChart)
{ Color: Byte; }
{ X,Y: Number; }
{ Visible: Boolean; }
{ PieSlices: PieSlicePtr; }
StepProc: StepProcedure;
constructor Init(InitX, InitY: Number;
InitStepProc: StepProcedure);
{ destructor Done; virtual; }
{ procedure Draw; virtual; }
{ procedure Show; virtual; }
{ procedure Hide; virtual; }
{ function GetX: Number; }
{ function GetY: Number; }
{ function IsVisible: Boolean; }
{ procedure MoveTo(NewX, NewY: Number); }
{ procedure Drag(DragBy: Number); virtual; }
{ procedure Expand(ExpandBy: Real); virtual; }
{ procedure Contract(ContractBy: Real); virtual; }
{ procedure RotateLeft(Alpha: Integer); virtual; }
{ procedure RotateRight(Alpha: Integer); virtual; }
{ procedure Add(Item: FigurePtr; RX, RY: Number); }
 procedure StepRight; virtual;
 procedure StepLeft; virtual;
 end;
LISTING Č. 3
program Kurca;
uses MyFigs, MyFeet, Graph, Crt;
type
NohaPtr = ^Noha;
Noha = object (MyFigs. Triangle)
procedure Draw; virtual;
  end;
KuraPtr = ^Kura;
Kura = object (BiPed)
constructor Init(InitX, InitY, InitR: Number;
InitStepProc: StepProcedure);
  end;
var C: Kura;
nh2, nd2: Triangleptr;
MM: Byte;
gd,gm: integer;
 
procedure Noha.Draw;
begin
Graph.Line(round(X),round(Y),round(X+dX),round(Y+dY));
Graph.Line(round(X+dX),round(Y+dY),round(X+dX2),round(Y+dY2));
end;
 
procedure beep; far;
var j:integer;
begin
if random>0.9 then
begin
nh2^.hide;
nd2^.hide;
nh2^.rotateleft(55);
 
   nd2^.rotateright(55);
   nh2^.show;
   nd2^.show;           ,
   for j:=0 to 100 do sound(3000+j*20); 
   delay(150);
   nh2^.hide;
   nd2^.hide;
   nh2^. rotateright (55);
   nd2^.rotateleft(55);
   nh2^.show;
   nd2^.show;
 end
 else delay(30);
 nosound;
end;
constructor Kura.Init(InitX, InitY, InitR: Number;
InitStepProc: StepProcedure);
const a:real = 1;
h = 7;
var p2,12: FigurePtr;
r1,r2,r3: Real;
C1, C2 : CirclePtr;
begin
r1 := InitR;
r2 := 2/3*InitR;
r3 := InitR/5;
p2:=New(NohaPtr,Init(12,0,0,0,r2,r2/2,r2));
12 :=New(NohaPtr,Init(12,0,0,0,r2,r2/2,r2));
BiPed.Init(InitX,InitY,12,p2,0,r1,35,5,InitStepProc);
C1 := New(CirclePtr,Init(14,O,O,r1));
Add(Cl,0,0);
C2 := New(CirolePtr,Init(14,0,0,r2));
Add(C2,(r1+r2)*cos(a),-(r1+r2)*sin(a));
Add (New (CirclePtr, Init (LightMagenta, O, O, r3)), (r1+r2 * l.5) *cos (a), -
(r1+r2*1.5)*sin(a));
nh2: =New (TrianglePtr, Init (LightGray, O, O, -h/8, -h/2, h, O));
Add(nh2,(r1+r2)*cos(a)+r2+l,-(r1+r2)*sin(a));
nd2:=New(TrianglePtr,Init(LightGray,0,0,h,0,-h/8,h/2));
Add(nd2, (r1+r2)*cos(a)+r2+l,-(r1+r2)*sin(a));
end;
BEGIN
gd := detect;
InitGraph(gd,gm,'');
setbkcolor(Blue);
C.Init(40,200,15,beep);
C.Show;
repeat
    C.Drag(lO);
    MM := mem[0:$0417];            { Ovladanie Shiftov }
    if (MM and $01) <> O then C.StepRight else  
      if (MM and $02) <> O then C.StepLeft;
  until (MM and $03) = 0;
  C.Done;
  CloseGraph;
EMD.
LISTING Č. 4
program Stonozka;
uses MyFigs, MyFeet, Graph, Crt;
type
NohaPtr = ^Noha;
Noha = object (Triangle)
constructor Init(InitR: Nunber};
procedure Draw; virtual;
  end;
HlavaPtr = ^Hlava;
Hlava = object (PieChart)
constructor Init(InitX, InitY, InitR: Number; Right: Boolean);
  end;
ClanokPtr = ^Clanok;
Clanok = object (BiPed)
constructor Init(InitX, InitY, InitR: Number);
  end;
Stonoh = object (NPed)
constructor Init(InitX, InitY, InitR: Number;
                   PocetClankov: Integer;
 
InitStepProc: StepProcedure);
end;
 
var LH, RH: HlavaPtr;     { Left Read & Right Head Pointer }
    MM: Byte;
    gd.gm: integer;
 
procedure nic; far;
begin
end;
procedure hlavotoc; far;
begin
RH^.rotateright(45);
LH^.rotateright(45);
end;
 
constructor Noha.Init(InitR: Number);
begin
Triangle. Init (12,0,0,0, InitR, InitR/3, InitR);
end;
 
procedure Noha.Draw;
begin
Graph.Line (round (X), round (Y) , round (X+dX), round (Y+dY)) ;
Graph.Line(round(X+dX) ,round(Y+dY),round(X+dX2),round(Y+dY2));
end;
constructor Hlava.Init(InitX, InitY, InitR: Number; Right: Boolean);
var D: Real;
begin
PieChart.Init(InitX, InitY);
Add(New(CirclePtr, Init(14,O,O,InitR)),0,0);
if Right then D := InitR/3 else D := -InitR/3;
Add(New(CirclePtr, Init(13,0,0,InitR/4)),D,-D);
end;
constructor Clanok.Init(InitX, InitY, InitR: Number);
var NL, NR: NohaPtr;
begin
NL := New(NohaPtr, Init(InitR) );
NR := New(NohaPtr, Init(InitR) ) ;
BiPed.Init(InitX,InitY,NL,NR,0,InitR,20,5,nic) ;
Add(New(CirclePtr, Init(14,0,0,InitR)),0,0);
end;
 
constructor Stonoh.Init(InitX, InitY, InitR: Number;
                          PocetClankov: Integer;
                          InitStepProc: StepProcedure);
var I: Integer;
Clan: ClanokPtr;
begin
NPed.Init(InitX, InitY, InitStepProc);
for I := 1 to PocetClankov do
  begin
Clan := New(ClanokPtr, Init(0,0,InitR));
if I = 1
then begin LH := New(HlavaPtr, Init(0,0,InitR,False));
Clan^.Add(LH,-2*IniťR,0); end;
      if I = PocetClankov
then begin RH := New(HlavaPtr, Init(0,0,InitR,True)) ;
      Clan^.Add(RH,2*InitR,0); end; Add(Clan,I*InitR*2,0);
    end;
end;
 
var C: Stonoh;
    R, N: Byte;
BEGIN
Write(' Polomer tela stonozky(max 30): '); ReadLn(R);
Write(' Počet clankov stonozky(max 100): '); ReadLn(N);
if R>30 then R:=30;
if N>100 then N:=100;
gd := detect;
InitGraph(gd,gm,'');
C.Init(100,100,R,N,hlavotoc);
C.Show;
repeat
C.Drag(lO);
MM := mem[0:$0417];
if (MM and $01) <> O then C.StepRight else
  if (MM and $02) <> O then C.StepLeft;
  until (MM and $03) = 0;
  C.Done;
  CloseGraph;
END.

Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Ako zbaviť fotky hmly

08.12.2016 11:59

Hmla alebo dym sú často veľmi kreatívne nástroje. No všetkého veľa škodí. Fotka potom stráca kontrast a v podstate na nej nič nevidieť. Hmlu môžete neraz následnými úpravami odstrániť alebo zredukovať ...

Ako na to

Užitočné SW nástroje

08.12.2016 11:53

AllDup v4.0.3 Určenie: program na vyhľadávanie a odstraňovanie duplicitných súborov Vlastnosti: duplicitné súbory sa vyhľadávajú len na zvolených diskových jednotkách alebo len v rámci vybraných ...

Ako na to

Fotografovanie s bleskom

08.12.2016 11:47

Ak máte moderný fotoaparát so vstavaným alebo externým bleskom, zdá sa vám téma článku triviálna. Jednoducho nastavíte vhodný režim, vyberiete najlepšiu kompozíciu záberu, exponujete a o zvyšok sa už ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá