hedgewars/GSHandlers.inc
changeset 3570 3836fa355f96
parent 3569 27b0ec683572
child 3571 5c99b239340e
--- a/hedgewars/GSHandlers.inc	Sat Jun 26 19:30:16 2010 +0200
+++ b/hedgewars/GSHandlers.inc	Sun Jun 27 02:11:31 2010 +0200
@@ -3205,7 +3205,7 @@
 procedure doStepPortal(Gear: PGear);
 var 
     iterator, conPortal: PGear;
-    s, acptRadius, cdxy: hwFloat;
+    s, acptRadius, itdist, nx, ny, pspeed, nspeed: hwFloat;
     noTrap, hasdxy: Boolean;
 begin
     doPortalColorSwitch();
@@ -3281,7 +3281,8 @@
         // won't port stuff that moves away from me!
 
         // wow! good candidate there, let's see if the distance really is small enough!
-        if (Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y) > acptRadius) then
+        itdist := Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y);
+        if (itdist > acptRadius) then
             continue;
 (*
         noTrap := ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0))
@@ -3300,36 +3301,50 @@
         // Until loops are reliably broken
         inc(iterator^.PortalCounter);
 
-        // TODO: more accurate porting
-        cdxy := Distance(conPortal^.dX, conPortal^.dY);
-        s := (Int2hwFloat(Gear^.Radius)) / cdxy;
-
-        if iterator^.Kind = gtCake then
+        // find out how much speed parallel to the portal vector
+        // the gear has
+        pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY );
+        // create a normal of the portal vector
+        nx := - Gear^.dY;
+        ny := Gear^.dX;
+        // pick the normal vector that's pointing skywards
+        if (not ny.isNegative) then
             begin
-            iterator^.X := conPortal^.X ;
-            iterator^.Y := conPortal^.Y ;
-            end
-        else
+            nx.isNegative := not nx.isNegative;
+            ny.isNegative := not ny.isNegative;
+            end;
+        // now let's find out how much speed the gear has in the
+        // direction of that normal
+        nspeed:= (nx * iterator^.dX + ny * iterator^.dY);
+
+        // now let's project those back to the connected portal's vectors
+        nx := - conPortal^.dY;
+        ny := conPortal^.dX;
+        if ny.isNegative then
             begin
-            iterator^.X := conPortal^.X + s * conPortal^.dX;
-            iterator^.Y := conPortal^.Y + s * conPortal^.dY;
-
-            s := Distance(iterator^.dX, iterator^.dY) / cdxy;
-
-            iterator^.dX := s * conPortal^.dX;
-            iterator^.dY := s * conPortal^.dY
+            nx.isNegative := not nx.isNegative;
+            ny.isNegative := not ny.isNegative;
             end;
+        iterator^.dX := -pspeed * conPortal^.dX + -nspeed * nx;
+        iterator^.dY := -pspeed * conPortal^.dY + -nspeed * ny;
+        if iterator^.Kind = gtCake then
+            itdist := int2hwFloat(iterator^.Radius) - _0_1;
+        s := itdist / Distance(iterator^.dX, iterator^.dY);            
+        iterator^.X := conPortal^.X + s * iterator^.dX;
+        iterator^.Y := conPortal^.Y + s * iterator^.dY;
+        end;
 
         FollowGear := iterator;
 
+{
         s := _0_2 + _0_008 * Gear^.Health;
         iterator^.dX := s * iterator^.dX;
         iterator^.dY := s * iterator^.dY;
+}
 
         if Gear^.Health > 1 then dec(Gear^.Health);
-            //dec(iterator^.Health);??
-
-        // breaks (some) loops
+
+{        // breaks (some) loops
         if Distance(iterator^.dX, iterator^.dY) > _0_96 then
         begin
             iterator^.dX := iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX);
@@ -3338,7 +3353,7 @@
             iterator^.dX := s * iterator^.dX;
             iterator^.dY := s * iterator^.dX;
         end;
-    end;
+}
 end;
 
 procedure doStepMovingPortal_real(Gear: PGear);