portal / slope detection:
authorsheepluva
Sat, 26 Jun 2010 19:30:16 +0200
changeset 3569 27b0ec683572
parent 3567 28e90e4541ce
child 3570 3836fa355f96
portal / slope detection: * make portal shot collision work regardless of portal projectile velocity * small hax so that hogs can open portals below their feet * killing some whitespaces for my personal entertainment
hedgewars/GSHandlers.inc
hedgewars/uCollisions.pas
hedgewars/uConsts.pas
--- a/hedgewars/GSHandlers.inc	Sat Jun 26 16:00:40 2010 +0200
+++ b/hedgewars/GSHandlers.inc	Sat Jun 26 19:30:16 2010 +0200
@@ -16,6 +16,54 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *)
 
+procedure doStepPerPixel(Gear: PGear; step: TGearStepProcedure; onlyCheckIfChanged: boolean);
+var
+    dX, dY, sX, sY: hwFloat;
+    i, steps: LongWord;
+    caller: TGearStepProcedure;
+begin
+    dX:= Gear^.dX;
+    dY:= Gear^.dY;
+    steps:= max(abs(hwRound(Gear^.X+dX)-hwRound(Gear^.X)), abs(hwRound(Gear^.Y+dY)-hwRound(Gear^.Y)));
+
+    // Gear is still on the same Pixel it was before
+    if steps < 1 then
+    begin
+        if onlyCheckIfChanged then
+        begin
+            Gear^.X := Gear^.X + dX;
+            Gear^.Y := Gear^.Y + dY;
+            EXIT;
+        end
+        else
+            steps := 1;
+    end;
+
+    if steps > 1 then
+    begin
+        sX:= dX / steps;
+        sY:= dY / steps;
+    end
+    else
+    begin
+        sX:= dX;
+        sY:= dY;
+    end;
+
+    caller:= Gear^.doStep;
+
+    for i:= 1 to steps do
+    begin
+        Gear^.X := Gear^.X + sX;
+        Gear^.Y := Gear^.Y + sY;
+        step(Gear);
+        if (Gear^.doStep <> caller)
+        or ((Gear^.State and gstCollision) <> 0)
+        or ((Gear^.State and gstMoving) = 0) then
+            break;
+    end;
+end;
+
 procedure makeHogsWorry(x, y: hwFloat; r: LongInt);
 var 
     gi: PGear;
@@ -3293,10 +3341,9 @@
     end;
 end;
 
-procedure doStepMovingPortal(Gear: PGear);
+procedure doStepMovingPortal_real(Gear: PGear);
 var 
     x, y, tx, ty: LongInt;
-    //, bx, by, tangle: LongInt;
     s: hwFloat;
 
 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean);
@@ -3322,17 +3369,6 @@
 end;
 
 begin
-    if (Gear^.Timer < 1)
-       or (PHedgehog(Gear^.Hedgehog) <> CurrentHedgehog) then
-    begin
-        deleteGear(Gear);
-        EXIT;
-    end;
-    
-    doPortalColorSwitch();
-
-    Gear^.X := Gear^.X + Gear^.dX;
-    Gear^.Y := Gear^.Y + Gear^.dY;
     x := hwRound(Gear^.X);
     y := hwRound(Gear^.Y);
     tx := 0;
@@ -3341,6 +3377,8 @@
 
     if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then
     begin
+        Gear^.State := Gear^.State or gstCollision;
+        Gear^.State := Gear^.State and not gstMoving;
         if not calcSlopeTangent(Gear, x, y, tx, ty, 255)
            or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain
         begin
@@ -3373,6 +3411,15 @@
              loadNewPortalBall(Gear, true);
 end;
 
+procedure doStepMovingPortal(Gear: PGear);
+begin
+    doPortalColorSwitch();
+    doStepPerPixel(Gear, @doStepMovingPortal_real, true);
+    if (Gear^.Timer < 1)
+       or (PHedgehog(Gear^.Hedgehog) <> CurrentHedgehog) then
+            deleteGear(Gear);
+end;
+
 procedure doStepPortalShot(newPortal: PGear);
 var 
     iterator: PGear;
@@ -3422,6 +3469,8 @@
                 iterator := iterator^.NextGear
             end;
         end;
+    newPortal^.State := newPortal^.State and not gstCollision;
+    newPortal^.State := newPortal^.State or gstMoving;
     newPortal^.doStep := @doStepMovingPortal;
 end;
 
--- a/hedgewars/uCollisions.pas	Sat Jun 26 16:00:40 2010 +0200
+++ b/hedgewars/uCollisions.pas	Sat Jun 26 19:30:16 2010 +0200
@@ -321,31 +321,39 @@
 var ldx, ldy, rdx, rdy: LongInt;
     i, j, mx, my, li, ri, jfr, jto, tmpo : ShortInt;
     tmpx, tmpy: LongWord;
-    dx, dy: hwFloat;
+    dx, dy, s: hwFloat;
     offset: Array[0..7,0..1] of ShortInt;
 
 begin
     dx:= Gear^.dX;
     dy:= Gear^.dY;
 
-    // we start searching from the direction the gear center is at
+    // we start searching from the direction the gear came from
+    if (dx.QWordValue > _0_995.QWordValue )
+    or (dy.QWordValue > _0_995.QWordValue ) then
+        begin // scale
+        s := _1 / Distance(dx,dy);
+        dx := s * dx;
+        dy := s * dy;
+        end;
+
     mx:= hwRound(Gear^.X-dx) - hwRound(Gear^.X);
     my:= hwRound(Gear^.Y-dy) - hwRound(Gear^.Y);
 
     li:= -1;
     ri:= -1;
-    
+
     // go around collision pixel, checking for first/last collisions
     // this will determinate what angles will be tried to crawl along
     for i:= 0 to 7 do
         begin
         offset[i,0]:= mx;
         offset[i,1]:= my;
-        
+
         tmpx:= collisionX + mx;
         tmpy:= collisionY + my;
 
-        if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK)  = 0) then
+        if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK) = 0) then
             if (Land[tmpy,tmpx] > TestWord) then
                 begin
                 // remember the index belonging to the first and last collision (if in 1st half)
--- a/hedgewars/uConsts.pas	Sat Jun 26 16:00:40 2010 +0200
+++ b/hedgewars/uConsts.pas	Sat Jun 26 19:30:16 2010 +0200
@@ -2015,7 +2015,7 @@
             SkipTurns: 0;
             PosCount: 1;
             PosSprite: sprWater;
-            ejectX: 0; //29;
+            ejectX: -5; //29;
             ejectY: -7),
 
 // Piano