hedgewars/uGearsHandlersRope.pas
changeset 8733 b6002f1956d5
parent 8680 5fe344cc8610
child 8744 6c87486fd89b
equal deleted inserted replaced
8732:57c10f640b60 8733:b6002f1956d5
   108     HHGear: PGear;
   108     HHGear: PGear;
   109     len, tx, ty, nx, ny, ropeDx, ropeDy, mdX, mdY: hwFloat;
   109     len, tx, ty, nx, ny, ropeDx, ropeDy, mdX, mdY: hwFloat;
   110     lx, ly, cd: LongInt;
   110     lx, ly, cd: LongInt;
   111     haveCollision,
   111     haveCollision,
   112     haveDivided: boolean;
   112     haveDivided: boolean;
   113 
   113     wrongSide: boolean;
   114 begin
   114 begin
   115     if GameTicks mod 4 <> 0 then exit;
   115     if GameTicks mod 4 <> 0 then exit;
   116 
   116 
   117     HHGear := Gear^.Hedgehog^.Gear;
   117     HHGear := Gear^.Hedgehog^.Gear;
   118 
   118 
   214                 X := Gear^.X;
   214                 X := Gear^.X;
   215                 Y := Gear^.Y;
   215                 Y := Gear^.Y;
   216                 if RopePoints.Count = 0 then
   216                 if RopePoints.Count = 0 then
   217                     RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX);
   217                     RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX);
   218                 b := (nx * HHGear^.dY) > (ny * HHGear^.dX);
   218                 b := (nx * HHGear^.dY) > (ny * HHGear^.dX);
       
   219                 sx:= Gear^.dX.isNegative;
       
   220                 sy:= Gear^.dY.isNegative;
       
   221                 sb:= Gear^.dX.QWordValue < Gear^.dY.QWordValue;
   219                 dLen := len
   222                 dLen := len
   220                 end;
   223                 end;
   221 
   224 
   222             with RopePoints.rounded[RopePoints.Count] do
   225             with RopePoints.rounded[RopePoints.Count] do
   223                 begin
   226                 begin
   246             begin
   249             begin
   247             tx := RopePoints.ar[Pred(RopePoints.Count)].X;
   250             tx := RopePoints.ar[Pred(RopePoints.Count)].X;
   248             ty := RopePoints.ar[Pred(RopePoints.Count)].Y;
   251             ty := RopePoints.ar[Pred(RopePoints.Count)].Y;
   249             mdX := tx - Gear^.X;
   252             mdX := tx - Gear^.X;
   250             mdY := ty - Gear^.Y;
   253             mdY := ty - Gear^.Y;
   251             if RopePoints.ar[Pred(RopePoints.Count)].b xor (mdX * (ty - HHGear^.Y) > (tx - HHGear^.X) * mdY) then
   254             ropeDx:= tx - HHGear^.X;
       
   255             ropeDy:= ty - HHGear^.Y;
       
   256             if RopePoints.ar[Pred(RopePoints.Count)].b xor (mdX * ropeDy > ropeDx * mdY) then
   252                 begin
   257                 begin
   253                 dec(RopePoints.Count);
   258                 dec(RopePoints.Count);
   254                 Gear^.X := RopePoints.ar[RopePoints.Count].X;
   259                 Gear^.X := tx;
   255                 Gear^.Y := RopePoints.ar[RopePoints.Count].Y;
   260                 Gear^.Y := ty;
   256                 Gear^.Elasticity := Gear^.Elasticity + RopePoints.ar[RopePoints.Count].dLen;
   261 
   257                 Gear^.Friction := Gear^.Friction + RopePoints.ar[RopePoints.Count].dLen;
   262                 // oops, opposite quadrant, don't restore hog position in such case, just remove the point
   258 
   263                 wrongSide:= (ropeDx.isNegative = RopePoints.ar[RopePoints.Count].sx)
   259                 // restore hog position
   264                     and (ropeDy.isNegative = RopePoints.ar[RopePoints.Count].sy);
   260                 len := _1 / Distance(mdX, mdY);
   265 
   261                 mdX := mdX * len;
   266                 // previous check could be inaccurate in vertical/horizontal rope positions,
   262                 mdY := mdY * len;
   267                 // so perform this check also, even though odds are 1 to 415927 to hit this
   263 
   268                 if (not wrongSide)
   264                 HHGear^.X := Gear^.X - mdX * Gear^.Elasticity;
   269                     and ((ropeDx.isNegative = RopePoints.ar[RopePoints.Count].sx)
   265                 HHGear^.Y := Gear^.Y - mdY * Gear^.Elasticity;
   270                       <> (ropeDy.isNegative = RopePoints.ar[RopePoints.Count].sy)) then
       
   271                     if RopePoints.ar[RopePoints.Count].sb then
       
   272                         wrongSide:= ropeDy.isNegative = RopePoints.ar[RopePoints.Count].sy
       
   273                         else
       
   274                         wrongSide:= ropeDx.isNegative = RopePoints.ar[RopePoints.Count].sx;
       
   275 
       
   276                 if wrongSide then
       
   277                     begin
       
   278                     Gear^.Elasticity := Gear^.Elasticity - RopePoints.ar[RopePoints.Count].dLen;
       
   279                     Gear^.Friction := Gear^.Friction - RopePoints.ar[RopePoints.Count].dLen;
       
   280                     end else
       
   281                     begin
       
   282                     Gear^.Elasticity := Gear^.Elasticity + RopePoints.ar[RopePoints.Count].dLen;
       
   283                     Gear^.Friction := Gear^.Friction + RopePoints.ar[RopePoints.Count].dLen;
       
   284 
       
   285                     // restore hog position
       
   286                     len := _1 / Distance(mdX, mdY);
       
   287                     mdX := mdX * len;
       
   288                     mdY := mdY * len;
       
   289 
       
   290                     HHGear^.X := Gear^.X - mdX * Gear^.Elasticity;
       
   291                     HHGear^.Y := Gear^.Y - mdY * Gear^.Elasticity;
       
   292                     end;
   266                 end
   293                 end
   267             end;
   294             end;
   268 
   295 
   269     haveCollision := false;
   296     haveCollision := false;
   270     if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
   297     if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then