Break up the hog/object collision. Currently is $7F, allowing 128 overlapping objects accurately. Breaking it up into 15 for hogs, 7 for other objects. I'm thinking the overall accuracy should be just fine as far as people noticing even with a ton of overlapping hogs, and this way we can tell the difference between a hog and "something else". For experiment and rope-breaking purposes, make rope pass through hogs.
authornemo
Thu, 03 Mar 2016 16:36:05 -0500
changeset 11594 c453620cc6d6
parent 11593 7c8fd2f66e9b
child 11595 8d1cfedfaf1f
Break up the hog/object collision. Currently is $7F, allowing 128 overlapping objects accurately. Breaking it up into 15 for hogs, 7 for other objects. I'm thinking the overall accuracy should be just fine as far as people noticing even with a ton of overlapping hogs, and this way we can tell the difference between a hog and "something else". For experiment and rope-breaking purposes, make rope pass through hogs.
hedgewars/uCollisions.pas
hedgewars/uConsts.pas
hedgewars/uGearsHandlersRope.pas
hedgewars/uGearsList.pas
hedgewars/uLandGraphics.pas
--- a/hedgewars/uCollisions.pas	Thu Mar 03 15:41:53 2016 -0500
+++ b/hedgewars/uCollisions.pas	Thu Mar 03 16:36:05 2016 -0500
@@ -85,7 +85,7 @@
     X:= hwRound(Gear^.X);
     Y:= hwRound(Gear^.Y);
     Radius:= Gear^.Radius;
-    ChangeRoundInLand(X, Y, Radius - 1, true, (Gear = CurrentHedgehog^.Gear) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen = 0)));
+    ChangeRoundInLand(X, Y, Radius - 1, true,  ((CurrentHedgehog <> nil) and (Gear = CurrentHedgehog^.Gear)) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen = 0)), Gear^.Kind = gtHedgehog);
     cGear:= Gear
     end;
 Gear^.CollisionIndex:= Count;
@@ -97,7 +97,7 @@
 if Gear^.CollisionIndex >= 0 then
     begin
     with cinfos[Gear^.CollisionIndex] do
-        ChangeRoundInLand(X, Y, Radius - 1, false, ((CurrentHedgehog <> nil) and (Gear = CurrentHedgehog^.Gear)) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen = 0)));
+        ChangeRoundInLand(X, Y, Radius - 1, false, ((CurrentHedgehog <> nil) and (Gear = CurrentHedgehog^.Gear)) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen = 0)), Gear^.Kind = gtHedgehog);
     cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)];
     cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex;
     Gear^.CollisionIndex:= -1;
--- a/hedgewars/uConsts.pas	Thu Mar 03 15:41:53 2016 -0500
+++ b/hedgewars/uConsts.pas	Thu Mar 03 16:36:05 2016 -0500
@@ -115,13 +115,24 @@
 
     lfCurrentHog     = $0080;  // CurrentHog.  It is also used to flag crates, for convenience of AI.  Since an active hog would instantly collect the crate, this does not impact play
     lfNotCurrentMask = $FF7F;  // inverse of above. frequently used
-    lfObjMask        = $007F;  // lower 7 bits used for hogs
+    lfObjMask        = $007F;  // lower 7 bits used for hogs and explosives and mines 
     lfNotObjMask     = $FF80;  // inverse of above.
+
+// breaking up hogs would makes it easier to differentiate 
+// colliding with a hog from colliding with other things
+// if overlapping hogs are less common than objects, the division can be altered.
+// 3 bits for objects, 4 for hogs, that is, overlap 7 barrels/mines before possible dents, and 15 hogs.
+    lfHHMask         = $000F;  // lower 4 bits used only for hogs
+    lfNotHHObjMask   = $0070;  // next 3 bits used for non-hog things
+    lfNotHHObjShift  = 4;
+    lfNotHHObjSize   = lfNotHHObjMask shr lfNotHHObjShift;  
+
     // lower byte is for objects.
     // consists of 0-127 counted for object checkins and $80 as a bit flag for current hog.
     lfAllObjMask     = $00FF;  // lfCurrentHog or lfObjMask
 
 
+
     cMaxPower     = 1500;
     cMaxAngle     = 2048;
     cPowerDivisor = 1500;
--- a/hedgewars/uGearsHandlersRope.pas	Thu Mar 03 15:41:53 2016 -0500
+++ b/hedgewars/uGearsHandlersRope.pas	Thu Mar 03 16:36:05 2016 -0500
@@ -498,7 +498,7 @@
         end;
 
     if Gear^.Elasticity < _20 then Gear^.CollisionMask:= lfLandMask
-    else Gear^.CollisionMask:= lfNotCurrentMask;
+    else Gear^.CollisionMask:= lfNotObjMask or lfNotHHObjMask;
     CheckCollision(Gear);
 
     if (Gear^.State and gstCollision) <> 0 then
--- a/hedgewars/uGearsList.pas	Thu Mar 03 15:41:53 2016 -0500
+++ b/hedgewars/uGearsList.pas	Thu Mar 03 16:36:05 2016 -0500
@@ -407,6 +407,7 @@
                 RopePoints.Count:= 0;
                 gear^.Tint:= $D8D8D8FF;
                 gear^.Tag:= 0; // normal rope render
