2. Objekt Korytnačka


Posledná zmena: 1.10.2002

Banner Text 24.9.2002

Naučíme sa pracovať s objektom korytnačka

  • korytnačkou budeme nazývať špeciálne grafické pero, ktoré sa pohybuje po grafickej ploche, pričom môže za sebou zanechávať stopu - čiaru
  • "počítač" si o korytnačke musí pamätať rôznu informáciu: napr. kde sa nachádza v ploche, ktorým smerom je natočená, aké má nastavené pero, či je pero zdvihnuté, ...
  • korytnačka má preddefinované rôzne povely - väčšinou slúžia na zmenu polohy, smeru alebo nastavení pera

Keď budeme chcieť pracovať s korytnačkou:

  • najprv musíme zadefinovať premennú typu "korytnačka", napr. var k:TKor;
  • potom musíme vytvoriť (oživiť) túto korytnačku špeciálnym Delphi-príkazom:
    • k:=TKor.Create;

  • podobne sa v Delphi vytvárajú všetky windows-prvky, napr. grafická plocha TImage, tlačidlo TButton atď.
  • od tohoto momentu grafické pero existuje a môžeme ho riadiť príkazmi, napr. príkazom k.dopredu(100); korytnačka prejde v momentálnom smere natočenia 100 krokov (úsečku dĺžky 100) a príkazom k.vpravo(90); sa otočí vpravo (v smere otáčania hod. ručičiek) o 90 stupňov
  • všimnite si, že vždy, keď oslovujeme korytnačku (prikazujeme jej nejaký povel), píšeme meno premennej k a bodku - podobne ako pre príkazy pre grafickú plochu v minulej prednáške

Ako vytvoríme projekt s korytnačkou

  • rovnako ako v prvej prednáške začneme novým projektom (File/New/Application) - môžeme ho preventívne najprv uložiť do nejakého nového adresára (File/Save Project As...) - a ďalej do formulára umiestnime grafickú plochu (komponent Image) a tlačidlo (komponent Button)
  • objekt korytnačka je definovaný v programovej jednotke KorUnit - aby sme s týmto objektom mohli pracovať v Delphi, musíme do nášho programu pridať riadok:
    • uses KorUnit;

  • okrem toho musíme zadeklarovať "korytnačiu" premennú, napr. identifikátor k
  • pozrite program, ktorý pomocou korytnačky kreslí štvorec so stranou 100:

kompletný Unit1.pas:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  KorUnit;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  k:TKor;
  i:integer;
begin
  k:=TKor.Create;
  for i:=1 to 4 do begin
    k.dopredu(100);
    k.vpravo(90);
  end;
end;

end.
  • takto to bude vyzerať v grafickej ploche:

Korytnačie príkazy

  • k:=TKor.Create( x, y, uhol ); špeciálna konštrukcia na vytvorenie korytnačky
    • na pozícii x, y sa vytvorí korytnačka so smerom uhol
    • pero je spustené a je čierne tenké
    • uhly sú v stupňoch 0..359 (môžu byť aj nie celé čísla)
    • uhol 0 je na sever; ostatné uhly sa určujú v smere otáčania hod. ručičiek
    • ani x a y nemusia byť celé čísla
    • skrátený tvar k:=TKor.Create; bez parametrov znamená, že korytnačka sa vytvorí v strede plochy
  • k.Dopredu( dĺžka_kroku );
    • nemusí byť celé ani kladné číslo
  • k.Vpravo ( uhol );
  • k.Vlavo ( uhol );
  • k.ZmenSmer ( uhol );
    • korytnačka nastaví svoj smer na hodnotu uhol
  • k.PH;
    • pero hore
  • k.PD;
    • pero dole
  • k.ZmenXY( x, y );
    • ak je pero dole, tak sa kreslí čiara
  • k.ZmenFP( farba );
    • farebná konštanta (clBlack, clRed, clBlue, ...)
    • ako farba sa môže použiť aj konštrukcia RGB( číslo, číslo, číslo ), kde čísla môžu byť z intervalu <0,255>
  • k.ZmenHP( hrúbka );
    • ľubovoľné celé kladné číslo

