Revert prior attempted optimisation. Gridding the land pays in some situations, but not all. Restricting to an upper bound might help, but overall, seems too fuzzy to be worth it. On one side is increased cost of Add/Delete + extra test on collision check, on the other is skipping the list iteration. Perhaps for large lists.
authornemo
Thu, 01 Jul 2010 23:41:10 -0400
changeset 3608 c509bbc779e7
parent 3607 2ad7885615c1
child 3609 bc63ed514b70
child 3610 8590424bdfb0
Revert prior attempted optimisation. Gridding the land pays in some situations, but not all. Restricting to an upper bound might help, but overall, seems too fuzzy to be worth it. On one side is increased cost of Add/Delete + extra test on collision check, on the other is skipping the list iteration. Perhaps for large lists.
hedgewars/uCollisions.pas
hedgewars/uLand.pas
hedgewars/uLandGraphics.pas
--- a/hedgewars/uCollisions.pas	Thu Jul 01 19:05:29 2010 -0400
+++ b/hedgewars/uCollisions.pas	Thu Jul 01 23:41:10 2010 -0400
@@ -65,8 +65,6 @@
     ga: TGearArray;
 
 procedure AddGearCI(Gear: PGear);
-var i, j, k, tr: LongInt;
-    tmpVals: array[0..8] of byte;
 begin
 if Gear^.CollisionIndex >= 0 then exit;
 TryDo(Count <= MAXRECTSINDEX, 'Collision rects array overflow', true);
@@ -75,53 +73,19 @@
     X:= hwRound(Gear^.X);
     Y:= hwRound(Gear^.Y);
     Radius:= Gear^.Radius;
-    tr:= Radius - 1;
-    ChangeRoundInLand(X, Y, tr, true);
-    cGear:= Gear;
-    k:= 0;
-    for i:= -1 to 1 do
-        for j:= -1 to 1 do
-            begin
-            tmpVals[k]:= LandCollided[(Y + tr*i) div 32, (X + tr*i) div 32];
-            inc(k);
-            end;
-    k:= 0;
-    for i:= -1 to 1 do
-        for j:= -1 to 1 do
-            begin
-            if LandCollided[(Y + tr*i) div 32, (X + tr*i) div 32] < 255 then LandCollided[(Y + tr*i) div 32, (X + tr*i) div 32]:= tmpVals[k] + 1;
-            inc(k)
-            end
+    ChangeRoundInLand(X, Y, Radius - 1, true);
+    cGear:= Gear
     end;
 Gear^.CollisionIndex:= Count;
 inc(Count)
 end;
 
 procedure DeleteCI(Gear: PGear);
-var i, j, k, tr: LongInt;
-    tmpVals: array[0..8] of byte;
 begin
 if Gear^.CollisionIndex >= 0 then
     begin
     with cinfos[Gear^.CollisionIndex] do
-        begin
-        tr:= Radius - 1;
-        ChangeRoundInLand(X, Y, tr, false);
-        k:= 0;
-        for i:= -1 to 1 do
-            for j:= -1 to 1 do
-                begin
-                tmpVals[k]:= LandCollided[(Y + tr*i) div 32, (X + tr*i) div 32];
-                inc(k);
-                end;
-        k:= 0;
-        for i:= -1 to 1 do
-            for j:= -1 to 1 do
-                begin
-                if LandCollided[(Y + tr*i) div 32, (X + tr*i) div 32] > 0 then LandCollided[(Y + tr*i) div 32, (X + tr*i) div 32]:= tmpVals[k] - 1;
-                inc(k)
-                end
-        end;
+        ChangeRoundInLand(X, Y, Radius - 1, false);
     cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)];
     cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex;
     Gear^.CollisionIndex:= -1;
@@ -130,7 +94,7 @@
 end;
 
 function CheckGearsCollision(Gear: PGear): PGearArray;
-var mx, my, xP, xN, x0, yP, yN, y0, tr: LongInt;
+var mx, my: LongInt;
     i: Longword;
 begin
 CheckGearsCollision:= @ga;
@@ -138,31 +102,15 @@
 if Count = 0 then exit;
 mx:= hwRound(Gear^.X);
 my:= hwRound(Gear^.Y);
