hedgewars/uGearsHandlersRope.pas
changeset 7657 347e18494fb9
parent 7656 e7bef1a4fda7
child 7658 70a874a26414
equal deleted inserted replaced
7656:e7bef1a4fda7 7657:347e18494fb9
    96 end;
    96 end;
    97 
    97 
    98 procedure doStepRopeWork(Gear: PGear);
    98 procedure doStepRopeWork(Gear: PGear);
    99 var 
    99 var 
   100     HHGear: PGear;
   100     HHGear: PGear;
   101     len, tx, ty, nx, ny, ropeDx, ropeDy, mdX, mdY, sDx, sDy: hwFloat;
   101     len, tx, ty, nx, ny, ropeDx, ropeDy, mdX, mdY: hwFloat;
   102     i, lx, ly, cd: LongInt;
   102     lx, ly, cd: LongInt;
   103     haveCollision,
   103     haveCollision,
   104     haveDivided: boolean;
   104     haveDivided: boolean;
   105 
   105 
   106 begin
   106 begin
   107     if GameTicks mod 8 <> 0 then exit;
   107     if GameTicks mod 4 <> 0 then exit;
   108 
   108 
   109     HHGear := Gear^.Hedgehog^.Gear;
   109     HHGear := Gear^.Hedgehog^.Gear;
   110 
   110 
   111     if ((HHGear^.State and gstHHDriven) = 0)
   111     if ((HHGear^.State and gstHHDriven) = 0)
   112        or (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then
   112        or (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then
   113         begin
   113         begin
       
   114         HHGear^.dX.QWordValue:= HHGear^.dX.QWordValue shr 2;
       
   115         HHGear^.dY.QWordValue:= HHGear^.dY.QWordValue shr 2;
   114         PlaySound(sndRopeRelease);
   116         PlaySound(sndRopeRelease);
   115         RopeDeleteMe(Gear, HHGear);
   117         RopeDeleteMe(Gear, HHGear);
   116         exit
   118         exit
   117         end;
   119         end;
   118 
   120 
   119     HHGear^.dX.QWordValue:= HHGear^.dX.QWordValue shl 3;
       
   120     HHGear^.dY.QWordValue:= HHGear^.dY.QWordValue shl 3;
       
   121 
       
   122     if (Gear^.Message and gmLeft  <> 0) and (not TestCollisionXwithGear(HHGear, -1)) then
   121     if (Gear^.Message and gmLeft  <> 0) and (not TestCollisionXwithGear(HHGear, -1)) then
   123         HHGear^.dX := HHGear^.dX - _0_0128;
   122         HHGear^.dX := HHGear^.dX - _0_0032;
   124 
   123 
   125     if (Gear^.Message and gmRight <> 0) and (not TestCollisionXwithGear(HHGear,  1)) then
   124     if (Gear^.Message and gmRight <> 0) and (not TestCollisionXwithGear(HHGear,  1)) then
   126         HHGear^.dX := HHGear^.dX + _0_0128;
   125         HHGear^.dX := HHGear^.dX + _0_0032;
   127 
   126 
   128     // vector between hedgehog and rope attaching point
   127     // vector between hedgehog and rope attaching point
   129     ropeDx := HHGear^.X - Gear^.X;
   128     ropeDx := HHGear^.X - Gear^.X;
   130     ropeDy := HHGear^.Y - Gear^.Y;
   129     ropeDy := HHGear^.Y - Gear^.Y;
   131 
   130 
   139         else
   138         else
   140             cd:= 1;
   139             cd:= 1;
   141 
   140 
   142         // apply gravity if there is no obstacle
   141         // apply gravity if there is no obstacle
   143         if not TestCollisionXwithGear(HHGear, cd) then
   142         if not TestCollisionXwithGear(HHGear, cd) then
   144             HHGear^.dY := HHGear^.dY + cGravity * 64;
   143             HHGear^.dY := HHGear^.dY + cGravity * 16;
   145 
   144 
   146         if (GameFlags and gfMoreWind) <> 0 then
   145         if (GameFlags and gfMoreWind) <> 0 then
   147             // apply wind if there's no obstacle
   146             // apply wind if there's no obstacle
   148             if not TestCollisionXwithGear(HHGear, hwSign(cWindSpeed)) then
   147             if not TestCollisionXwithGear(HHGear, hwSign(cWindSpeed)) then
   149                 HHGear^.dX := HHGear^.dX + cWindSpeed * 64 / HHGear^.Density;
   148                 HHGear^.dX := HHGear^.dX + cWindSpeed * 16 / HHGear^.Density;
   150         end;
   149         end;
   151 
   150 
   152     mdX := ropeDx + HHGear^.dX;
   151     mdX := ropeDx + HHGear^.dX;
   153     mdY := ropeDy + HHGear^.dY;
   152     mdY := ropeDy + HHGear^.dY;
   154     len := _1 / Distance(mdX, mdY);
   153     len := _1 / Distance(mdX, mdY);
   165     ty := HHGear^.Y;
   164     ty := HHGear^.Y;
   166 
   165 
   167     if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
   166     if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
   168         if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
   167         if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
   169         or (TestCollisionYwithGear(HHGear, hwSign(ropeDy)) <> 0)) then
   168         or (TestCollisionYwithGear(HHGear, hwSign(ropeDy)) <> 0)) then
   170             Gear^.Elasticity := Gear^.Elasticity + _2_4;
   169             Gear^.Elasticity := Gear^.Elasticity + _1_2;
   171 
   170 
   172     if ((Gear^.Message and gmUp) <> 0) and (Gear^.Elasticity > _30) then
   171     if ((Gear^.Message and gmUp) <> 0) and (Gear^.Elasticity > _30) then
   173         if not (TestCollisionXwithGear(HHGear, -hwSign(ropeDx))
   172         if not (TestCollisionXwithGear(HHGear, -hwSign(ropeDx))
   174         or (TestCollisionYwithGear(HHGear, -hwSign(ropeDy)) <> 0)) then
   173         or (TestCollisionYwithGear(HHGear, -hwSign(ropeDy)) <> 0)) then
   175             Gear^.Elasticity := Gear^.Elasticity - _2_4;
   174             Gear^.Elasticity := Gear^.Elasticity - _1_2;
   176 
   175 
   177     HHGear^.X := Gear^.X + mdX * Gear^.Elasticity;
   176     HHGear^.X := Gear^.X + mdX * Gear^.Elasticity;
   178     HHGear^.Y := Gear^.Y + mdY * Gear^.Elasticity;
   177     HHGear^.Y := Gear^.Y + mdY * Gear^.Elasticity;
   179 
   178 
   180     HHGear^.dX := Gear^.X + mdX * Gear^.Elasticity - tx;
   179     HHGear^.dX := HHGear^.X - tx;
   181     HHGear^.dY := Gear^.Y + mdY * Gear^.Elasticity - ty;
   180     HHGear^.dY := HHGear^.Y - ty;
   182 
       
   183     sDx:= HHGear^.dX / 8;
       
   184     sDy:= HHGear^.dY / 8;
       
   185 
       
   186     HHGear^.X:= tx;
       
   187     HHGear^.Y:= ty;
       
   188 
       
   189     i:= 0;
       
   190     while not ((i = 8)
       
   191         or TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX))
       
   192         or (TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) <> 0)) do
       
   193         begin
       
   194         inc(i);
       
   195         HHGear^.X:= HHGear^.X + sDx;
       
   196         HHGear^.Y:= HHGear^.Y + sDy;
       
   197         end;
       
   198     ////
   181     ////
   199 
   182 
   200 
   183 
   201     haveDivided := false;
   184     haveDivided := false;
   202     // check whether rope needs dividing
   185     // check whether rope needs dividing
   203 
   186 
   204     len := Gear^.Elasticity - _5;
   187     len := Gear^.Elasticity - _5;
   205     nx := Gear^.X + mdX * len;
   188     nx := Gear^.X + mdX * len;
   206     ny := Gear^.Y + mdY * len;
   189     ny := Gear^.Y + mdY * len;
   207     tx := mdX * _2_4; // should be the same as increase step
   190     tx := mdX * _1_2; // should be the same as increase step
   208     ty := mdY * _2_4;
   191     ty := mdY * _1_2;
   209 
   192 
   210     while len > _3 do
   193     while len > _3 do
   211         begin
   194         begin
   212         lx := hwRound(nx);
   195         lx := hwRound(nx);
   213         ly := hwRound(ny);
   196         ly := hwRound(ny);
   244             break
   227             break
   245             end;
   228             end;
   246         nx := nx - tx;
   229         nx := nx - tx;
   247         ny := ny - ty;
   230         ny := ny - ty;
   248 
   231 
   249         // len := len - _2_4 // should be the same as increase step
   232         // len := len - _1_2 // should be the same as increase step
   250         len.QWordValue := len.QWordValue - _2_4.QWordValue;
   233         len.QWordValue := len.QWordValue - _1_2.QWordValue;
   251         end;
   234         end;
   252 
   235 
   253     if not haveDivided then
   236     if not haveDivided then
   254         if RopePoints.Count > 0 then // check whether the last dividing point could be removed
   237         if RopePoints.Count > 0 then // check whether the last dividing point could be removed
   255             begin
   238             begin
   287         haveCollision := true
   270         haveCollision := true
   288         end;
   271         end;
   289 
   272 
   290     if haveCollision and (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.Message and (gmUp or gmDown) <> 0) then
   273     if haveCollision and (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.Message and (gmUp or gmDown) <> 0) then
   291         begin
   274         begin
   292         HHGear^.dX := SignAs(hwAbs(HHGear^.dX) + _1_6, HHGear^.dX);
   275         HHGear^.dX := SignAs(hwAbs(HHGear^.dX) + _0_8, HHGear^.dX);
   293         HHGear^.dY := SignAs(hwAbs(HHGear^.dY) + _1_6, HHGear^.dY)
   276         HHGear^.dY := SignAs(hwAbs(HHGear^.dY) + _0_8, HHGear^.dY)
   294         end;
   277         end;
   295 
   278 
   296     len := hwSqr(HHGear^.dX) + hwSqr(HHGear^.dY);
   279     len := hwSqr(HHGear^.dX) + hwSqr(HHGear^.dY);
   297     if len > _49 then
   280     if len > _10 then
   298         begin
   281         begin
   299         len := _7 / hwSqrt(len);
   282         len := _3_2 / hwSqrt(len);
   300         HHGear^.dX := HHGear^.dX * len;
   283         HHGear^.dX := HHGear^.dX * len;
   301         HHGear^.dY := HHGear^.dY * len;
   284         HHGear^.dY := HHGear^.dY * len;
   302         end;
   285         end;
   303 
   286 
   304     haveCollision:= ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)]) <> 0);
   287     haveCollision:= ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)]) <> 0);
   340 
   323 
   341     if not haveCollision then
   324     if not haveCollision then
   342         begin
   325         begin
   343         if (Gear^.State and gsttmpFlag) <> 0 then
   326         if (Gear^.State and gsttmpFlag) <> 0 then
   344             begin
   327             begin
       
   328             HHGear^.dX.QWordValue:= HHGear^.dX.QWordValue shr 2;
       
   329             HHGear^.dY.QWordValue:= HHGear^.dY.QWordValue shr 2;
       
   330             
   345             PlaySound(sndRopeRelease);
   331             PlaySound(sndRopeRelease);
   346             if Gear^.Hedgehog^.CurAmmoType <> amParachute then
   332             if Gear^.Hedgehog^.CurAmmoType <> amParachute then
   347                 RopeWaitCollision(Gear, HHGear)
   333                 RopeWaitCollision(Gear, HHGear)
   348             else
   334             else
   349                 RopeDeleteMe(Gear, HHGear)
   335                 RopeDeleteMe(Gear, HHGear)
   350             end
   336             end
   351         end
   337         end
   352     else
   338     else
   353         if (Gear^.State and gsttmpFlag) = 0 then
   339         if (Gear^.State and gsttmpFlag) = 0 then
   354             Gear^.State := Gear^.State or gsttmpFlag;
   340             Gear^.State := Gear^.State or gsttmpFlag;
   355 
       
   356     HHGear^.dX.QWordValue:= HHGear^.dX.QWordValue shr 3;
       
   357     HHGear^.dY.QWordValue:= HHGear^.dY.QWordValue shr 3;
       
   358 end;
   341 end;
   359 
   342 
   360 procedure RopeRemoveFromAmmo(Gear, HHGear: PGear);
   343 procedure RopeRemoveFromAmmo(Gear, HHGear: PGear);
   361 begin
   344 begin
   362     if (Gear^.State and gstAttacked) = 0 then
   345     if (Gear^.State and gstAttacked) = 0 then
   416                 Gear^.Elasticity := tt;
   399                 Gear^.Elasticity := tt;
   417                 Gear^.doStep := @doStepRopeWork;
   400                 Gear^.doStep := @doStepRopeWork;
   418                 PlaySound(sndRopeAttach);
   401                 PlaySound(sndRopeAttach);
   419                 with HHGear^ do
   402                 with HHGear^ do
   420                     begin
   403                     begin
       
   404                     dX.QWordValue:= dX.QWordValue shl 2;
       
   405                     dY.QWordValue:= dY.QWordValue shl 2;
   421                     State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
   406                     State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
   422                     Message := Message and (not gmAttack)
   407                     Message := Message and (not gmAttack)
   423                     end;
   408                     end;
   424 
   409 
   425                 RopeRemoveFromAmmo(Gear, HHGear);
   410                 RopeRemoveFromAmmo(Gear, HHGear);
   442         begin
   427         begin
   443         Gear^.doStep := @doStepRopeWork;
   428         Gear^.doStep := @doStepRopeWork;
   444         PlaySound(sndRopeAttach);
   429         PlaySound(sndRopeAttach);
   445         with HHGear^ do
   430         with HHGear^ do
   446             begin
   431             begin
       
   432             dX.QWordValue:= dX.QWordValue shl 2;
       
   433             dY.QWordValue:= dY.QWordValue shl 2;
   447             State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
   434             State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
   448             Message := Message and (not gmAttack)
   435             Message := Message and (not gmAttack)
   449             end;
   436             end;
   450 
   437 
   451         RopeRemoveFromAmmo(Gear, HHGear);
   438         RopeRemoveFromAmmo(Gear, HHGear);