DEADSOFTWARE

better hitscan tracer; no more level trace bitmap (but no more particles too, alas)
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Mon, 21 Aug 2017 20:11:19 +0000 (23:11 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Mon, 21 Aug 2017 21:02:16 +0000 (00:02 +0300)
src/game/g_basic.pas
src/game/g_gfx.pas
src/game/g_map.pas
src/game/g_weapons.pas
src/game/z_aabbtree.pas

index 98cebcce846067023ff07b3fa558f1c9ddba0797..8e1ae926769f02fa83676e5a685bd9274417d124 100644 (file)
@@ -48,7 +48,7 @@ function g_CollideAround(X1, Y1: Integer; Width1, Height1: Word;
                          X2, Y2: Integer; Width2, Height2: Word): Boolean;
 function g_CollidePlayer(X, Y: Integer; Width, Height: Word): Boolean;
 function g_PatchLength(X1, Y1, X2, Y2: Integer): Word;
-function g_TraceVector(X1, Y1, X2, Y2: Integer): Boolean;
+function g_TraceVector(X1, Y1, X2, Y2: Integer): Boolean; // `true`: no wall hit
 function g_GetAcidHit(X, Y: Integer; Width, Height: Word): Byte;
 function g_Look(a, b: PObj; d: TDirection): Boolean;
 procedure IncMax(var A: Integer; B, Max: Integer); overload;
@@ -142,15 +142,21 @@ begin
       end;
 end;
 
+
 function g_TraceVector(X1, Y1, X2, Y2: Integer): Boolean;
 var
+  wallHitX: Integer = 0;
+  wallHitY: Integer = 0;
+(*
   i: Integer;
   dx, dy: Integer;
   Xerr, Yerr, d: LongWord;
   incX, incY: Integer;
   x, y: Integer;
+*)
 begin
-  Result := False;
+  (*
+  result := False;
 
   Assert(gCollideMap <> nil, 'g_TraceVector: gCollideMap = nil');
 
@@ -193,8 +199,21 @@ begin
   end;
 
   Result := True;
+  *)
+
+  if (g_Map_traceToNearestWall(x1, y1, x2, y2, @wallHitX, @wallHitY) >= 0) then
+  begin
+    // check distance
+    //result := ((wallHitX-x1)*(wallHitX-x1)+(wallHitY-y1)*(wallHitY-y1) > (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
+    result := false;
+  end
+  else
+  begin
+    result := true; // no obstacles
+  end;
 end;
 
+
 function g_CreateUID(UIDType: Byte): Word;
 var
   ok: Boolean;
index 17bbe920be07ac8843548777c9ed53878c498c80..37036278d08175ca4dbf3a93c88e724ac32995f7 100644 (file)
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *)
 {$INCLUDE ../shared/a_modes.inc}
+{.$DEFINE HAS_COLLIDE_BITMAP}
 unit g_gfx;
 
 interface
@@ -58,8 +59,12 @@ procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean);
 procedure g_GFX_Update();
 procedure g_GFX_Draw();
 
+
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   gCollideMap: Array of Array of Byte;
+{$ENDIF}
+
 
 implementation
 
@@ -103,9 +108,12 @@ var
   CurrentParticle: Integer;
 
 procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean);
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   yy, y2, xx, x2: Integer;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   if x < 0 then
   begin
     Width := Width + x;
@@ -150,12 +158,16 @@ begin
         for xx := x to x2 do
           gCollideMap[yy][xx] := gCollideMap[yy][xx] and t;
     end;
+{$ENDIF}
 end;
 
 procedure CreateCollideMap();
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   a: Integer;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 1/6', 0, False);
   SetLength(gCollideMap, gMapInfo.Height+1);
   for a := 0 to High(gCollideMap) do
@@ -225,6 +237,7 @@ begin
           g_Mark(X, Y, Width, Height, MARK_WALL, True);
     end;
   end;
+{$ENDIF}
 end;
 
 procedure g_GFX_Init();
@@ -248,9 +261,13 @@ begin
     OnceAnims := nil;
   end;
 
+  {$IF DEFINED(HAS_COLLIDE_BITMAP)}
   gCollideMap := nil;
+  {$ENDIF}
 end;
 
+
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 procedure CorrectOffsets(id: Integer);
 begin
   with Particles[id] do
@@ -270,14 +287,19 @@ begin
       offsetX := 0;
   end;
 end;
+{$ENDIF}
+
 
 procedure g_GFX_SparkVel(fX, fY: Integer; Count: Word; VX, VY: Integer; DevX, DevY: Byte);
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   a: Integer;
   DevX1, DevX2,
   DevY1, DevY2: Byte;
   l: Integer;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   l := Length(Particles);
   if l = 0 then
     Exit;