-tr:= Gear^.Radius - 1;
-xP:= (mx + tr) div 32;
-xN:= (mx - tr) div 32;
-yP:= (my + tr) div 32;
-yN:= (my - tr) div 32;
-x0:= mx div 32;
-y0:= my div 32;
 
-if (LandCollided[yN, xN] <> 0) or
-   (LandCollided[yN, x0] <> 0) or
-   (LandCollided[yN, xP] <> 0) or
-   (LandCollided[y0, xN] <> 0) or
-   (LandCollided[y0, x0] <> 0) or
-   (LandCollided[y0, xP] <> 0) or
-   (LandCollided[yP, xN] <> 0) or
-   (LandCollided[yP, x0] <> 0) or
-   (LandCollided[yP, xP] <> 0) then 
-    for i:= 0 to Pred(Count) do
-        with cinfos[i] do
-            if (Gear <> cGear) and
-                (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) then
-                    begin
-                    ga.ar[ga.Count]:= cinfos[i].cGear;
-                    inc(ga.Count)
-                    end
+for i:= 0 to Pred(Count) do
+    with cinfos[i] do
+        if (Gear <> cGear) and
+            (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) then
+                begin
+                ga.ar[ga.Count]:= cinfos[i].cGear;
+                inc(ga.Count)
+                end
 end;
 
 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): boolean;
@@ -228,7 +176,7 @@
 end;
 
 function TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean;
-var x, y, mx, my, i, xP, xN, x0, yP, yN, y0, tr: LongInt;
+var x, y, mx, my, i: LongInt;
     flag: boolean;
 begin
 flag:= false;
@@ -256,47 +204,31 @@
 
    mx:= hwRound(Gear^.X);
    my:= hwRound(Gear^.Y);
-   tr:= Gear^.Radius - 1;
-   xP:= (mx + tr) div 32;
-   xN:= (mx - tr) div 32;
-   yP:= (my + tr) div 32;
-   yN:= (my - tr) div 32;
-   x0:= mx div 32;
-   y0:= my div 32;
 
-   if (LandCollided[yN, xN] <> 0) or
-      (LandCollided[yN, x0] <> 0) or
-      (LandCollided[yN, xP] <> 0) or
-      (LandCollided[y0, xN] <> 0) or
-      (LandCollided[y0, x0] <> 0) or
-      (LandCollided[y0, xP] <> 0) or
-      (LandCollided[yP, xN] <> 0) or
-      (LandCollided[yP, x0] <> 0) or
-      (LandCollided[yP, xP] <> 0) then 
-      for i:= 0 to Pred(Count) do
-       with cinfos[i] do
-         if (Gear <> cGear) and
-            (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) and
-            ((mx > x) xor (Dir > 0)) then
-            if ((cGear^.Kind in [gtHedgehog, gtMine]) and ((Gear^.State and gstNotKickable) = 0)) or
-               // only apply X kick if the barrel is knocked over
-               ((cGear^.Kind = gtExplosives) and ((cGear^.State and gsttmpflag) <> 0)) then
-                begin
-                with cGear^ do
-                     begin
-                     dX:= Gear^.dX;
-                     dY:= Gear^.dY * _0_5;
-                     State:= State or gstMoving;
-                     Active:= true
-                     end;
-                DeleteCI(cGear);
-                exit(false)
-                end
-      end
+   for i:= 0 to Pred(Count) do
+    with cinfos[i] do
+      if (Gear <> cGear) and
+         (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) and
+         ((mx > x) xor (Dir > 0)) then
+         if ((cGear^.Kind in [gtHedgehog, gtMine]) and ((Gear^.State and gstNotKickable) = 0)) or
+            // only apply X kick if the barrel is knocked over
+            ((cGear^.Kind = gtExplosives) and ((cGear^.State and gsttmpflag) <> 0)) then
+             begin
+             with cGear^ do
+                  begin
+                  dX:= Gear^.dX;
+                  dY:= Gear^.dY * _0_5;
+                  State:= State or gstMoving;
+                  Active:= true
+                  end;
+             DeleteCI(cGear);
+             exit(false)
+             end
+   end
 end;
 
 function TestCollisionYKick(Gear: PGear; Dir: LongInt): boolean;
-var x, y, mx, my, i, xP, xN, x0, yP, yN, y0, tr: LongInt;
+var x, y, mx, my, i: LongInt;
     flag: boolean;
 begin
 flag:= false;