Grafická plocha

  • podobne ako na minulej prednáške veľkosť grafickej plochy závisí od veľkosti komponentu Image na formulári
  • budeme predpokladať, že je veľká aspoň 450x360 - aktuálnu veľkosť sa môžeme dozvedieť z premenných sirka a vyska (mohli by sme používať aj zápisy Image1.Width a Image1.Height) - pozor, tieto dve premenné dostanú hodnotu až po vytvorení korytnačky
  • počiatok súradnej sústavy (bod [0,0]) je v ľavom hornom rohu grafickej plochy, pričom x-ová os má kladné hodnoty vpravo a y-ová os má kladné hodnoty nador (opačne ako v matematike)
  • máme k dispozícii príkaz zmaz, ktorý zmaže obsah grafickej plochy, pričom korytnačka ostáva na svojom mieste (zmaz nie je korytnačí príkaz - nepíšeme pred neho k.)

Korytnačia programová jednotka - unit

  • aby sme mohli pracovať s korytnačou grafikou a definovať si vlastné korytnačky, musíme si projekt v Delphi špeciálne pripraviť - stiahnite si pripravenú programovú jednotku (unit) na prácu s korytnačkami KorUnit.pas
  • keď budete chcieť pracovať s korytnačím unitom, najprv musíte prekopírovať tento súbor do adresára, kde sa nachádza váš projekt a potom musíme do súboru Unit1.pas (súbor, v ktorom je definované správanie formulára) pridať jeden riadok najlepšie za riadok so slovom implementation:
    • uses KorUnit;

  • tento zabezpečí, že Delphi budú poznať korytnačiu grafiku. Programová jednotka KorUnit je tiež program v pascale a môžete si ju prezrieť, ak ju otvoríte pomocou Open... v menu File - neskôr sa naučíme porozumieť väčšine konštrukcií v tomto programe.

Prvé jednoduché programy

  • Predpokladáme, že na formulári je grafická plocha - komponent Image1 a tlačidlo Button1, ktorým sa bude spúšťať nejaká akcia, napr. vytvorenie korytnačky a nakreslenie nejakého obrázka:

program kreslí špirálu:

procedure TForm1.Button1Click(Sender: TObject);
var
  k:TKor;
  i:integer;
begin
  k:=TKor.Create(200,200,30);
  for i:=1 to 100 do begin
    k.dopredu(2*i);
    k.vpravo(90);
  end;
end;
  • ďalší príklad  využije vnorené cykly:

program nakreslí 8 otočených rovnostranných trojuholníkov:

var
  k:TKor;
  i,j:integer;
begin
  k:=TKor.Create;
  for j:=1 to 8 do begin
    for i:=1 to 3 do begin
      k.dopredu(100);
      k.vlavo(120);
    end;
    k.vpravo(45)
  end;
end;
  • priebeh kreslenia sme nemohli dobre sledovať, lebo prebehlo veľmi rýchlo
  • výpočet môžeme spomaľovať:
    • príkaz cakaj( číslo ); - pozastaví výpočet na príslušný počet milisekúnd (cakaj(1000); znamená zdržanie 1 sekundu)
  • ... uhly aj dĺžky nemusia byť celé čísla, hoci sa korytnačka na obrazovke zobrazuje v nejakom rastri:

pomalé kreslenie trojuholníka:

var
  k:TKor;
  i,j:integer;
begin
  k:=TKor.Create(200,200,20);
  for i:=1 to 3 do begin
    for j:=1 to 1000 do k.dopredu(0.1);
    for j:=1 to 1200 do k.vlavo(0.1);
  end;
end;