@@ -326,10 +348,12 @@ begin
     else
       CurrentParticle := CurrentParticle+1;
   end;
+{$ENDIF}
 end;
 
 procedure g_GFX_Blood(fX, fY: Integer; Count: Word; vx, vy: Integer;
   DevX, DevY: Word; CR, CG, CB: Byte; Kind: Byte = BLOOD_NORMAL);
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   a: Integer;
   DevX1, DevX2,
@@ -337,7 +361,9 @@ var
   l: Integer;
   CRnd: Byte;
   CC: SmallInt;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   if Kind = BLOOD_SPARKS then
   begin
     g_GFX_SparkVel(fX, fY, 2 + Random(2), -VX div 2, -VY div 2, DevX, DevY);
@@ -419,9 +445,11 @@ begin
     else
       CurrentParticle := CurrentParticle+1;
   end;
+{$ENDIF}
 end;
 
 procedure g_GFX_Spark(fX, fY: Integer; Count: Word; Angle: SmallInt; DevX, DevY: Byte);
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   a: Integer;
   b: Single;
@@ -429,7 +457,9 @@ var
   DevY1, DevY2: Byte;
   BaseVelX, BaseVelY: Single;
   l: Integer;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   l := Length(Particles);
   if l = 0 then
     Exit;
@@ -480,15 +510,19 @@ begin
     else
       CurrentParticle := CurrentParticle+1;
   end;
+{$ENDIF}
 end;
 
 procedure g_GFX_Water(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DevX, DevY, Color: Byte);
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   a: Integer;
   DevX1, DevX2,
   DevY1, DevY2: Byte;
   l: Integer;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   l := Length(Particles);
   if l = 0 then
     Exit;
@@ -562,13 +596,17 @@ begin
     else
       CurrentParticle := CurrentParticle+1;
   end;
+{$ENDIF}
 end;
 
 procedure g_GFX_SimpleWater(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DefColor, CR, CG, CB: Byte);
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   a: Integer;
   l: Integer;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   l := Length(Particles);
   if l = 0 then
     Exit;
@@ -647,15 +685,19 @@ begin
     else
       CurrentParticle := CurrentParticle+1;
   end;
+{$ENDIF}
 end;
 
 procedure g_GFX_Bubbles(fX, fY: Integer; Count: Word; DevX, DevY: Byte);
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
 var
   a: Integer;
   DevX1, DevX2,
   DevY1, DevY2: Byte;
   l: Integer;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   l := Length(Particles);
   if l = 0 then
     Exit;
@@ -704,6 +746,7 @@ begin
     else
       CurrentParticle := CurrentParticle+1;
   end;
+{$ENDIF}
 end;
 
 procedure g_GFX_SetMax(Count: Integer);
@@ -766,12 +809,15 @@ end;
 procedure g_GFX_Update();
 var
   a: Integer;
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   w, h: Integer;
   dX, dY: SmallInt;
   b, len: Integer;
   s: ShortInt;
   c: Byte;
+{$ENDIF}
 begin
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
   if Particles <> nil then
   begin
     w := gMapInfo.Width;
@@ -1235,6 +1281,7 @@ begin
           CorrectOffsets(a);
         end;
   end; // Particles <> nil
+{$ENDIF}
 
   if OnceAnims <> nil then
   begin
index 36ac9072a2fc315286abddb31042cba92eb9e053..a73434b9b8c6632bd41dbe63a194dd5376885def 100644 (file)
@@ -286,6 +286,8 @@ end;
 
 // wall index in `gWalls` or -1
 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Integer;
+var
+  maxDistSq: Single;
 
   function sqchecker (pan: TPanel; var ray: Ray2D): Single;
   var
@@ -298,6 +300,7 @@ function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil;
     if not aabb.valid then exit;
     if aabb.intersects(ray, @tmin) then
     begin
+      //if (tmin*tmin > maxDistSq) then exit;
       if (tmin >= 0.0) then
       begin
         //e_WriteLog(Format('sqchecker(%d,%d,%d,%d): panel #%d (%d,%d)-(%d,%d); tmin=%f', [x0, y0, x1, y1, pan.arrIdx, pan.X, pan.Y, pan.Width, pan.Height, tmin]), MSG_NOTIFY);
@@ -315,9 +318,10 @@ var
 begin
   result := -1;
   if (mapTree = nil) then exit;
+  maxDistSq := (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);
   if mapTree.segmentQuery(qr, x0, y0, x1, y1, sqchecker, (GridTagWall or GridTagDoor)) then
   begin
-    if (qr.flesh <> nil) then
+    if (qr.flesh <> nil) and (qr.time*qr.time <= maxDistSq) then
     begin
       result := qr.flesh.arrIdx;
       if (hitx <> nil) or (hity <> nil) then
