22 interface |
22 interface |
23 uses uFloat, uTypes, uUtils; |
23 uses uFloat, uTypes, uUtils; |
24 |
24 |
25 const cMaxGearArrayInd = 1023; |
25 const cMaxGearArrayInd = 1023; |
26 const cMaxGearHitOrderInd = 1023; |
26 const cMaxGearHitOrderInd = 1023; |
|
27 const cMaxGearProximityCacheInd = 1023; |
27 |
28 |
28 type PGearArray = ^TGearArray; |
29 type PGearArray = ^TGearArray; |
29 TGearArray = record |
30 TGearArray = record |
30 ar: array[0..cMaxGearArrayInd] of PGear; |
31 ar: array[0..cMaxGearArrayInd] of PGear; |
31 cX: array[0..cMaxGearArrayInd] of LongInt; |
32 cX: array[0..cMaxGearArrayInd] of LongInt; |
38 ar: array[0..cMaxGearHitOrderInd] of PGear; |
39 ar: array[0..cMaxGearHitOrderInd] of PGear; |
39 order: array[0..cMaxGearHitOrderInd] of LongInt; |
40 order: array[0..cMaxGearHitOrderInd] of LongInt; |
40 Count: Longword |
41 Count: Longword |
41 end; |
42 end; |
42 |
43 |
|
44 type PGearProximityCache = ^TGearProximityCache; |
|
45 TGearProximityCache = record |
|
46 ar: array[0..cMaxGearProximityCacheInd] of PGear; |
|
47 Count: Longword |
|
48 end; |
|
49 |
43 type TLineCollision = record |
50 type TLineCollision = record |
44 hasCollision: Boolean; |
51 hasCollision: Boolean; |
45 cX, cY: LongInt; //for visual effects only |
52 cX, cY: LongInt; //for visual effects only |
46 end; |
53 end; |
47 |
54 |
51 procedure AddCI(Gear: PGear); |
58 procedure AddCI(Gear: PGear); |
52 procedure DeleteCI(Gear: PGear); |
59 procedure DeleteCI(Gear: PGear); |
53 |
60 |
54 function CheckGearsCollision(Gear: PGear): PGearArray; |
61 function CheckGearsCollision(Gear: PGear): PGearArray; |
55 function CheckAllGearsCollision(SourceGear: PGear): PGearArray; |
62 function CheckAllGearsCollision(SourceGear: PGear): PGearArray; |
|
63 function CheckCacheCollision(SourceGear: PGear): PGearArray; |
56 |
64 |
57 function CheckGearsLineCollision(Gear: PGear; oX, oY, tX, tY: hwFloat): PGearArray; |
65 function CheckGearsLineCollision(Gear: PGear; oX, oY, tX, tY: hwFloat): PGearArray; |
58 function CheckAllGearsLineCollision(SourceGear: PGear; oX, oY, tX, tY: hwFloat): PGearArray; |
66 function CheckAllGearsLineCollision(SourceGear: PGear; oX, oY, tX, tY: hwFloat): PGearArray; |
59 |
67 |
60 function UpdateHitOrder(Gear: PGear; Order: LongInt): boolean; |
68 function UpdateHitOrder(Gear: PGear; Order: LongInt): boolean; |
61 procedure ClearHitOrderLeq(MinOrder: LongInt); |
69 procedure ClearHitOrderLeq(MinOrder: LongInt); |
62 procedure ClearHitOrder(); |
70 procedure ClearHitOrder(); |
|
71 |
|
72 procedure RefillProximityCache(SourceGear: PGear; radius: LongInt); |
|
73 procedure RemoveFromProximityCache(Gear: PGear); |
|
74 procedure ClearProximityCache(); |
63 |
75 |
64 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word; |
76 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word; |
65 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
77 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
66 |
78 |
67 function TestCollisionXKick(Gear: PGear; Dir: LongInt): Word; |
79 function TestCollisionXKick(Gear: PGear; Dir: LongInt): Word; |
95 const MAXRECTSINDEX = 1023; |
107 const MAXRECTSINDEX = 1023; |
96 var Count: Longword; |
108 var Count: Longword; |
97 cinfos: array[0..MAXRECTSINDEX] of TCollisionEntry; |
109 cinfos: array[0..MAXRECTSINDEX] of TCollisionEntry; |
98 ga: TGearArray; |
110 ga: TGearArray; |
99 ordera: TGearHitOrder; |
111 ordera: TGearHitOrder; |
|
112 proximitya: TGearProximityCache; |
100 |
113 |
101 procedure AddCI(Gear: PGear); |
114 procedure AddCI(Gear: PGear); |
102 begin |
115 begin |
103 if (Gear^.CollisionIndex >= 0) or (Count > MAXRECTSINDEX) or |
116 if (Gear^.CollisionIndex >= 0) or (Count > MAXRECTSINDEX) or |
104 ((Count > MAXRECTSINDEX-200) and ((Gear^.Kind = gtMine) or (Gear^.Kind = gtSMine) or (Gear^.Kind = gtKnife))) then |
117 ((Count > MAXRECTSINDEX-200) and ((Gear^.Kind = gtMine) or (Gear^.Kind = gtSMine) or (Gear^.Kind = gtKnife))) then |
178 begin |
191 begin |
179 if (Gear <> SourceGear) and |
192 if (Gear <> SourceGear) and |
180 (sqr(mx - hwRound(Gear^.x)) + sqr(my - hwRound(Gear^.y)) <= sqr(Gear^.Radius + tr))then |
193 (sqr(mx - hwRound(Gear^.x)) + sqr(my - hwRound(Gear^.y)) <= sqr(Gear^.Radius + tr))then |
181 begin |
194 begin |
182 ga.ar[ga.Count]:= Gear; |
195 ga.ar[ga.Count]:= Gear; |
183 ga.cX[ga.Count]:= hwround(SourceGear^.X); |
196 ga.cX[ga.Count]:= mx; |
184 ga.cY[ga.Count]:= hwround(SourceGear^.Y); |
197 ga.cY[ga.Count]:= my; |
185 inc(ga.Count) |
198 inc(ga.Count) |
186 end; |
199 end; |
187 |
200 |
188 Gear := Gear^.NextGear |
201 Gear := Gear^.NextGear |
189 end; |
202 end; |
285 end; |
298 end; |
286 Gear := Gear^.NextGear |
299 Gear := Gear^.NextGear |
287 end; |
300 end; |
288 end; |
301 end; |
289 |
302 |
|
303 function CheckCacheCollision(SourceGear: PGear): PGearArray; |
|
304 var mx, my, tr, i: LongInt; |
|
305 Gear: PGear; |
|
306 begin |
|
307 CheckCacheCollision:= @ga; |
|
308 ga.Count:= 0; |
|
309 |
|
310 mx:= hwRound(SourceGear^.X); |
|
311 my:= hwRound(SourceGear^.Y); |
|
312 |
|
313 tr:= SourceGear^.Radius + 2; |
|
314 |
|
315 for i:= 0 to proximitya.Count - 1 do |
|
316 begin |
|
317 Gear:= proximitya.ar[i]; |
|
318 // Assuming the cache has been filled correctly, it will not contain SourceGear |
|
319 // and other gears won't be far enough for sqr overflow |
|
320 if (sqr(mx - hwRound(Gear^.X)) + sqr(my - hwRound(Gear^.Y)) <= sqr(Gear^.Radius + tr)) then |
|
321 begin |
|
322 ga.ar[ga.Count]:= Gear; |
|
323 ga.cX[ga.Count]:= mx; |
|
324 ga.cY[ga.Count]:= my; |
|
325 inc(ga.Count) |
|
326 end; |
|
327 end; |
|
328 end; |
|
329 |
290 function UpdateHitOrder(Gear: PGear; Order: LongInt): boolean; |
330 function UpdateHitOrder(Gear: PGear; Order: LongInt): boolean; |
291 var i: LongInt; |
331 var i: LongInt; |
292 begin |
332 begin |
293 UpdateHitOrder:= true; |
333 UpdateHitOrder:= true; |
294 for i:= 0 to ordera.Count - 1 do |
334 for i:= 0 to ordera.Count - 1 do |
333 end; |
373 end; |
334 |
374 |
335 procedure ClearHitOrder(); |
375 procedure ClearHitOrder(); |
336 begin |
376 begin |
337 ordera.Count:= 0; |
377 ordera.Count:= 0; |
|
378 end; |
|
379 |
|
380 procedure RefillProximityCache(SourceGear: PGear; radius: LongInt); |
|
381 var cx, cy, dx, dy, r: LongInt; |
|
382 Gear: PGear; |
|
383 begin |
|
384 proximitya.Count:= 0; |
|
385 cx:= hwRound(SourceGear^.X); |
|
386 cy:= hwRound(SourceGear^.Y); |
|
387 Gear:= GearsList; |
|
388 |
|
389 while (Gear <> nil) and (proximitya.Count <= cMaxGearProximityCacheInd) do |
|
390 begin |
|
391 dx:= abs(hwRound(Gear^.X) - cx); |
|
392 dy:= abs(hwRound(Gear^.Y) - cy); |
|
393 r:= radius + Gear^.radius + 2; |
|
394 if (Gear <> SourceGear) and (max(dx, dy) <= r) and (sqr(dx) + sqr(dy) <= sqr(r)) then |
|
395 begin |
|
396 proximitya.ar[proximitya.Count]:= Gear; |
|
397 inc(proximitya.Count) |
|
398 end; |
|
399 Gear := Gear^.NextGear |
|
400 end; |
|
401 end; |
|
402 |
|
403 procedure RemoveFromProximityCache(Gear: PGear); |
|
404 var i: LongInt; |
|
405 begin |
|
406 i := 0; |
|
407 while i < proximitya.Count do |
|
408 begin |
|
409 if proximitya.ar[i] = Gear then |
|
410 begin |
|
411 proximitya.ar[i]:= proximitya.ar[proximitya.Count - 1]; |
|
412 dec(proximitya.Count); |
|
413 end |
|
414 else |
|
415 inc(i); |
|
416 end; |
|
417 end; |
|
418 |
|
419 procedure ClearProximityCache(); |
|
420 begin |
|
421 proximitya.Count:= 0; |
338 end; |
422 end; |
339 |
423 |
340 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word; |
424 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word; |
341 var x, y, i: LongInt; |
425 var x, y, i: LongInt; |
342 begin |
426 begin |