Program Cilindro;
Uses crt,graph;

type
  TFIGURA = object
    public
      x,y: integer;
      constructor criar (nx,ny:integer);
      procedure mover (dx,dy:integer);
      procedure mostrar; virtual;
      procedure ocultar; virtual;
    private
    end;

  TCILINDRO = object (TFIGURA)
    public
      raio,h : integer;
      nivel : word;
      cor: byte;
      constructor criar (nx,ny,nr,nh:integer;ncor:byte;nnivel:word);
      procedure mostrar; virtual;
      procedure ocultar; virtual;
      procedure maisnivel (quanto:integer);
      procedure maish (quanto:integer);
      procedure maisraio (quanto:integer);

      function AreaBase:real;
      function AreaLateral:real;
      function AreaTotal:real;
      function Volume:real;
      function VolumeOcupado:real;
    private
    end;

var
  k:char;
  cil:TCILINDRO;
  vel: byte;


  {------------------------------------------------------------}
  constructor TFIGURA.criar (nx,ny:integer);
  begin
   x:=nx;
   y:=ny;
  end;

  procedure TFIGURA.mover (dx,dy:integer);
  begin
   ocultar;
   x:=x + dx;
   y:=y + dy;
   mostrar;
  end;

  procedure TFIGURA.mostrar;
  begin
   putpixel(x,y, white);
  end;

  procedure TFIGURA.ocultar;
  begin
   putpixel(x,y,getbkcolor);
  end;

 {------------------------------------------------------------}
  constructor TCILINDRO.criar(nx,ny,nr,nh:integer;ncor:byte;nnivel:word);
  begin
   x:=nx;
   y:=ny;
   raio:=nr;
   h:=nh;
   cor:=ncor;
   nivel:=nnivel;
  end;

  procedure TCILINDRO.mostrar;
  var temp:integer;
  begin
   temp:=nivel*h shr 8;
   if temp>0 then begin
     SetFillStyle(1,cor);
     bar(x-raio+1,y-temp,x+raio-1,y);
   end;
   setcolor (white);
   rectangle(x-raio,y-h,x+raio,y);
  end;

  procedure TCILINDRO.ocultar;
  begin
   SetFillStyle(0,getbkcolor);
   bar(x-raio,y-h,x+raio,y);
  end;

  procedure TCILINDRO.maisnivel(quanto:integer);
  begin
    ocultar;
    if (nivel+quanto>=0) AND (nivel+quanto<=256) then
      nivel:=nivel+quanto;
    mostrar;
  end;

  procedure TCILINDRO.maish(quanto:integer);
  begin
    ocultar;
    if h+quanto>=0 then
      h:=h+quanto;
    mostrar;
  end;

  procedure TCILINDRO.maisraio(quanto:integer);
  begin
    ocultar;
    if raio+quanto>=0 then
      raio:=raio+quanto;
    mostrar;
  end;

  function TCILINDRO.AreaBase:real;
  begin
    AreaBase:=raio*raio*PI;
  end;

  function TCILINDRO.AreaLateral:real;
  begin
    AreaLateral:=2*raio*h*PI;
  end;

  function TCILINDRO.AreaTotal:real;
  begin
    AreaTotal:=2*AreaBase+AreaLateral;
  end;

  function TCILINDRO.Volume:real;
  begin
    Volume:=AreaBase*h;
  end;

  function TCILINDRO.VolumeOcupado:real;
  begin
    VolumeOcupado:=AreaBase*(nivel*h shr 8);
  end;


procedure IniciaGrafico;
var grDriver, grMode :integer;
begin
  grDriver := Detect;
  InitGraph(grDriver, grMode,'');
end;

procedure FechaGrafico;
begin
 closegraph;
end;



BEGIN

IniciaGrafico;
vel:=2;
cil.criar(200,200,30,100,yellow,16);
cil.mostrar;

repeat

 k:=readkey;
 if k=#0 then begin
   k:=readkey;
   case k of
     #82 : cil.maisnivel(+8); {Insert}
     #83 : cil.maisnivel(-8); {Delete}

     #73 : cil.maish(+vel); {PageUp  }
     #81 : cil.maish(-vel); {PageDown}

     #71 : cil.maisraio(+vel); {Home}
     #79 : cil.maisraio(-vel); {End }
   end;
 end else begin
   case k of
     '8' : cil.mover(   0,-vel);
     '2' : cil.mover(   0,+vel);
     '4' : cil.mover(-vel,   0);
     '6' : cil.mover(+vel,   0);

     '7' : cil.mover(-vel,-vel);
     '9' : cil.mover(+vel,-vel);
     '1' : cil.mover(-vel,+vel);
     '3' : cil.mover(+vel,+vel);

     '+' : inc(vel,1);
     '-' : if vel>0 then dec(vel,1);
   end;
 end;

until k=#27;

FechaGrafico;

END.
