
{$G+} { //-- Generar c¢digo 286  }

program Karate;

uses crt,dos;
const

incre=1;
tamax=8;
tamay=10;
maxelem=900;

graf1:Array [1..tamay,1..tamax] of byte=(
(0,0,1,1,0,0,0,0),
(0,0,1,7,1,0,0,0),
(0,1,1,1,1,0,0,0),
(0,1,2,2,0,0,0,0),
(0,2,1,1,0,0,0,0),
(0,0,2,4,4,0,0,0),
(0,1,1,2,0,0,0,0),
(0,1,0,1,0,0,0,0),
(1,0,0,1,0,0,0,0),
(3,3,0,3,3,0,0,0)
)
;

graf2:Array [1..tamay,1..tamax] of byte=(
(0,0,1,1,0,0,0,0),
(0,0,1,7,1,0,0,0),
(0,1,1,1,1,0,0,0),
(0,1,2,2,0,0,0,0),
(0,1,1,2,2,2,4,4),
(0,0,1,1,0,0,4,0),
(0,1,1,1,0,0,0,0),
(0,1,0,1,0,0,0,0),
(1,0,0,1,0,0,0,0),
(3,3,0,3,3,0,0,0)

)
;

graf3:Array [1..tamay,1..tamax] of byte=(
(0,0,1,1,0,0,0,0),
(0,0,1,7,1,0,0,0),
(0,1,1,1,1,0,0,0),
(0,1,2,2,0,0,0,0),
(0,2,1,1,0,0,0,0),
(0,0,2,4,4,0,0,0),
(0,0,1,2,0,0,0,0),
(0,0,1,1,0,0,0,0),
(0,0,1,1,0,0,0,0),
(0,0,3,3,3,0,0,0)
)
;

graf4:Array [1..tamay,1..tamax] of byte=(
(0,10,0,0,0,0,0,0),
(0,0,10,0,0,0,0,0),
(0,10,0,0,6,0,6,0),
(0,0,0,0,0,0,0,0),
(0,6,0,10,0,0,0,0),
(0,0,0,0,0,0,6,0),
(0,2,0,0,10,0,0,0),
(0,0,6,0,0,0,0,0),
(0,0,0,0,0,10,0,0),
(0,20,0,0,0,0,0,0)
)
;

type
   Graficodef=Array [1..tamay,1..tamax] of byte;     {Sprites tamayx}
   pantalla=Array[0..199,0..219] of byte;
   pantalla_virtual=^pantalla;
   grafico=^Graficodef;
   apuntador=^byte;
   elemento=record
              x,y:word;
            end;
{ //---------------------------------------------------------------------- }

var
numesp:word;

vaddr:pantalla_virtual;
dpvir:longint;
fondo:pantalla_virtual;
MONIGOTE,MONIGOTE2,MONIGOTE3,MONIGOTE4:grafico;
tecla:char;
x,y:integer;
i,j:word;
posiciones:array [1..maxelem] of elemento;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
Procedure SetVga256;  { Para inicializar el modo 320x200 256 colores }
BEGIN
  asm
     mov        ax,0013h
     int        10h
  end;
END;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}

Procedure SetUpVirtual;
   { Inicializa un pantalla virtual }
BEGIN
  GetMem (fondo,64000);
  GetMem (vaddr,64000);
  GetMem (monigote,sizeof(graficodef));
  GetMem (monigote2,sizeof(graficodef));
  GetMem (monigote3,sizeof(graficodef));
  GetMem (monigote4,sizeof(graficodef));

END;

{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
procedure flip(source:pantalla_virtual); assembler;
  { Copia la pantalla que le indiquemos, al destino que querramos }
  { por ejemplo, para visualizar una pantalla virtual }


  asm
    push    ds
    push    ax
    push    cx
    push    di
    push    si

    mov     ax, $A000
    mov     es, ax
    mov     ax, word ptr [Source+2]
    mov     ds, ax
    mov     si, word ptr [Source]
    xor     di, di
    mov     cx, 32000
    rep     movsw

    pop     si
    pop     di
    pop     cx
    pop     ax
    pop     ds
  end;




{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
procedure CopFondEnVirt(source,dest:pantalla_virtual); assembler;
  { Copia la pantalla que le indiquemos, al destino que querramos }
  { por ejemplo, para visualizar una pantalla virtual }


  asm
    push    ds
    push    ax
    push    cx
    push    di
    push    si

    mov     ax, word ptr [dest+2]
    mov     es, ax
    mov     ax, word ptr [Source+2]
    mov     ds, ax
    mov     si, word ptr [Source]
    mov     di, word ptr [dest]
    mov     cx, 32000
    rep     movsw

    pop     si
    pop     di
    pop     cx
    pop     ax
    pop     ds
  end;




{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
Procedure ShutDown;
    { libera la memoria que ocupa en el Heap, la pantalla virtual }
BEGIN
  FreeMem (vaddr,64000);
  FreeMem (fondo,64000);
  FreeMem (monigote,sizeof(graficodef));
  FreeMem (monigote2,sizeof(graficodef));
  FreeMem (monigote3,sizeof(graficodef));
  FreeMem (monigote4,sizeof(graficodef));

END;
{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
PROCEDURE MODOTEXTO;
begin
  asm
    mov ax,3
    int 10h
  end;
end;


{//-------------------------------------------------------------------------}
Procedure Cls (Where:pantalla_virtual;Col : Byte);assembler;
   { Borra la pantalla que le indiquemos, con el color que queramos }

     asm
        push    ds
        push    ax
        push    cx
        push    di
        push    si
        push    es
        mov     cx, 32000;
        mov     ax,word ptr [where+2]
        mov     es,ax      {bingo, segmento y desplazamiento al que
                            apunta where}
        mov     di,word ptr [where]
        mov     al,[col]
        mov     ah,al
        rep     stosw
        pop     es
        pop     si
        pop     di
        pop     cx
        pop     ax
        pop     ds


     End;

{//-------------------------------------------------------------------------}



Procedure poner_sprite(x,y:word;tx,ty:word;origen:Grafico;lugar:pantalla_virtual); assembler;

{Sintaxis pone un sprite de tama¤o tx*ty en una pantalla virtual}

Asm
    push ds

    mov     cx,[ty]

@otro: mov     ax,word ptr [lugar+2]
    mov     es,ax
    mov     ax,word ptr [origen+2]
    mov     ds,ax

    

    mov     bx,[X]
    mov     dx,[Y]
    mov     di,bx
    mov     bx, dx             {     ; bx = dx     }
    shl     dx, 8
    shl     bx, 6
    add     dx, bx              {    ; dx = dx + bx (ie y*320)   }
    add     di, dx               {   ; finalise location}

    mov     si,word ptr [origen]{+sy*320}
    mov     ax,[tx]
    mov     bx,cx
    dec     bx
    mul     bx
    add     si,ax

    add     di, word ptr [lugar]{+sy*320}
    mov     ax,320
    mov     bx,cx
    dec     bx
    mul     bx
    add     di,ax

    push cx
       mov cx,[tx]
 @otro2:cmp byte ptr ds:[si],0
        je  @transp
        movsb
        jmp @siguiente
@transp:inc si  {Pasamos de el por ser transparente}
        inc di
@siguiente:loop @otro2


    pop  cx
    loop @otro

    pop ds
 @fin:
 End;



procedure ACTUALIZA(x,y:word); { //... Actualiza la pantalla }
var
sx,sy:integer;
conta,conta2:word;
color:byte;
grafaux:grafico;
origen:longint;
begin

  color:=7;

{  cls (fondo,15);}  {Hacemos un CLS sobre la pantalla de reserva}
  CopFondEnVirt(fondo,vaddr);

 { origen:=random(500);
  move(origen,vaddr^,64000);}

  if not(tecla='m') then

      if random(2)=1 then grafaux:=monigote        {tio normal}
      else grafaux:=monigote3
   else
   grafaux:=monigote2;        {tio da patada}
   poner_sprite(x,y,tamax,tamay,grafaux,vaddr);

   for i:=1 to maxelem do
   begin
    CASE (RANDOM(3)) OF
     0:grafaux:=monigote;          {tio normal}
     1:grafaux:=monigote2;        {tio da patada}
     2:grafaux:=monigote3;        {tio ANDA}
    END;
    with posiciones[i] do
    begin
      poner_sprite(x,y,tamax,tamay,grafaux,vaddr);
     end;
   end;

  
   {posicionx,la y,tama¤o x, y,donde ponerlo,origen}
  flip (vaddr);
  {Copia pantalla virtual a pantalla real}
   
end;
{//-------------------------------------------------------------------------}

PROCEDURE INICIA;
begin
 setvga256;
 setupvirtual;

 
end;
{//-------------------------------------------------------------------------}
Var
    h0,m0,s0,c0:word;
    h1,m1,s1,c1:word;

begin
writeln('La siguiente demo mueve 900 sprites de tama¤o 8x10 .');
writeln('Da los tiempos inicial y final antes del ultimo fotograma.');
writeln('Salir = "s"');
while not keypressed do;
tecla:='?';
inicia;

x:=0;
y:=0;


for i:=1 to maxelem do
begin
   posiciones[i].x:=random(300);
   posiciones[i].y:=random(170);
end;


for i:=1 to tamax do for j:=1 to tamay do Monigote^[j,i]:=graf1[j,i];
for i:=1 to tamax do for j:=1 to tamay do Monigote2^[j,i]:=graf2[j,i];
for i:=1 to tamax do for j:=1 to tamay do Monigote3^[j,i]:=graf3[j,i];
for i:=1 to tamax do for j:=1 to tamay do Monigote4^[j,i]:=graf4[j,i];

cls(fondo,15);
                {llena fondo de matas}

for j:=0 to 1000 do
   poner_sprite(random(310),random(190),tamax,tamay,monigote4,fondo);

repeat
     if tecla='m' then tecla:='?';
     if keypressed then tecla:=readkey;
     case tecla of
      'q':y:=y-incre;
      'a':y:=y+incre;
      'o':x:=x-incre;
      'p':x:=x+incre;
     end;

     if y>199-tamay then y:=199-tamay;
     if x>319-tamax then x:=319-tamax;
     if y<0 then y:=0;
     if x<0 then x:=0;
     for i:=1 to maxelem do
      begin
         posiciones[i].x:=posiciones[i].x+(random(incre*2+1)-(incre));
         posiciones[i].y:=posiciones[i].y+(random(incre*2+1)-(incre
         ));

         if posiciones[i].y>195-tamay then posiciones[i].y:=195-tamay;
         if posiciones[i].x>315-tamax then posiciones[i].y:=315-tamax;
         if posiciones[i].y<5 then posiciones[i].y:=5;
         if posiciones[i].x<5 then posiciones[i].x:=5;
      end;


   

     gettime(h0,m0,s0,c0);
     actualiza(x,y);
     gettime(h1,m1,s1,c1)
    
until tecla='s';

shutdown;
modotexto;
writeln(h0,'h',m0,'m',s0,'s',c0,'c');
writeln(h1,'h',m1,'m',s1,'s',c1,'c');
while not keypressed do;

end.
