{$mode objfpc}{$unitpath lib}programnatal2016;usessysutils,strutils,types,math,ptccrt,ptcgraph,typex,graphix;const// Códigos para as cores usadasGREEN=9900;YELLOW=65200;BLUE=9500;ORANGE=64200;{$i inc/draw.inc}const// Posicionamento da árvore; referência para restantes elementosINITPOS:TPoint=(x:50;y:100);INITSIZE:TSize=(cx:50;cy:100);ITERTREE=5;// Textos a apresentarPROMPT1='Merry Year';PROMPT2='and a';PROMPT3='Happy New Xmas!';PROMPT4='... or something...';// Velocidade da coloração da árvoreSPEEDMIN=50;SPEEDMAX=1000;SPEEDSTEP=50;// Gestão de cores da árvoreCOLORMIN=63487;COLORMAX=65535;COLORSTEP=300;var// Gestão gráficaerr:smallint;// Erro de inicializaçãodriver,mode:smallint;// Modo e driver a usar// Navegação e outrosi,f:longint;key:char;speed:word=SPEEDMIN;beginDetectGraph(driver,mode);mode:=m1024x768;// OverrideInitGraph(driver,mode,'');err:=GraphResult;iferr<>grOkthenbeginwriteln('Initialization exception [InitGraph]: ',GraphErrorMsg(err));readlnendelsebegin// Inicializa árvoreSetFillStyle(SolidFill,0);fori:=2toITERTREEdobeginifi>1thenBar(INITPOS.x-5,INITPOS.y-5,INITPOS.x*(i-1)+INITSIZE.cx*(i-1)+5,INITPOS.y+INITSIZE.cy*(i-1)+5);DrawTree(INITPOS,INITSIZE*i);Sleep(1000);end;// Coloca os textosSetTextStyle(SansSerifFont,HorizDir,GetBestFit(PROMPT4,(ITERTREE+1)*INITSIZE.cx+3*INITPOS.x));SetColor(GREEN);SlideText((ITERTREE+2)*INITSIZE.cx,250,PROMPT1);SetColor(ORANGE);SlideText((ITERTREE+2)*INITSIZE.cx,300,PROMPT2);SetColor(YELLOW);SlideText((ITERTREE+2)*INITSIZE.cx,350,PROMPT3);Sleep(1500);SetColor(BLUE);SlideText((ITERTREE+2)*INITSIZE.cx,550,PROMPT4);// Legenda de utilizaçãoSleep(500);SetTextStyle(SansSerifFont,HorizDir,1);SetColor(GREEN);OutTextXY(INITPOS.x,650,' Velocidade = '+IntToStr(speed)+' ms ');OutTextXY(INITPOS.x,652,'_______________________');SetColor(BLUE);OutTextXY(INITPOS.x,660,'+ aumentar | - diminuir');OutTextXY(INITPOS.x,670,'0 minimo | 1 maximo');SetColor(YELLOW);OutTextXY(INITPOS.x,685,'ESC sair');// Animação da árvoreSetColor(BLUE);i:=YELLOW;f:=1;repeatwhilenotKeyPresseddobegin// Gestão automática de coresifi+COLORSTEP>COLORMAXthenf:=-1elseifi-COLORSTEP<COLORMINthenf:=1;i:=i+(COLORSTEP*f);DrawTree(INITPOS,INITSIZE*5,i);Sleep(speed);end;// Tecla foi premida: qual?repeatkey:=ReadKey;untilkey<>#0;// Descarta teclas "especiais"ifkeyin['+','-','0','1']thenbegin// Gestão da velocidadecasekeyof'+':ifspeed<SPEEDMAXthenInc(speed,SPEEDSTEP);'-':ifspeed>SPEEDMINthenDec(speed,SPEEDSTEP);'0':speed:=SPEEDMIN;'1':speed:=SPEEDMAX;end;// Actualiza indicadorBar(INITPOS.x,650,INITPOS.x+TextWidth('_______________________'),650+TextHeight('X'));SetColor(GREEN);OutTextXY(INITPOS.x,650,' Velocidade = '+IntToStr(speed)+' ms ');end;untilkey=#27;// ESC para sair// Libertar recursos gráficosClearDevice;CloseGraph;end;end.
typeTPointList=arrayofTPoint;functionNewPoint(x,y:LongInt):TPoint;(* Cria TPoint in loco sem necessidade de variável temporária. *)beginNewPoint.x:=x;NewPoint.y:=y;end;functionNewSize(x,y:LongInt):TSize;(* Cria TSize in loco sem necessidade de variável temporária. *)beginNewSize.cx:=x;NewSize.cy:=y;end;procedureDrawTree(position:TPoint;size:TSize;constCOLORLINES:word=65200);(* Desenho da árvore, com gestão automática das ramificações. *)constMINIMUM=10;varbranches:longword=0;// Ramificações que constroem visualmente a árvoreleft:TPointList=nil;// Lado esquerdo da árvoreright:TPointList=nil;// Lado direito da árvorejump:longword;// Para cálculo dos pontosi,x:longword;// Auxiliaresbegin// Ajuste automático de branches:i:=10;while(size.cxmod(2*(size.cydivi))<>0)doInc(i);branches:=size.cydivi;if(branches<MINIMUM)thenbeginOutTextXY(10,10,'ERRO!');WriteLn('Ajuste automático falhou. As definicoes fornecidas sao lastimaveis!');Exit;end;// Árvore começa no canto inferior esquerdo e termina no vértice superior do triângulo// Vértice superior pode ficar em qualquer um dos lados da árvore: depende se 'branches' é par ou ímpar.// Sendo par, fica do lado esquerdo, logo ímpar é do lado direito.if(branchesmod2=0)thenbeginSetLength(left,branchesdiv2+1);SetLength(right,branchesdiv2);endelsebeginSetLength(left,(branches+1)div2);SetLength(right,(branches+1)div2);end;// Definição dos pontos dos dois lados:i:=0;x:=0;jump:=size.cxdiv(2*branches);whilei<Min(Length(left),Length(right))dobeginleft[i].x:=x;left[i].y:=size.cy-(i*2)*(size.cydivbranches);ifi<=High(right)thenbeginright[i].x:=size.cx-x-jump;right[i].y:=size.cy-(i*2+1)*(size.cydivbranches);end;Inc(x,2*jump);Inc(i);end;SetColor(COLORLINES);SetLineStyle(SolidLn,0,NormWidth);// Primeira linhaLine(position.x+left[0].x,position.y+left[0].y,position.x+right[0].x,position.y+right[0].y);// Restantes linhas, excepto últimafori:=1toMin(Length(left),Length(right))-1dobeginLine(position.x+left[i].x,position.y+left[i].y,position.x+right[i].x,position.y+right[i].y);Line(position.x+right[i-1].x,position.y+right[i-1].y,position.x+left[i].x,position.y+left[i].y);end;// Última linhaif(branchesmod2=0)thenLine(position.x+right[i-1].x,position.y+right[i-1].y,position.x+left[i].x,position.y+left[i].y)elseLine(position.x+left[High(left)].x,position.y+left[High(left)].y,position.x+right[High(right)].x,position.y+right[High(right)].y);// TriânguloSetColor(GREEN);SetLineStyle(SolidLn,0,ThickWidth);Line(position.x,position.y+size.cy,position.x+size.cx,position.y+size.cy);Line(position.x,position.y+size.cy,position.x+size.cxdiv2,position.y);Line(position.x+size.cx,position.y+size.cy,position.x+size.cxdiv2,position.y);// Libertar recursos dos arrays dinâmicosSetLength(left,0);SetLength(right,0);end;
(* Extension for unit types *){$mode objfpc}unittypex;interfaceusestypes;// Facilita algumas contas...operator*(s:TSize;v:LongInt)res:TSize;operator*(v:LongInt;s:TSize)res:TSize;implementationoperator*(s:TSize;v:LongInt)res:TSize;beginres.cx:=s.cx*v;res.cy:=s.cy*v;end;operator*(v:LongInt;s:TSize)res:TSize;beginres:=s*v;end;end.
(* Extension for unit graph and ptcgraph *){$mode objfpc}unitgraphix;interfaceusessysutils,ptcgraph;functionGetBestFit(constTXT:string;diff:word=0):Word;procedureSlideText(constX,Y:word;constPROMPT:string);implementationfunctionGetBestFit(constTXT:string;diff:word=0):Word;(* Obtém o melhor tamanho de letra para a dimensão horizontal da janela. diff -> Factor de redução de GetMaxX *)vari:word=0;beginwhileTextWidth(TXT)<(GetMaxX-diff)dobeginInc(i);SetTextStyle(SansSerifFont,HorizDir,i);end;GetBestFit:=i;end;procedureSlideText(constX,Y:word;constPROMPT:string);(* Animação de texto: aparece letra a letra a cada décimo de segundo. *)vari:word;beginfori:=1toLength(PROMPT)dobeginOutTextXY(X+TextWidth('X')*(i-1),Y,PROMPT[i]);ifPROMPT[i]<>' 'thenSleep(100);end;end;end.