[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]

    program new_flame_test;
    {New! FLAME by OVERLAYING! Flame that you have *NEVER* seen!
     By Nelson Chu, July 1996, Macau}
    {$X+,S-,R-,E-,N-,G+,D-,L-,A+}
    uses crt, graphic{, misc};
    {Unit GRAPHIC to be found in GRAPHICS.SWG }

    const width  = 62;  height = 80; intensity  = 190; hot = width div 2;
          reserved = width div 10;
          quit:boolean=false;      dx:byte=10; dc:byte=25;

    type ftype=array[0..height+1, 0..width+1] of byte;

    var f:array[1..2] of ftype;
        t :word; a:byte;

    procedure setpal;
    var a,x:byte;
    begin
     for a:= 1 to 32 do setcolor(a,0,0,a*2-1);
     for a:= 1 to 32 do setcolor(a+32,0,a*2-1,63);
     for a:= 1 to 32 do setcolor(a+32*2,a*2-1,63,63);

     for a:= 32*2+1 to 120 do setcolor(a,63,63,63);
     for a:= 1 to 63 do setcolor(120+a,64-a,64-a,64-a);
     for a:= 120+64 to 255 do setcolor(a,0,0,0);
    end;

    procedure showflame(var flame:ftype; x,y:word);
    var a: byte;
    begin
    for a:= 1 to height-2 do
    move( flame[a], screen^[a+y, x + sine[byte((t+a) shl 2)] div 32],
          sizeof(flame[1]));
    end;

    procedure clearbuf(var flame:ftype);
    begin fillchar(flame,sizeof(flame),#0); end;

    procedure genfrow(var flame:ftype);{GENerate Front ROW}
    var b: byte;
    begin
     for b:= 1 to hot div 2 do
      flame[height,reserved+random(width-reserved*8)+1]:=intensity;
     for b:= 1 to hot div 2 do
      flame[height,reserved*4+random(width-reserved*8)+1]:=intensity;
    end;

    procedure up(var flame:ftype);
    begin move(flame[2],flame[1],(width+2)*(height-1)); end;

    procedure render2(sfm,ofm:word);
    var a,b,base:word;
    const w=width+2;
    begin
    for a:= height downto 1 do
    for b:= 1 to width do
    begin
    base:=ofm+a*w+b;
     mem[sfm:base]:= (mem[sfm:base+1] + mem[sfm:base-1] +
                      mem[sfm:base+w-1] + mem[sfm:base+w+1] )
                      div 4;
    end;
    end;

    procedure render(sfm,ofm:word);
    var a,b,base:word;
    const w=width+2;
    begin
    for a:= height downto 1 do
    for b:= 1 to width do
    begin
    base:=ofm+a*w+b;
    case random(2) of{don't forget to add some random factor;)}
    0:mem[sfm:base]:= ((mem[sfm:base-w-2] + mem[sfm:base-w+2]) +
                      (mem[sfm:base-1] + mem[sfm:base+1]) +
                      mem[sfm:base+w] * 2
                      )
                     div 6;
    {1:mem[sfm:base]:= (mem[sfm:base+2] + mem[sfm:base] +
                      mem[sfm:base+w] + mem[sfm:base+w+2] )
                      div 4;
    2:mem[sfm:base]:= (mem[sfm:base-2] + mem[sfm:base] +
                      mem[sfm:base+w] + mem[sfm:base+w-2] )
                      div 4}
    else
      mem[sfm:base]:= (mem[sfm:base+1] + mem[sfm:base-1] +
                      mem[sfm:base+w-1] + mem[sfm:base+w+1] )
                      div 4;
    end;{case}
    end;
    end;

    procedure combineshow(x,y:word);
    var a,b,base:word; temp:byte; p1,p2:shortint;
    begin
    {showflame(f[1], x,y);}
    for a:= height-2 downto 1 do
    for b:= 1 to width do
     begin
     p1:= sine[byte((t+a)*2)] shr 7;
     p2:= sine[byte((t+10+a)shl 2 + random(3) )] shr 6 +
          sine[byte((t shl 1+a)shl 2)] shr 7 - p1;

     screen^[ y+a, x+b ]:= f[1][a,b + p1] - f[1][a,b + p2+dx]+dc;
                                         {^ This minus sign means negative
                                            overlaying, secret of the strange
                                            flame ;)}
    {dec(screen^[ y+a, x+b ], f[2][a,b + p2-10]-60);}
     end;
    end;

    procedure init;
    begin
    setcrtmode($13);
    setpal;
    clearbuf(f[1]); clearbuf(f[2]);
    directvideo:=false;
    textcolor(70);
    gotoxy(4,24);write('Old flame with');
    gotoxy(7,25);write('sin effect');
    gotoxy(22,24);write('My new flame!(with');
    gotoxy(23,25);write('sin effect,too.)');
    end;

    begin
    init;

    repeat
          for a:=1 to 1 do
          begin
          genfrow(f[a]);
          up(f[a]);
          render2(seg(f[a]), ofs(f[a]));
          vSync;
          showflame( f[a], a*(width+10), 200-height-16);
          combineshow(200, 200-height-16);
          end;
          inc(t);
    until keypressed;
    readkey;
    gotoxy(6,10);write('Now both stopped ''generating''.');
    repeat
          vSync;
     {     showflame( f[a], a*(width+10), 200-height-16);}
    {uncomment the about call if you want to see a just-sinus flame}
          combineshow(200, 200-height-16);
          inc(t);
          if keypressed then
           case readkey of
           #27:quit:=true;{ESC ah!}
           'z':inc(dx);
           'x':dec(dx);
           'a':inc(dc);
           's':dec(dc);
          end;
    until quit;
    setcrtmode($3);
    writeln('By Nelson Chu 1996.');
    end.
    { Well, I originally wanted to do it by just "adding" two flame buffers with
      sinusoidal displacement to make a moving flame without "generating" it. But
      I tried "minusing" one from the other, and it turned out to be very nice!
      I was so happy when I got this...

      I think "adding" two flame buffers can give you a flame which resembles
      those found in the kitchen(blue when gas is burning, with momentary
      orange/red spurts from the bottom.). You want to try it?

      Enjoy!

      By Nelson Chu  Internet e-mail: eg_cshaa@stu.ust.hk}
    P.S. Did you know that I'm from Hong Kong? (Consult your geographic teacher
    if you don't know where Hong kong is. ;)

[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]