hedgewars/uCollisions.pas
branchtransitional_engine
changeset 15900 128ace913837
parent 15722 498c1482dec2
equal deleted inserted replaced
15899:73cdc306888f 15900:128ace913837
    68 function  CheckCacheCollision(SourceGear: PGear): PGearArray;
    68 function  CheckCacheCollision(SourceGear: PGear): PGearArray;
    69 
    69 
    70 function  CheckGearsLineCollision(Gear: PGear; oX, oY, tX, tY: hwFloat): PGearArray;
    70 function  CheckGearsLineCollision(Gear: PGear; oX, oY, tX, tY: hwFloat): PGearArray;
    71 function  CheckAllGearsLineCollision(SourceGear: PGear; oX, oY, tX, tY: hwFloat): PGearArray;
    71 function  CheckAllGearsLineCollision(SourceGear: PGear; oX, oY, tX, tY: hwFloat): PGearArray;
    72 
    72 
    73 function  UpdateHitOrder(Gear: PGear; Order: LongInt): boolean; inline;
    73 function  UpdateHitOrder(Gear: PGear; Order: LongInt): boolean;
    74 function  UpdateHitOrder(Gear: PGear; Order: LongInt; Global: boolean): boolean; inline;
    74 function  UpdateHitOrder(Gear: PGear; Order: LongInt; Global: boolean): boolean;
    75 function  UpdateGlobalHitOrder(Gear: PGear; Order: LongInt): boolean; inline;
    75 function  UpdateGlobalHitOrder(Gear: PGear; Order: LongInt): boolean;
    76 procedure ClearHitOrderLeq(MinOrder: LongInt); inline;
    76 procedure ClearHitOrderLeq(MinOrder: LongInt);
    77 procedure ClearGlobalHitOrderLeq(MinOrder: LongInt); inline;
    77 procedure ClearGlobalHitOrderLeq(MinOrder: LongInt);
    78 procedure ClearHitOrder();
    78 procedure ClearHitOrder();
    79 
    79 
    80 procedure RefillProximityCache(SourceGear: PGear; radius: LongInt);
    80 procedure RefillProximityCache(SourceGear: PGear; radius: LongInt);
    81 procedure RemoveFromProximityCache(Gear: PGear);
    81 procedure RemoveFromProximityCache(Gear: PGear);
    82 procedure ClearProximityCache();
    82 procedure ClearProximityCache();
    83 
    83 
    84 function  TestCollisionXImpl(centerX, centerY, radius, direction: LongInt; collisionMask: Word): Word;
    84 function  TestCollisionXImpl(centerX, centerY, radius, direction: LongInt; collisionMask: Word): Word;
    85 function  TestCollisionYImpl(centerX, centerY, radius, direction: LongInt; collisionMask: Word): Word;
    85 function  TestCollisionYImpl(centerX, centerY, radius, direction: LongInt; collisionMask: Word): Word;
    86 
    86 
    87 function  TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word; inline;
    87 function  TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word;
    88 function  TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; inline;
    88 function  TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word;
    89 
    89 
    90 function  TestCollisionX(Gear: PGear; Dir: LongInt): Word; inline;
    90 function  TestCollisionX(Gear: PGear; Dir: LongInt): Word;
    91 function  TestCollisionY(Gear: PGear; Dir: LongInt): Word; inline;
    91 function  TestCollisionY(Gear: PGear; Dir: LongInt): Word;
    92 
    92 
    93 function  TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): Word; inline;
    93 function  TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): Word;
    94 function  TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; inline;
    94 function  TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word;
    95 function  TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): Word; inline;
    95 function  TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): Word;
    96 function  TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; inline;
    96 function  TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word;
    97 
    97 
    98 function  TestCollisionXKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
    98 function  TestCollisionXKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
    99 function  TestCollisionYKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
    99 function  TestCollisionYKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
   100 
   100 
   101 function  TestCollisionXKick(Gear: PGear; Dir: LongInt): Word;
   101 function  TestCollisionXKick(Gear: PGear; Dir: LongInt): Word;
   102 function  TestCollisionYKick(Gear: PGear; Dir: LongInt): Word;
   102 function  TestCollisionYKick(Gear: PGear; Dir: LongInt): Word;
   103 
   103 
   104 function  TestRectangleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean;
   104 function  TestRectangleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean;
   105 
   105 
   106 function  CheckCoordInWater(X, Y: LongInt): boolean; inline;
   106 function  CheckCoordInWater(X, Y: LongInt): boolean;
   107 
   107 
   108 // returns: negative sign if going downhill to left, value is steepness (noslope/error = _0, 45 = _0_5)
   108 // returns: negative sign if going downhill to left, value is steepness (noslope/error = _0, 45 = _0_5)
   109 function  CalcSlopeBelowGear(Gear: PGear): hwFloat;
   109 function  CalcSlopeBelowGear(Gear: PGear): hwFloat;
   110 function  CalcSlopeNearGear(Gear: PGear; dirX, dirY: LongInt): hwFloat;
   110 function  CalcSlopeNearGear(Gear: PGear; dirX, dirY: LongInt): hwFloat;
   111 function  CalcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): boolean;
   111 function  CalcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): boolean;
   112 
   112 
   113 function CheckGearsUnderSprite(Sprite: TSprite; sprX, sprY, Frame: LongInt): boolean;
   113 function CheckGearsUnderSprite(Sprite: TSprite; sprX, sprY, Frame: LongInt): boolean;
   114 
   114 
   115 implementation
   115 implementation
   116 uses uConsts, uLandGraphics, uVariables, SDLh, uLandTexture, uDebug;
   116 uses uConsts, uLandGraphics, uVariables, SDLh, uLandTexture, uDebug, uLandUtils;
   117 
   117 
   118 type TCollisionEntry = record
   118 type TCollisionEntry = record
   119     X, Y, Radius: LongInt;
   119     X, Y, Radius: LongInt;
   120     cGear: PGear;
   120     cGear: PGear;
   121     end;
   121     end;
   157     Gear^.CollisionIndex:= -1;
   157     Gear^.CollisionIndex:= -1;
   158     dec(Count)
   158     dec(Count)
   159     end;
   159     end;
   160 end;
   160 end;
   161 
   161 
   162 function CheckCoordInWater(X, Y: LongInt): boolean; inline;
   162 function CheckCoordInWater(X, Y: LongInt): boolean;
   163 begin
   163 begin
   164     CheckCoordInWater:= (Y > cWaterLine)
   164     CheckCoordInWater:= (Y > cWaterLine)
   165         or ((WorldEdge = weSea) and ((X < leftX) or (X > rightX)));
   165         or ((WorldEdge = weSea) and ((X < leftX) or (X > rightX)));
   166 end;
   166 end;
   167 
   167 
   219         end;
   219         end;
   220 end;
   220 end;
   221 
   221 
   222 function LineCollisionTest(oX, oY, dirX, dirY, dirNormSqr, dirNormBound: hwFloat;
   222 function LineCollisionTest(oX, oY, dirX, dirY, dirNormSqr, dirNormBound: hwFloat;
   223         width: LongInt; Gear: PGear):
   223         width: LongInt; Gear: PGear):
   224     TLineCollision; inline;
   224     TLineCollision;
   225 var toCenterX, toCenterY, r,
   225 var toCenterX, toCenterY, r,
   226     b, bSqr, c, desc, t: hwFloat;
   226     b, bSqr, c, desc, t: hwFloat;
   227     realT: extended;
   227     realT: extended;
   228 begin
   228 begin
   229     LineCollisionTest.hasCollision:= false;
   229     LineCollisionTest.hasCollision:= false;
   365         HitOrder^.order[HitOrder^.Count] := Order;
   365         HitOrder^.order[HitOrder^.Count] := Order;
   366         Inc(HitOrder^.Count);
   366         Inc(HitOrder^.Count);
   367     end
   367     end
   368 end;
   368 end;
   369 
   369 
   370 function UpdateHitOrder(Gear: PGear; Order: LongInt): boolean; inline;
   370 function UpdateHitOrder(Gear: PGear; Order: LongInt): boolean;
   371 begin
   371 begin
   372     UpdateHitOrder := UpdateHitOrderImpl(@ordera, Gear, Order);
   372     UpdateHitOrder := UpdateHitOrderImpl(@ordera, Gear, Order);
   373 end;
   373 end;
   374 
   374 
   375 function UpdateHitOrder(Gear: PGear; Order: LongInt; Global: boolean): boolean; inline;
   375 function UpdateHitOrder(Gear: PGear; Order: LongInt; Global: boolean): boolean;
   376 begin
   376 begin
   377     if Global then
   377     if Global then
   378         UpdateHitOrder := UpdateHitOrderImpl(@globalordera, Gear, Order)
   378         UpdateHitOrder := UpdateHitOrderImpl(@globalordera, Gear, Order)
   379     else
   379     else
   380         UpdateHitOrder := UpdateHitOrderImpl(@ordera, Gear, Order)
   380         UpdateHitOrder := UpdateHitOrderImpl(@ordera, Gear, Order)
   381 end;
   381 end;
   382 
   382 
   383 function UpdateGlobalHitOrder(Gear: PGear; Order: LongInt): boolean; inline;
   383 function UpdateGlobalHitOrder(Gear: PGear; Order: LongInt): boolean;
   384 begin
   384 begin
   385     UpdateGlobalHitOrder := UpdateHitOrderImpl(@globalordera, Gear, Order);
   385     UpdateGlobalHitOrder := UpdateHitOrderImpl(@globalordera, Gear, Order);
   386 end;
   386 end;
   387 
   387 
   388 procedure ClearHitOrderLeqImpl(HitOrder: PGearHitOrder; MinOrder: LongInt);
   388 procedure ClearHitOrderLeqImpl(HitOrder: PGearHitOrder; MinOrder: LongInt);
   406         end;
   406         end;
   407         Inc(i)
   407         Inc(i)
   408     end
   408     end
   409 end;
   409 end;
   410 
   410 
   411 procedure ClearHitOrderLeq(MinOrder: LongInt); inline;
   411 procedure ClearHitOrderLeq(MinOrder: LongInt);
   412 begin
   412 begin
   413     ClearHitOrderLeqImpl(@ordera, MinOrder);
   413     ClearHitOrderLeqImpl(@ordera, MinOrder);
   414 end;
   414 end;
   415 
   415 
   416 procedure ClearGlobalHitOrderLeq(MinOrder: LongInt); inline;
   416 procedure ClearGlobalHitOrderLeq(MinOrder: LongInt);
   417 begin
   417 begin
   418     ClearHitOrderLeqImpl(@globalordera, MinOrder);
   418     ClearHitOrderLeqImpl(@globalordera, MinOrder);
   419 end;
   419 end;
   420 
   420 
   421 procedure ClearHitOrder();
   421 procedure ClearHitOrder();
   478     if (x and LAND_WIDTH_MASK) = 0 then
   478     if (x and LAND_WIDTH_MASK) = 0 then
   479     begin
   479     begin
   480         minY := max(centerY - radius + 1, 0);
   480         minY := max(centerY - radius + 1, 0);
   481         maxY := min(centerY + radius - 1, LAND_HEIGHT - 1);
   481         maxY := min(centerY + radius - 1, LAND_HEIGHT - 1);
   482         for y := minY to maxY do
   482         for y := minY to maxY do
   483             if Land[y, x] and collisionMask <> 0 then
   483             if LandGet(y, x) and collisionMask <> 0 then
   484                 exit(Land[y, x] and collisionMask);
   484                 exit(LandGet(y, x) and collisionMask);
   485     end;
   485     end;
   486     TestCollisionXImpl := 0;
   486     TestCollisionXImpl := 0;
   487 end;
   487 end;
   488 
   488 
   489 function TestCollisionYImpl(centerX, centerY, radius, direction: LongInt; collisionMask: Word): Word;
   489 function TestCollisionYImpl(centerX, centerY, radius, direction: LongInt; collisionMask: Word): Word;
   497     if (y and LAND_HEIGHT_MASK) = 0 then
   497     if (y and LAND_HEIGHT_MASK) = 0 then
   498     begin
   498     begin
   499         minX := max(centerX - radius + 1, 0);
   499         minX := max(centerX - radius + 1, 0);
   500         maxX := min(centerX + radius - 1, LAND_WIDTH - 1);
   500         maxX := min(centerX + radius - 1, LAND_WIDTH - 1);
   501         for x := minX to maxX do
   501         for x := minX to maxX do
   502             if Land[y, x] and collisionMask <> 0 then
   502             if LandGet(y, x) and collisionMask <> 0 then
   503                 exit(Land[y, x] and collisionMask);
   503                 exit(LandGet(y, x) and collisionMask);
   504     end;
   504     end;
   505     TestCollisionYImpl := 0;
   505     TestCollisionYImpl := 0;
   506 end;
   506 end;
   507 
   507 
   508 function TestCollisionX(Gear: PGear; Dir: LongInt): Word; inline;
   508 function TestCollisionX(Gear: PGear; Dir: LongInt): Word;
   509 begin
   509 begin
   510     TestCollisionX := TestCollisionXImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask and lfLandMask);
   510     TestCollisionX := TestCollisionXImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask and lfLandMask);
   511 end;
   511 end;
   512 
   512 
   513 function TestCollisionY(Gear: PGear; Dir: LongInt): Word; inline;
   513 function TestCollisionY(Gear: PGear; Dir: LongInt): Word;
   514 begin
   514 begin
   515     TestCollisionY := TestCollisionYImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask and lfLandMask);
   515     TestCollisionY := TestCollisionYImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask and lfLandMask);
   516 end;
   516 end;
   517 
   517 
   518 procedure LegacyFixupX(Gear: PGear);
   518 procedure LegacyFixupX(Gear: PGear);
   531     ((hwRound(Gear^.Hedgehog^.Gear^.Y) + Gear^.Hedgehog^.Gear^.Radius + 16 < hwRound(Gear^.Y) - Gear^.Radius) or
   531     ((hwRound(Gear^.Hedgehog^.Gear^.Y) + Gear^.Hedgehog^.Gear^.Radius + 16 < hwRound(Gear^.Y) - Gear^.Radius) or
   532     (hwRound(Gear^.Hedgehog^.Gear^.Y) - Gear^.Hedgehog^.Gear^.Radius - 16 > hwRound(Gear^.Y) + Gear^.Radius)) then
   532     (hwRound(Gear^.Hedgehog^.Gear^.Y) - Gear^.Hedgehog^.Gear^.Radius - 16 > hwRound(Gear^.Y) + Gear^.Radius)) then
   533         Gear^.CollisionMask:= lfAll;
   533         Gear^.CollisionMask:= lfAll;
   534 end;
   534 end;
   535 
   535 
   536 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word; inline;
   536 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word;
   537 begin
   537 begin
   538     LegacyFixupX(Gear);
   538     LegacyFixupX(Gear);
   539     TestCollisionXwithGear:= TestCollisionXImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask);
   539     TestCollisionXwithGear:= TestCollisionXImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask);
   540 end;
   540 end;
   541 
   541 
   542 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; inline;
   542 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word;
   543 begin
   543 begin
   544     LegacyFixupY(Gear);
   544     LegacyFixupY(Gear);
   545     TestCollisionYwithGear:= TestCollisionYImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask);
   545     TestCollisionYwithGear:= TestCollisionYImpl(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, Dir, Gear^.CollisionMask);
   546 end;
   546 end;
   547 
   547 
   548 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; inline;
   548 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word;
   549 var collisionMask: Word;
   549 var collisionMask: Word;
   550 begin
   550 begin
   551     if withGear then
   551     if withGear then
   552     begin
   552     begin
   553         LegacyFixupX(Gear);
   553         LegacyFixupX(Gear);
   557         collisionMask:= Gear^.CollisionMask and lfLandMask;
   557         collisionMask:= Gear^.CollisionMask and lfLandMask;
   558 
   558 
   559     TestCollisionXwithXYShift := TestCollisionXImpl(hwRound(Gear^.X + ShiftX), hwRound(Gear^.Y) + ShiftY, Gear^.Radius, Dir, collisionMask)
   559     TestCollisionXwithXYShift := TestCollisionXImpl(hwRound(Gear^.X + ShiftX), hwRound(Gear^.Y) + ShiftY, Gear^.Radius, Dir, collisionMask)
   560 end;
   560 end;
   561 
   561 
   562 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; inline;
   562 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word;
   563 var collisionMask: Word;
   563 var collisionMask: Word;
   564 begin
   564 begin
   565     if withGear then
   565     if withGear then
   566     begin
   566     begin
   567         LegacyFixupY(Gear);
   567         LegacyFixupY(Gear);
   571         collisionMask:= Gear^.CollisionMask and lfLandMask;
   571         collisionMask:= Gear^.CollisionMask and lfLandMask;
   572 
   572 
   573     TestCollisionYwithXYShift := TestCollisionYImpl(hwRound(Gear^.X) + ShiftX, hwRound(Gear^.Y) + ShiftY, Gear^.Radius, Dir, collisionMask)
   573     TestCollisionYwithXYShift := TestCollisionYImpl(hwRound(Gear^.X) + ShiftX, hwRound(Gear^.Y) + ShiftY, Gear^.Radius, Dir, collisionMask)
   574 end;
   574 end;
   575 
   575 
   576 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): Word; inline;
   576 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): Word;
   577 begin
   577 begin
   578     TestCollisionXwithXYShift:= TestCollisionXwithXYShift(Gear, ShiftX, ShiftY, Dir, true);
   578     TestCollisionXwithXYShift:= TestCollisionXwithXYShift(Gear, ShiftX, ShiftY, Dir, true);
   579 end;
   579 end;
   580 
   580 
   581 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): Word; inline;
   581 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): Word;
   582 begin
   582 begin
   583     TestCollisionYwithXYShift:= TestCollisionYwithXYShift(Gear, ShiftX, ShiftY, Dir, true);
   583     TestCollisionYwithXYShift:= TestCollisionYwithXYShift(Gear, ShiftX, ShiftY, Dir, true);
   584 end;
   584 end;
   585 
   585 
   586 function TestCollisionXKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
   586 function TestCollisionXKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
   597     if (x and LAND_WIDTH_MASK) = 0 then
   597     if (x and LAND_WIDTH_MASK) = 0 then
   598     begin
   598     begin
   599         minY := max(centerY - radius + 1, 0);
   599         minY := max(centerY - radius + 1, 0);
   600         maxY := min(centerY + radius - 1, LAND_HEIGHT - 1);
   600         maxY := min(centerY + radius - 1, LAND_HEIGHT - 1);
   601         for y := minY to maxY do
   601         for y := minY to maxY do
   602             if Land[y, x] and collisionMask <> 0 then
   602             if LandGet(y, x) and collisionMask <> 0 then
   603             begin
   603             begin
   604                 TestCollisionXKickImpl.kick := false;
   604                 TestCollisionXKickImpl.kick := false;
   605                 TestCollisionXKickImpl.collisionMask := Land[y, x] and collisionMask;
   605                 TestCollisionXKickImpl.collisionMask := LandGet(y, x) and collisionMask;
   606                 exit
   606                 exit
   607             end
   607             end
   608             else if Land[y, x] and kickMask <> 0 then
   608             else if LandGet(y, x) and kickMask <> 0 then
   609             begin
   609             begin
   610                 TestCollisionXKickImpl.kick := true;
   610                 TestCollisionXKickImpl.kick := true;
   611                 TestCollisionXKickImpl.collisionMask := Land[y, x] and kickMask;
   611                 TestCollisionXKickImpl.collisionMask := LandGet(y, x) and kickMask;
   612             end;
   612             end;
   613     end;
   613     end;
   614 end;
   614 end;
   615 
   615 
   616 function TestCollisionYKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
   616 function TestCollisionYKickImpl(centerX, centerY, radius, direction: LongInt; collisionMask, kickMask: Word): TKickTest;
   627     if (y and LAND_HEIGHT_MASK) = 0 then
   627     if (y and LAND_HEIGHT_MASK) = 0 then
   628     begin
   628     begin
   629         minX := max(centerX - radius + 1, 0);
   629         minX := max(centerX - radius + 1, 0);
   630         maxX := min(centerX + radius - 1, LAND_WIDTH - 1);
   630         maxX := min(centerX + radius - 1, LAND_WIDTH - 1);
   631         for x := minX to maxX do
   631         for x := minX to maxX do
   632             if Land[y, x] and collisionMask <> 0 then
   632             if LandGet(y, x) and collisionMask <> 0 then
   633             begin
   633             begin
   634                 TestCollisionYKickImpl.kick := false;
   634                 TestCollisionYKickImpl.kick := false;
   635                 TestCollisionYKickImpl.collisionMask := Land[y, x] and collisionMask;
   635                 TestCollisionYKickImpl.collisionMask := LandGet(y, x) and collisionMask;
   636                 exit
   636                 exit
   637             end
   637             end
   638             else if Land[y, x] and kickMask <> 0 then
   638             else if LandGet(y, x) and kickMask <> 0 then
   639             begin
   639             begin
   640                 TestCollisionYKickImpl.kick := true;
   640                 TestCollisionYKickImpl.kick := true;
   641                 TestCollisionYKickImpl.collisionMask := Land[y, x] and kickMask;
   641                 TestCollisionYKickImpl.collisionMask := LandGet(y, x) and kickMask;
   642             end;
   642             end;
   643     end;
   643     end;
   644 end;
   644 end;
   645 
   645 
   646 function TestCollisionXKick(Gear: PGear; Dir: LongInt): Word;
   646 function TestCollisionXKick(Gear: PGear; Dir: LongInt): Word;
   765 if (hasBorder and ((y1 < 0) or (x1 < 0) or (x2 > LAND_WIDTH))) then
   765 if (hasBorder and ((y1 < 0) or (x1 < 0) or (x2 > LAND_WIDTH))) then
   766     exit;
   766     exit;
   767 
   767 
   768 for y := y1 to y2 do
   768 for y := y1 to y2 do
   769     for x := x1 to x2 do
   769     for x := x1 to x2 do
   770         if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > TestWord) then
   770         if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (LandGet(y, x) > TestWord) then
   771             exit;
   771             exit;
   772 
   772 
   773 TestRectangleForObstacle:= false
   773 TestRectangleForObstacle:= false
   774 end;
   774 end;
   775 
   775 
   814             begin
   814             begin
   815             tmpx:= collisionX + k * mx;
   815             tmpx:= collisionX + k * mx;
   816             tmpy:= collisionY + k * my;
   816             tmpy:= collisionY + k * my;
   817 
   817 
   818             if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK) = 0) then
   818             if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK) = 0) then
   819                 if (Land[tmpy,tmpx] > TestWord) then
   819                 if (LandGet(tmpy,tmpx) > TestWord) then
   820                     begin
   820                     begin
   821                     // remember the index belonging to the first and last collision (if in 1st half)
   821                     // remember the index belonging to the first and last collision (if in 1st half)
   822                     if (i <> 0) then
   822                     if (i <> 0) then
   823                         begin
   823                         begin
   824                         if (ri = -1) then
   824                         if (ri = -1) then
   865             for k:= 3 downto 1 do
   865             for k:= 3 downto 1 do
   866                 begin
   866                 begin
   867                 tmpx:= ldx + k * offset[tmpo,0];
   867                 tmpx:= ldx + k * offset[tmpo,0];
   868                 tmpy:= ldy + k * offset[tmpo,1];
   868                 tmpy:= ldy + k * offset[tmpo,1];
   869                 if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK)  = 0)
   869                 if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK)  = 0)
   870                 and (Land[tmpy,tmpx] > TestWord) then
   870                 and (LandGet(tmpy,tmpx) > TestWord) then
   871                     begin
   871                     begin
   872                     ldx:= tmpx;
   872                     ldx:= tmpx;
   873                     ldy:= tmpy;
   873                     ldy:= tmpy;
   874                     isColl:= true;
   874                     isColl:= true;
   875                     break;
   875                     break;
   889             for k:= 3 downto 1 do
   889             for k:= 3 downto 1 do
   890                 begin
   890                 begin
   891                 tmpx:= rdx + k * offset[tmpo,0];
   891                 tmpx:= rdx + k * offset[tmpo,0];
   892                 tmpy:= rdy + k * offset[tmpo,1];
   892                 tmpy:= rdy + k * offset[tmpo,1];
   893                 if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK)  = 0)
   893                 if (((tmpy) and LAND_HEIGHT_MASK) = 0) and (((tmpx) and LAND_WIDTH_MASK)  = 0)
   894                 and (Land[tmpy,tmpx] > TestWord) then
   894                 and (LandGet(tmpy,tmpx) > TestWord) then
   895                     begin
   895                     begin
   896                     rdx:= tmpx;
   896                     rdx:= tmpx;
   897                     rdy:= tmpy;
   897                     rdy:= tmpy;
   898                     isColl:= true;
   898                     isColl:= true;
   899                     break;
   899                     break;
   932         begin
   932         begin
   933         x:= hwRound(Gear^.X) - Gear^.Radius + 1;
   933         x:= hwRound(Gear^.X) - Gear^.Radius + 1;
   934         i:= x + Gear^.Radius * 2 - 2;
   934         i:= x + Gear^.Radius * 2 - 2;
   935         repeat
   935         repeat
   936         if (x and LAND_WIDTH_MASK) = 0 then
   936         if (x and LAND_WIDTH_MASK) = 0 then
   937             if Land[y, x] <> 0 then
   937             if LandGet(y, x) <> 0 then
   938                 if (not isColl) or (abs(x-gx) < abs(collX-gx)) then
   938                 if (not isColl) or (abs(x-gx) < abs(collX-gx)) then
   939                     begin
   939                     begin
   940                     isColl:= true;
   940                     isColl:= true;
   941                     collX := x;
   941                     collX := x;
   942                     end;
   942                     end;
   955         begin
   955         begin
   956         y:= hwRound(Gear^.Y) - Gear^.Radius + 1;
   956         y:= hwRound(Gear^.Y) - Gear^.Radius + 1;
   957         i:= y + Gear^.Radius * 2 - 2;
   957         i:= y + Gear^.Radius * 2 - 2;
   958         repeat
   958         repeat
   959         if (y and LAND_HEIGHT_MASK) = 0 then
   959         if (y and LAND_HEIGHT_MASK) = 0 then
   960             if Land[y, x] <> 0 then
   960             if LandGet(y, x) <> 0 then
   961                 if (not isColl) or (abs(y-gy) < abs(collY-gy)) then
   961                 if (not isColl) or (abs(y-gy) < abs(collY-gy)) then
   962                     begin
   962                     begin
   963                     isColl:= true;
   963                     isColl:= true;
   964                     collY := y;
   964                     collY := y;
   965                     end;
   965                     end;
  1024     begin
  1024     begin
  1025     x:= hwRound(Gear^.X) - Gear^.Radius + 1;
  1025     x:= hwRound(Gear^.X) - Gear^.Radius + 1;
  1026     i:= x + Gear^.Radius * 2 - 2;
  1026     i:= x + Gear^.Radius * 2 - 2;
  1027     repeat
  1027     repeat
  1028     if (x and LAND_WIDTH_MASK) = 0 then
  1028     if (x and LAND_WIDTH_MASK) = 0 then
  1029         if (Land[y, x] and lfLandMask) <> 0 then
  1029         if (LandGet(y, x) and lfLandMask) <> 0 then
  1030             if (not isColl) or (abs(x-gx) < abs(collX-gx)) then
  1030             if (not isColl) or (abs(x-gx) < abs(collX-gx)) then
  1031                 begin
  1031                 begin
  1032                 isColl:= true;
  1032                 isColl:= true;
  1033                 collX := x;
  1033                 collX := x;
  1034                 end;
  1034                 end;