+                gear^.CollisionMask:= lfNotObjMask or lfNotHHObjMask;
                 end;
         gtMine: begin
                 gear^.ImpactSound:= sndMineImpact;
--- a/hedgewars/uLandGraphics.pas	Thu Mar 03 15:41:53 2016 -0500
+++ b/hedgewars/uLandGraphics.pas	Thu Mar 03 16:36:05 2016 -0500
@@ -23,7 +23,7 @@
 uses uFloat, uConsts, uTypes, Math, uRenderUtils;
 
 type
-    fillType = (nullPixel, backgroundPixel, ebcPixel, icePixel, setNotCurrentMask, changePixelSetNotCurrent, setCurrentHog, changePixelNotSetNotCurrent);
+    fillType = (nullPixel, backgroundPixel, ebcPixel, icePixel, addNotHHObj, removeNotHHObj, addHH, removeHH, setCurrentHog, removeCurrentHog);
 
 type TRangeArray = array[0..31] of record
                                    Left, Right: LongInt;
@@ -41,7 +41,7 @@
 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
 function FillRoundInLand(X, Y, Radius: LongInt; Value: Longword): Longword;
 function FillRoundInLandFT(X, Y, Radius: LongInt; fill: fillType): Longword;
-procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean);
+procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent, isHH: boolean);
 function  LandBackPixel(x, y: LongInt): LongWord;
 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword);
 function  DrawThickLine(X1, Y1, X2, Y2, radius: LongInt; color: Longword): Longword;
@@ -209,15 +209,28 @@
             calculatePixelsCoordinates(i, y, px, py);
             DrawPixelIce(i, y, px, py);
             end;
-    setNotCurrentMask:
+    addNotHHObj:
+        for i:= fromPix to toPix do
+            begin
+            if Land[y, i] and lfNotHHObjMask shr lfNotHHObjShift < lfNotHHObjSize then
+                Land[y, i]:= (Land[y, i] and not lfNotHHObjMask) or ((Land[y, i] and lfNotHHObjMask shr lfNotHHObjShift + 1) shl lfNotHHObjShift);
+            end;
+    removeNotHHObj:
         for i:= fromPix to toPix do
             begin
-            Land[y, i]:= Land[y, i] and lfNotCurrentMask;
+            if Land[y, i] and lfNotHHObjMask <> 0 then
+                Land[y, i]:= (Land[y, i] and not lfNotHHObjMask) or ((Land[y, i] and lfNotHHObjMask shr lfNotHHObjShift - 1) shl lfNotHHObjShift);
             end;
-    changePixelSetNotCurrent:
+    addHH:
         for i:= fromPix to toPix do
             begin
-            if Land[y, i] and lfObjMask > 0 then
+            if Land[y, i] and lfHHMask < lfHHMask then
+                Land[y, i]:= Land[y, i] + 1
+            end;
+    removeHH:
+        for i:= fromPix to toPix do
+            begin
+            if Land[y, i] and lfHHMask > 0 then
                 Land[y, i]:= Land[y, i] - 1;
             end;
     setCurrentHog:
@@ -225,11 +238,10 @@
             begin
             Land[y, i]:= Land[y, i] or lfCurrentHog
             end;
-    changePixelNotSetNotCurrent:
+    removeCurrentHog:
         for i:= fromPix to toPix do
             begin
-            if Land[y, i] and lfObjMask < lfObjMask then
-                Land[y, i]:= Land[y, i] + 1
+            Land[y, i]:= Land[y, i] and lfNotCurrentMask;
             end;
     end;
 end;
@@ -360,16 +372,20 @@
     inc(FillRoundInLand, FillCircleLines(x, y, dx, dy, Value));
 end;
 
-procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean);
+procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent, isHH: boolean);
 begin
 if not doSet and isCurrent then
-    FillRoundInLandFT(X, Y, Radius, setNotCurrentMask)
-else if not doSet and (not IsCurrent) then
-    FillRoundInLandFT(X, Y, Radius, changePixelSetNotCurrent)
+    FillRoundInLandFT(X, Y, Radius, removeCurrentHog)
+else if (not doSet) and (not IsCurrent) and isHH then
+    FillRoundInLandFT(X, Y, Radius, removeHH)
+else if (not doSet) and (not IsCurrent) and (not isHH) then
+    FillRoundInLandFT(X, Y, Radius, removeNotHHObj)
 else if doSet and IsCurrent then
     FillRoundInLandFT(X, Y, Radius, setCurrentHog)
-else if doSet and (not IsCurrent) then
-    FillRoundInLandFT(X, Y, Radius, changePixelNotSetNotCurrent);
+else if doSet and (not IsCurrent) and isHH then
+    FillRoundInLandFT(X, Y, Radius, addHH)
+else if doSet and (not IsCurrent) and (not isHH) then
+    FillRoundInLandFT(X, Y, Radius, addNotHHObj);
 end;
 
 procedure DrawIceBreak(x, y, iceRadius, iceHeight: Longint);