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; |
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); |
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); |
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; |