Viac korytnačiek

  • v programe môžeme vytvoriť a aj riadiť naraz viac korytnačiek
  • dáme im rôzne mená, napr. k1, k2, ... a pred každý korytnačí príkaz napíšeme príslušné meno, napr. k2.dopredu(...

dve korytnačky kreslia "paralelne":

var
  k1,k2:TKor;
  i:integer;
begin
  k1:=TKor.Create(150,200);
  k2:=TKor.Create(250,200);
  for i:=1 to 5 do begin
    k1.dopredu(80); cakaj(500); 
    k2.dopredu(150); cakaj(500); 
    k1.vpravo(144);
    k2.vpravo(144);
  end;
end;

Ďalšie úlohy

zaujímavá špirála:

var
  k:TKor;
  d:integer;
begin
  k:=TKor.Create(200,200,20);
  for d:=1 to 2000 do begin
    k.dopredu(5);
    k.vpravo(d);     // vyskúšajte:    k.vpravo(d+0.1);
    cakaj(1);
  end;
end;

kružnica ako pravidelný 360-uholník so stranou 2:

var
  k:TKor;
  n:integer;
begin
  k:=TKor.Create(100,200);
  for n:=1 to 360 do begin
    k.dopredu(2);
    k.vpravo(1);
  end;
end;

lupeň kvetu je vytvorený z dvoch štvrťkruhov:

var
  k:TKor;
  i,j,n:integer;
begin
  k:=TKor.Create;
  k.ZmenHP(7); k.ZmenFP(clRed);
  for i:=1 to 7 do begin
    for j:=1 to 2 do begin
      for n:=1 to 90 do begin
        k.dopredu(2);
        k.vpravo(1);
      end;
      k.vpravo(90);
    end;
    k.vpravo(360/7);
  end;
end;

program kreslí všeobecný N-uholník:

const
  N=15;    // sem môžeme nastaviť ľubovoľnú hodnotu N-uholníka
var
  k:TKor;
  i:integer;
begin
  k:=TKor.Create(100,200);
  for i:=1 to N do begin
    k.dopredu(50);
    k.vpravo(360/N);
  end;
end;

Objekt korytnačka

V doterajších príkladoch sme zadefinovali a používali buď celočíselné premenné (integer) alebo premenné typu Korytnačka. Tieto korytnačkové premenné sa líšia od "obyčajných" premenných tým, že

  • si pamätajú svoj momentálny stav v svojich tzv. stavových premenných (napr. pozícia, farba, ...)
  • majú svoje súkromné príkazy, pomocou ktorých ich nejako riadime, resp. meníme ich stavové premenné - takýmto príkazom - sú to procedúry - hovoríme metódy a "rozumejú" im len korytnačky (premenné typu TKor)
  • musia byť vytvorené (nie deklarované) špeciálnym spôsobom ( TKor.Create(...); ) a kým sa takto nevytvoria, nesmú sa vôbec používať
  • takýmto premenným hovoríme OBJEKT a typom, z ktorých vytvárame objekty (napr. TKor) hovoríme TRIEDA (po anglicky object a class); niekedy sa objektu hovorí aj inštancia triedy.
  • okrem korytnačiek sme sa už stretli aj s inými objektmi, napr. Form1, Image1, Button1 aj premenná g, ktorá bola inštanciou triedy TCanvas
  • zatiaľ si o objektoch treba zapamätať, že sú to premenné, ktoré môžu v sebe obsahovať veľa stavových premenných a tiež "v sebe" obsahujú nejaké svoje procedúry (metódy) => tomuto hovoríme zapuzdrenie (enkapsulácia), lebo v jednom "puzdre" sú aj údaje (stavové premenné) aj algoritmy (metódy), ktoré vedia s týmito údajmi pracovať.

Trieda korytnačka - TKor

  • pre prvé zjednodušenie si povedzme, že trieda TKor (a teda aj každá jej inštancia) má tieto stavové premenné:
    • X, Y a Smer určujú momentálnu polohu v ploche a natočenie v  stupňoch
    • FP a HP nesú informáciu o farbe pera a hrúbke pera
    • Dole je logická hodnota (pravda/nepravda), v ktorej si korytnačka pamätá, či má momentálne svoje pero spustené dole
  • niektoré z týchto premenných môžeme v programe normálne používať (s príponou k.), napr.
    • k.Smer := k.Smer + 45;    // je to to isté ako  k.vpravo(45);
      k.HP := 10;
      k.FP := clBlue;

  • stavové premenné X a Y môžeme meniť len pomocou metód (napr. ZmenXY), ale ich hodnotu môžeme používať, napr.
    • k.ZmenXY( k.X, 100*sin(k.X) );

  • obsahuje ďalšie metódy, napr. vypln, pis, smerom

Ďalšie korytnačie príkazy

pomocné príkazy:

  • PresunXY( x, y );
    • presunie korytnačku do bodu (x,y), pričom nekreslí čiaru aj keď má spustené pero
  • Vypln( farba );
    • vyplní farebne ohraničenú oblasť pod korytnačkou danou farbou
  • Pis( text );
    • vypíše do plochy text
  • funkcia Smerom( x, y ) vráti číslo
    • vyjadruje absolútny uhol v stupňoch, do ktorého by sa musela otočiť korytnačka, aby bola natočená k bodu (x,y)
    • najčastejšie sa použije ako k.ZmenSmer(k.Smerom(x,y));

Práca s farbami

  • už sme sa zoznámili s niekoľkými situáciami, keď sme zadávali nejakú farbu (farba pera, farba výplne, farba obrysu) - doteraz sme používali preddefinované konštanty, napr. clBlack, clRed, clBlue a pod.
  • vo Windows sa farba určuje trojicou čísel, ktoré vyjadrujú v akom množstve treba "namiešať" tri základné farby červenú, zelenú a modrú, aby vznikla žiadaná farba - množstvá týchto zložiek sa zadávajú celým číslom od 0 do 255
    • napr. ak namiešame 0 červenej, 0 zelenej a 255 modrej, vznikne jasná modrá farba;
    • 0 červenej, 0 zelenej a 0 modrej je čierna; všetky zložky po 255 znamená bielu;
    • 255 červenej, 255 zelenej a 0 modrej vyrobí žltú a pod.
  • vo Windows sa tieto zložky nazývajú Red Green Blue, teda RGB a v Delphi môžeme farby definovať aj pomocou funkcie RGB, ktorá dostáva 3 čísla popisujúce zastúpenie zložiek
  • vymenujeme všetky užitočné preddefinované farby, poexperimentujte s nimi (uvádzame ich RGB hodnoty)

mená niektorých preddefinovaných farieb:

clBlack
clMaroon
clGreen
clOlive
clNavy
clPurple
clTeal
clGray
clSilver
clRed
clLime
clYellow
clBlue
clFuchsia
clAqua
clLtGray
clDkGray
clWhite

RGB(0,0,0)
RGB(128,0,0)
RGB(0,128,0)
RGB(128,128,0)
RGB(0,0,128)
RGB(128,0,128)
RGB(0,128,128)
RGB(128,128,128)
RGB(192,192,192)
RGB(255,0,0)
RGB(0,255,0)
RGB(255,255,0)
RGB(0,0,255)
RGB(255,0,255)
RGB(0,255,255)
RGB(192,192,192)
RGB(128,128,128)
RGB(255,255,255)

  • nasledujúci program ilustruje použitie RGB funkcie:

kreslenie rôznofarebných prúžkov:

var
  k:TKor;
  i:integer;
begin
  k:=TKor.Create(20,120); k.HP:=10;
  for i:=1 to 40 do begin
    k.FP:=RGB(0,0,55+5*i);
    k.dopredu(100);
    k.PresunXY(k.X+10,k.Y+100);
  end;
  k.PresunXY(20,240);
  for i:=1 to 40 do begin
    k.fp:=RGB(261-6*i,15+6*i,0);
    k.dopredu(100);
    k.PresunXY(k.X+10,k.Y+100);
  end;
  k.PresunXY(20,360);
  for i:=1 to 40 do begin
    k.fp:=RGB(random(256),random(256),random(256));
    k.dopredu(100);
    k.PresunXY(k.X+10,k.Y+100);
  end;
end;

Formátovanie programov

  • väčšina profesionálnych programátorov je veľmi citlivá na naformátovanie programov a veľmi často prvý pohľad na program prezradí, či je programátor začiatočník amatér alebo skúsenejší programátor
  • je uznávaných niekoľko spôsobov formátovania pascalovských programov a je niekoľko pravidiel, ktoré platia skoro pre všetky tieto štýly:
    • príkazy, ktoré sú na rovnakej úrovni vnorenia, sú buď na tom istom riadku alebo začínajú v tom istom stĺpci
    • zátvorky zložených príkazov (napr. begin a end), ak nie sú v jednom riadku,  
      • sú odsadené v tom istom stĺpci
      • alebo begin je na konci nadradeného príkazu a  príslušné end je zarovnané na začiatok nadradeného príkazu (takto zapisujeme všetky príklady v prednáškach)
    • počet medzier (odsadenie) na začiatku riadka by malo lineárne vyjadrovať úroveň vnorenia príkazu - najčastejšie je každé ďalšie vnorenie odsunuté o 2 medzery
  • zlé naformátovanie programu sa považuje za zlomyseľnosť a slúži len na skomplikovanie čitateľnosti programu, pozrite si preformátovaný predchádzajúci program:

úmyselne zle naformátovaný program:

procedure TForm1.Button12Click(Sender: TObject);
var k:TKor;i: integer;begin
k:=TKor.Create(20,
120); k.HP:=10;
    for i:=1 to 40 do begin
  k.FP:=RGB(0,0,55+5*i);k.dopredu(100);

    k.PresunXY(k.X+10,k.Y+100);end;k.PresunXY(20,240);
      for i:=1 to 40 do
begin
      k.fp:=RGB(261-6*i,15+6*i,0);
      k.dopredu(100);
      k.PresunXY(k.X+10,k.Y+100);end;
      k.PresunXY(20,360);for i:=1 to 40 do begin
      k.fp:=RGB(random(256),random(256),random(256));
      k.dopredu(100);
      k.PresunXY(k.X+10,k.Y+100);
end;end;

    tento program po spustení robí presne to isté ako predchádzajúci príklad s RGB - prekladaču Delphi je jedno, ako je to naformátované


© 2002 AB, KVI
blaho@fmph.uniba.sk