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

    {This is my procedure for drawing DOOM-like floors for the game I am working
    on. It uses the similar triangle method, but does not work as fast as I
    would like. The problem is probably that I am using Turbo Pascal.  I tried to
    optimize using assembler, but have never used it before.   If anyone could
    help me speed it up, I would really appreciate it. I think this procedure runs
    at about 11-12 fps without my wall,objects procedures, at about 8 fps with
    them.  The wall,objects procedures run at about 20 fps without the floor
    procedure.  My goal is for a nice 15 fps with everything.  All speeds are on a
    486 DX2/66.

    Sorry for the sloppy code. I'll try to explain.}

    procedure floorcast(var player1:player);
    var
       xp,yp:integer;       {some of these variables might not be needed}
       z:word;
       i:byte;
       dd:longint;
       xstep,ystep:longint;
       scrd:integer;
       finx1,finy1:longint;
       finx2,finy2:integer;
       finxd,finyd:longint;
       distance:longint;
       cc,colour:byte;
       ssofs:word;
       s3,o3,o4,s4:word;
       mapx,mapy,bmapx,bmapy:byte;
       ang:integer;
       v1,v2:longint;
       lookm:integer;
       flm:byte;
       loop:integer;
       ssinc:byte;
       zinc:word;
       hh:word;
       shade:byte;
       cos2,sin2,cos1,sin1:longint;
       sf:byte;
    begin
    v1:=viewcos^[0];                {to fix the fishbowl effect}
    v2:=viewcos^[319];
    lookm:=(player1.look-100); {to find out if the player is looking up or down}
    loop:=(player1.look+1);    {number of h-lines to draw}
    hh:=(vdis)*player1.height;  {viewer distance * player height}
    ang:=dangle(0,-dangle(player1.angle,(-160)));  {angle for left most pixel}
    cos1:=cost^[ang]; {trig values for angle}
    sin1:=sint^[ang];
    ang:=dangle(0,-dangle(player1.angle,(160)));  {angle for right most pixel}
    cos2:=cost^[ang]; {trig values for angle}
    sin2:=sint^[ang];
    ssofs:=320*loop+o1+xmin;  {screen offset at start of loop}
    ssinc:=xmin+320-xmax;     {screen offset increment to start each h-line}
    zinc:=xmax-xmin;          {size of h-viewport}
    emsmap(handle,0,0);       {ems routines for graphics}
    emsmap(handle,1,1);
    emsmap(handle,2,2);
    emsmap(handle,3,3);
    for i:=loop to toomax do  {loop from horizon to bottom of screen}
    begin
         dd:=(hh div (i-player1.look)); {temp distance variable used twice}
         distance:=(dd*v1) shr 16;      {fishbowl adjust}
         distance:=(distance*5) shr 2;  {This fixes a strange floor shift for me}
         distance:=distance-lookm;      {adjust for looking up or down}
         finx1:=((distance*cos1)) shr 16; {rotate to player angle}
         finy1:=(-(distance*sin1)) shr 16;

         distance:=(dd*v2) shr 16;         {same as above for right most pixel}
         distance:=(distance*5) shr 2;
         distance:=distance-lookm;
         finx2:=((distance*cos2)) shr 16;
         finy2:=(-(distance*sin2)) shr 16;

         finxd:=(finx2-finx1);  {x-distance}
         finyd:=(finy2-finy1);  {y-distance}
         finx1:=finx1+player1.x; {translate to player position}
         finy1:=finy1+player1.y;
         xstep:=(finxd shl 16) div 320;  {x-step along map for each pixel}
         ystep:=(finyd shl 16) div 320;  {x-step along map for each pixel}
         finx1:=finx1 shl 16;
         finy1:=finy1 shl 16;
         z:=ssofs+zinc;  {value for end of loop}
         finx1:=(finx1+xstep*xmin); { adjust for variable screen size}
         finy1:=(finy1+ystep*xmin);
         repeat
              if mem[s1:o1+ssofs]=0 then {if a wall or object has not been drawn}
              begin
              xp:=finx1 shr 16;  {fixed point shift}
              yp:=finy1 shr 16;
              asm
                 mov ax,xp       {map position}
                 shr ax,6
                 mov mapx,al
                 mov ax,yp
                 shr ax,6
                 mov mapy,al
                 mov ax,xp       {bitmap position}
                 and ax,3Fh
                 mov bmapx,al
                 mov ax,yp
                 and ax,3Fh
                 mov bmapy,al
              end;
              if (mapx>25) or (mapx<=0) or (mapy>25) or (mapy<=0) then
              colour:=8   {check if out of bounds, I have a small map}
              else
              begin
              colour:=floormap^[mapx,mapy]; {else find colour in map}
              flm:=flipmap^[mapx,mapy];     {check if I should flip the bitmap}
              if flm=0 then
              begin
              end
              else if flm=1 then bmapx:=63-bmapx
              else if flm=2 then bmapy:=63-bmapy
              else if flm=3 then
              begin
                   bmapx:=63-bmapx;
                   bmapy:=63-bmapy;
              end;
              end;
              if bmapy>62 then bmapy:=62;
              o4:=bmapx+((bmapy) shl 6)+ctable[colour];  {find the offset of the}
              asm                                        {pixel in the bitmap}
                 mov es,[segment]
                 mov bx,[o4]
                 mov dl,byte ptr [es:bx]                {put it on the screen}
                 mov es,[s1]
                 mov bx,[ssofs]
                 mov byte ptr [es:bx],dl
              end;
              end;
              ssofs:=ssofs+1;                     {increment screen offset}
              finx1:=finx1+xstep;                 {step along map}
              finy1:=finy1+ystep;
         until ssofs=z;                             {until end of h-line}
         ssofs:=ssofs+ssinc;                        {move down one h-line}
         end;
    end;

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