index c55931b540dd1e4055a949fb29799e0e83fd2c09..d52abc5fb519b33ed746296c632eae8a64cc6a3f 100644 (file)
@@ -1250,6 +1250,7 @@ begin
 end;
 
 
+(*
 procedure g_Weapon_gunOld(const x, y, xd, yd, v, dmg: Integer; SpawnerUID: Word; CheckTrigger: Boolean);
 var
   a: Integer;
@@ -1362,6 +1363,7 @@ begin
   if CheckTrigger and g_Game_IsServer then
     g_Triggers_PressL(X, Y, xx-xi, yy-yi, SpawnerUID, ACTIVATE_SHOT);
 end;
+*)
 
 
 (*
@@ -1769,11 +1771,13 @@ var
   stt: UInt64;
   {$ENDIF}
 begin
+  (*
   if not gwep_debug_fast_trace then
   begin
     g_Weapon_gunOld(x, y, xd, yd, v, dmg, SpawnerUID, CheckTrigger);
     exit;
   end;
+  *)
 
   wgunMonHash.reset(); //FIXME: clear hash on level change
   wgunHitHeap.clear();
index 86e05680340dfa2af06d8c4fee175a4f48e80083..72206539078e070e414dfdf5e1b7794b1624d475 100644 (file)
@@ -235,7 +235,6 @@ type
     chkAABB: AABB2D; // for checkers
     qSRes: PSegmentQueryResult; // for queries
     // for segment query
-    maxFraction: Single;
     curax, curay: Single;
     curbx, curby: Single;
     dirx, diry: Single;
@@ -1680,8 +1679,7 @@ end;
 
 
 function TDynAABBTreeBase.checkerRay (node: PTreeNode): Boolean;
-var
-  tmin: Single = 0;
+//var tmin: Single = 0;
 begin
   {$IF FALSE}
   result := node.aabb.intersects(curax, curay, curbx, curby, @tmin);
@@ -1696,7 +1694,10 @@ begin
     Integer(result),
   ]), MSG_NOTIFY);
   {$ELSE}
-  result := node.aabb.intersects(traceRay, maxFraction, @tmin);
+  result := false;
+  if (node.aabb.maxX < minSingle(curax, curbx)) or (node.aabb.maxY < minSingle(curay, curby)) then exit;
+  if (node.aabb.minX > maxSingle(curax, curbx)) or (node.aabb.minY > maxSingle(curay, curby)) then exit;
+  result := node.aabb.intersects(traceRay, qSRes.time{, @tmin});
   {
   e_WriteLog(Format('intersect: (%f,%f)-(%f,%f)  (%d,%d)-(%d,%d) tmin=%f  res=%d  frac=%f', [
     curax, curay, curbx, curby,
@@ -1704,7 +1705,7 @@ begin
     node.aabb.maxX, node.aabb.maxY,
     tmin,
     Integer(result),
-    maxFraction
+    qSRes.time
   ]), MSG_NOTIFY);
   }
   {$ENDIF}
@@ -1733,9 +1734,8 @@ begin
   if (hitFraction > 0.0) then
   begin
     // we update the maxFraction value and the ray AABB using the new maximum fraction
-    if (hitFraction < maxFraction) then
+    if (hitFraction < qSRes.time) then
     begin
-      maxFraction := hitFraction;
       qSRes.time := hitFraction;
       qSRes.flesh := flesh;
       // fix curb here
@@ -1751,7 +1751,6 @@ end;
 // segment querying method
 function TDynAABBTreeBase.segmentQuery (out qr: TSegmentQueryResult; ax, ay, bx, by: TreeNumber; cb: TSegQueryCallback; tagmask: Integer=-1): Boolean;
 var
-  oldmaxFraction: Single;
   oldcurax, oldcuray: Single;
   oldcurbx, oldcurby: Single;
   olddirx, olddiry: Single;
@@ -1764,7 +1763,6 @@ begin
 
   if (ax = bx) and (ay = by) then begin result := false; exit; end;
 
-  oldmaxFraction := maxFraction;
   oldcurax := curax;
   oldcuray := curay;
   oldcurbx := curbx;
@@ -1773,7 +1771,8 @@ begin
   olddiry := diry;
   oldray := traceRay;
 
-  maxFraction := 1.0e100; // infinity
+  qr.time := 1.0e100; // infinity
+  //qr.time := sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay))+1.0;
   curax := ax;
   curay := ay;
   curbx := bx;
@@ -1806,7 +1805,6 @@ begin
   curby := oldcurby;
   dirx := olddirx;
   diry := olddiry;
-  maxFraction := oldmaxFraction;
   traceRay := oldray;
 
   result := qr.valid;