@@ -326,41 +258,25 @@
 
    mx:= hwRound(Gear^.X);
    my:= hwRound(Gear^.Y);
-   tr:= Gear^.Radius - 1;
-   xP:= (mx + tr) div 32;
-   xN:= (mx - tr) div 32;
-   yP:= (my + tr) div 32;
-   yN:= (my - tr) div 32;
-   x0:= mx div 32;
-   y0:= my div 32;
 
-   if (LandCollided[yN, xN] <> 0) or
-      (LandCollided[yN, x0] <> 0) or
-      (LandCollided[yN, xP] <> 0) or
-      (LandCollided[y0, xN] <> 0) or
-      (LandCollided[y0, x0] <> 0) or
-      (LandCollided[y0, xP] <> 0) or
-      (LandCollided[yP, xN] <> 0) or
-      (LandCollided[yP, x0] <> 0) or
-      (LandCollided[yP, xP] <> 0) then 
-      for i:= 0 to Pred(Count) do
-       with cinfos[i] do
-         if (Gear <> cGear) and
-            (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) and
-            ((my > y) xor (Dir > 0)) then
-            if (cGear^.Kind in [gtHedgehog, gtMine, gtExplosives]) and ((Gear^.State and gstNotKickable) = 0) then
-                begin
-                with cGear^ do
-                     begin
-                     if (Kind <> gtExplosives) or ((State and gsttmpflag) <> 0) then dX:= Gear^.dX * _0_5;
-                     dY:= Gear^.dY;
-                     State:= State or gstMoving;
-                     Active:= true
-                     end;
-                DeleteCI(cGear);
-                exit(false)
-                end
-      end
+   for i:= 0 to Pred(Count) do
+    with cinfos[i] do
+      if (Gear <> cGear) and
+         (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) and
+         ((my > y) xor (Dir > 0)) then
+         if (cGear^.Kind in [gtHedgehog, gtMine, gtExplosives]) and ((Gear^.State and gstNotKickable) = 0) then
+             begin
+             with cGear^ do
+                  begin
+                  if (Kind <> gtExplosives) or ((State and gsttmpflag) <> 0) then dX:= Gear^.dX * _0_5;
+                  dY:= Gear^.dY;
+                  State:= State or gstMoving;
+                  Active:= true
+                  end;
+             DeleteCI(cGear);
+             exit(false)
+             end
+   end
 end;
 
 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): boolean;
--- a/hedgewars/uLand.pas	Thu Jul 01 19:05:29 2010 -0400
+++ b/hedgewars/uLand.pas	Thu Jul 01 23:41:10 2010 -0400
@@ -35,8 +35,7 @@
 
 var Land: TCollisionArray;
     LandPixels: TLandArray;
-// LandCollided is reusing DirtyTag size because currently the largest Radius we have is 32px (Piano)
-    LandDirty, LandCollided: TDirtyTag;
+    LandDirty: TDirtyTag;
     hasBorder: boolean; 
     hasGirders: boolean;  
     isMap: boolean;  
@@ -1346,7 +1345,6 @@
     LandBackSurface:= nil;
     digest:= '';
     FillChar(LandPixels, sizeof(TLandArray), 0);
-    FillChar(LandCollided, sizeof(TDirtyTag), 0);
 end;
 
 procedure freeModule;
--- a/hedgewars/uLandGraphics.pas	Thu Jul 01 19:05:29 2010 -0400
+++ b/hedgewars/uLandGraphics.pas	Thu Jul 01 23:41:10 2010 -0400
@@ -83,19 +83,19 @@
    begin
    if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
       for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-          if (Land[y + dy, i] < 255) then
+          if (Land[y + dy, i] < 256) then
               inc(Land[y + dy, i]);
    if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
       for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-          if (Land[y - dy, i] < 255) then
+          if (Land[y - dy, i] < 256) then
               inc(Land[y - dy, i]);
    if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
       for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-          if (Land[y + dx, i] < 255) then
+          if (Land[y + dx, i] < 256) then
               inc(Land[y + dx, i]);
    if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
       for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-          if (Land[y - dx, i] < 255) then
+          if (Land[y - dx, i] < 256) then
               inc(Land[y - dx, i]);
    end
 end;