36 procedure AddCI(Gear: PGear); |
36 procedure AddCI(Gear: PGear); |
37 procedure DeleteCI(Gear: PGear); |
37 procedure DeleteCI(Gear: PGear); |
38 |
38 |
39 function CheckGearsCollision(Gear: PGear): PGearArray; |
39 function CheckGearsCollision(Gear: PGear): PGearArray; |
40 |
40 |
41 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): boolean; |
41 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): Word; |
42 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
42 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
43 |
43 |
44 function TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean; |
44 function TestCollisionXKick(Gear: PGear; Dir: LongInt): Word; |
45 function TestCollisionYKick(Gear: PGear; Dir: LongInt): boolean; |
45 function TestCollisionYKick(Gear: PGear; Dir: LongInt): Word; |
46 |
46 |
47 function TestCollisionX(Gear: PGear; Dir: LongInt): boolean; |
47 function TestCollisionX(Gear: PGear; Dir: LongInt): Word; |
48 function TestCollisionY(Gear: PGear; Dir: LongInt): boolean; |
48 function TestCollisionY(Gear: PGear; Dir: LongInt): Word; |
49 |
49 |
50 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): boolean; inline; |
50 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): Word; inline; |
51 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean; |
51 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; |
52 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): boolean; inline; |
52 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): Word; inline; |
53 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean; |
53 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; |
54 |
54 |
55 function TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; |
55 function TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; |
56 |
56 |
57 // returns: negative sign if going downhill to left, value is steepness (noslope/error = _0, 45° = _0_5) |
57 // returns: negative sign if going downhill to left, value is steepness (noslope/error = _0, 45° = _0_5) |
58 function CalcSlopeBelowGear(Gear: PGear): hwFloat; |
58 function CalcSlopeBelowGear(Gear: PGear): hwFloat; |
59 function CalcSlopeNearGear(Gear: PGear; dirX, dirY: LongInt): hwFloat; |
59 function CalcSlopeNearGear(Gear: PGear; dirX, dirY: LongInt): hwFloat; |
60 function CalcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): Boolean; |
60 function CalcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): boolean; |
61 |
61 |
62 implementation |
62 implementation |
63 uses uConsts, uLandGraphics, uVariables, uDebug, uGearsList; |
63 uses uConsts, uLandGraphics, uVariables, uDebug, uGearsList; |
64 |
64 |
65 type TCollisionEntry = record |
65 type TCollisionEntry = record |
148 if Dir < 0 then |
148 if Dir < 0 then |
149 x:= x - Gear^.Radius |
149 x:= x - Gear^.Radius |
150 else |
150 else |
151 x:= x + Gear^.Radius; |
151 x:= x + Gear^.Radius; |
152 |
152 |
153 TestCollisionXwithGear:= true; |
|
154 if (x and LAND_WIDTH_MASK) = 0 then |
153 if (x and LAND_WIDTH_MASK) = 0 then |
155 begin |
154 begin |
156 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
155 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
157 i:= y + Gear^.Radius * 2 - 2; |
156 i:= y + Gear^.Radius * 2 - 2; |
158 repeat |
157 repeat |
159 if (y and LAND_HEIGHT_MASK) = 0 then |
158 if (y and LAND_HEIGHT_MASK) = 0 then |
160 if Land[y, x] and Gear^.CollisionMask <> 0 then |
159 if Land[y, x] and Gear^.CollisionMask <> 0 then |
161 exit; |
160 exit(Land[y, x]); |
162 inc(y) |
161 inc(y) |
163 until (y > i); |
162 until (y > i); |
164 end; |
163 end; |
165 TestCollisionXwithGear:= false |
164 TestCollisionXwithGear:= 0 |
166 end; |
165 end; |
167 |
166 |
168 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
167 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
169 var x, y, i: LongInt; |
168 var x, y, i: LongInt; |
170 begin |
169 begin |
187 repeat |
186 repeat |
188 if (x and LAND_WIDTH_MASK) = 0 then |
187 if (x and LAND_WIDTH_MASK) = 0 then |
189 if Land[y, x] and Gear^.CollisionMask <> 0 then |
188 if Land[y, x] and Gear^.CollisionMask <> 0 then |
190 begin |
189 begin |
191 TestCollisionYwithGear:= Land[y, x]; |
190 TestCollisionYwithGear:= Land[y, x]; |
192 exit; |
191 exit(Land[y, x]); |
193 end; |
192 end; |
194 inc(x) |
193 inc(x) |
195 until (x > i); |
194 until (x > i); |
196 end; |
195 end; |
197 TestCollisionYwithGear:= 0 |
196 TestCollisionYwithGear:= 0 |
198 end; |
197 end; |
199 |
198 |
200 function TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean; |
199 function TestCollisionXKick(Gear: PGear; Dir: LongInt): Word; |
201 var x, y, mx, my, i: LongInt; |
200 var x, y, mx, my, i: LongInt; |
202 flag: boolean; |
201 pixel: Word; |
203 begin |
202 begin |
204 flag:= false; |
203 pixel:= 0; |
205 x:= hwRound(Gear^.X); |
204 x:= hwRound(Gear^.X); |
206 if Dir < 0 then |
205 if Dir < 0 then |
207 x:= x - Gear^.Radius |
206 x:= x - Gear^.Radius |
208 else |
207 else |
209 x:= x + Gear^.Radius; |
208 x:= x + Gear^.Radius; |
210 |
209 |
211 TestCollisionXKick:= true; |
|
212 if (x and LAND_WIDTH_MASK) = 0 then |
210 if (x and LAND_WIDTH_MASK) = 0 then |
213 begin |
211 begin |
214 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
212 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
215 i:= y + Gear^.Radius * 2 - 2; |
213 i:= y + Gear^.Radius * 2 - 2; |
216 repeat |
214 repeat |
217 if (y and LAND_HEIGHT_MASK) = 0 then |
215 if (y and LAND_HEIGHT_MASK) = 0 then |
218 if Land[y, x] > 255 then |
216 if Land[y, x] > 255 then |
219 exit |
217 exit(Land[y, x]) |
220 else if Land[y, x] <> 0 then |
218 else if Land[y, x] <> 0 then |
221 flag:= true; |
219 pixel:= Land[y, x]; |
222 inc(y) |
220 inc(y) |
223 until (y > i); |
221 until (y > i); |
224 end; |
222 end; |
225 TestCollisionXKick:= flag; |
223 TestCollisionXKick:= pixel; |
226 |
224 |
227 if flag then |
225 if pixel <> 0 then |
228 begin |
226 begin |
229 if hwAbs(Gear^.dX) < cHHKick then |
227 if hwAbs(Gear^.dX) < cHHKick then |
230 exit; |
228 exit; |
231 if (Gear^.State and gstHHJumping <> 0) |
229 if (Gear^.State and gstHHJumping <> 0) |
232 and (hwAbs(Gear^.dX) < _0_4) then |
230 and (hwAbs(Gear^.dX) < _0_4) then |
253 State:= State or gstMoving; |
251 State:= State or gstMoving; |
254 if Kind = gtKnife then State:= State and (not gstCollision); |
252 if Kind = gtKnife then State:= State and (not gstCollision); |
255 Active:= true |
253 Active:= true |
256 end; |
254 end; |
257 DeleteCI(cGear); |
255 DeleteCI(cGear); |
258 TestCollisionXKick:= false; |
256 exit(0); |
259 exit; |
|
260 end |
257 end |
261 end |
258 end |
262 end; |
259 end; |
263 |
260 |
264 function TestCollisionYKick(Gear: PGear; Dir: LongInt): boolean; |
261 function TestCollisionYKick(Gear: PGear; Dir: LongInt): Word; |
265 var x, y, mx, my, myr, i: LongInt; |
262 var x, y, mx, my, myr, i: LongInt; |
266 flag: boolean; |
263 pixel: Word; |
267 begin |
264 begin |
268 flag:= false; |
265 pixel:= 0; |
269 y:= hwRound(Gear^.Y); |
266 y:= hwRound(Gear^.Y); |
270 if Dir < 0 then |
267 if Dir < 0 then |
271 y:= y - Gear^.Radius |
268 y:= y - Gear^.Radius |
272 else |
269 else |
273 y:= y + Gear^.Radius; |
270 y:= y + Gear^.Radius; |
274 |
271 |
275 TestCollisionYKick:= true; |
|
276 if (y and LAND_HEIGHT_MASK) = 0 then |
272 if (y and LAND_HEIGHT_MASK) = 0 then |
277 begin |
273 begin |
278 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
274 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
279 i:= x + Gear^.Radius * 2 - 2; |
275 i:= x + Gear^.Radius * 2 - 2; |
280 repeat |
276 repeat |
281 if (x and LAND_WIDTH_MASK) = 0 then |
277 if (x and LAND_WIDTH_MASK) = 0 then |
282 if Land[y, x] > 0 then |
278 if Land[y, x] > 0 then |
283 if Land[y, x] > 255 then |
279 if Land[y, x] > 255 then |
284 exit |
280 exit(Land[y, x]) |
285 else if Land[y, x] <> 0 then |
281 else if Land[y, x] <> 0 then |
286 flag:= true; |
282 pixel:= Land[y, x]; |
287 inc(x) |
283 inc(x) |
288 until (x > i); |
284 until (x > i); |
289 end; |
285 end; |
290 TestCollisionYKick:= flag; |
286 TestCollisionYKick:= pixel; |
291 |
287 |
292 if flag then |
288 if pixel <> 0 then |
293 begin |
289 begin |
294 if hwAbs(Gear^.dY) < cHHKick then |
290 if hwAbs(Gear^.dY) < cHHKick then |
295 exit; |
291 exit; |
296 if (Gear^.State and gstHHJumping <> 0) and (not Gear^.dY.isNegative) and (Gear^.dY < _0_4) then |
292 if (Gear^.State and gstHHJumping <> 0) and (not Gear^.dY.isNegative) and (Gear^.dY < _0_4) then |
297 exit; |
293 exit; |
316 State:= State or gstMoving; |
312 State:= State or gstMoving; |
317 if Kind = gtKnife then State:= State and (not gstCollision); |
313 if Kind = gtKnife then State:= State and (not gstCollision); |
318 Active:= true |
314 Active:= true |
319 end; |
315 end; |
320 DeleteCI(cGear); |
316 DeleteCI(cGear); |
321 TestCollisionYKick:= false; |
317 exit(0) |
322 exit |
|
323 end |
318 end |
324 end |
319 end |
325 end; |
320 end; |
326 |
321 |
327 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): boolean; inline; |
322 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): Word; inline; |
328 begin |
323 begin |
329 TestCollisionXwithXYShift:= TestCollisionXwithXYShift(Gear, ShiftX, ShiftY, Dir, true); |
324 TestCollisionXwithXYShift:= TestCollisionXwithXYShift(Gear, ShiftX, ShiftY, Dir, true); |
330 end; |
325 end; |
331 |
326 |
332 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean; |
327 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; |
333 begin |
328 begin |
334 Gear^.X:= Gear^.X + ShiftX; |
329 Gear^.X:= Gear^.X + ShiftX; |
335 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY); |
330 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY); |
336 if withGear then |
331 if withGear then |
337 TestCollisionXwithXYShift:= TestCollisionXwithGear(Gear, Dir) |
332 TestCollisionXwithXYShift:= TestCollisionXwithGear(Gear, Dir) |
338 else TestCollisionXwithXYShift:= TestCollisionX(Gear, Dir); |
333 else TestCollisionXwithXYShift:= TestCollisionX(Gear, Dir); |
339 Gear^.X:= Gear^.X - ShiftX; |
334 Gear^.X:= Gear^.X - ShiftX; |
340 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY) |
335 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY) |
341 end; |
336 end; |
342 |
337 |
343 function TestCollisionX(Gear: PGear; Dir: LongInt): boolean; |
338 function TestCollisionX(Gear: PGear; Dir: LongInt): Word; |
344 var x, y, i: LongInt; |
339 var x, y, i: LongInt; |
345 begin |
340 begin |
346 x:= hwRound(Gear^.X); |
341 x:= hwRound(Gear^.X); |
347 if Dir < 0 then |
342 if Dir < 0 then |
348 x:= x - Gear^.Radius |
343 x:= x - Gear^.Radius |
349 else |
344 else |
350 x:= x + Gear^.Radius; |
345 x:= x + Gear^.Radius; |
351 |
346 |
352 TestCollisionX:= true; |
|
353 if (x and LAND_WIDTH_MASK) = 0 then |
347 if (x and LAND_WIDTH_MASK) = 0 then |
354 begin |
348 begin |
355 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
349 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
356 i:= y + Gear^.Radius * 2 - 2; |
350 i:= y + Gear^.Radius * 2 - 2; |
357 repeat |
351 repeat |
358 if (y and LAND_HEIGHT_MASK) = 0 then |
352 if (y and LAND_HEIGHT_MASK) = 0 then |
359 if Land[y, x] > 255 then |
353 if Land[y, x] > 255 then |
360 exit; |
354 exit(Land[y, x]); |
361 inc(y) |
355 inc(y) |
362 until (y > i); |
356 until (y > i); |
363 end; |
357 end; |
364 TestCollisionX:= false |
358 TestCollisionX:= 0 |
365 end; |
359 end; |
366 |
360 |
367 function TestCollisionY(Gear: PGear; Dir: LongInt): boolean; |
361 function TestCollisionY(Gear: PGear; Dir: LongInt): Word; |
368 var x, y, i: LongInt; |
362 var x, y, i: LongInt; |
369 begin |
363 begin |
370 y:= hwRound(Gear^.Y); |
364 y:= hwRound(Gear^.Y); |
371 if Dir < 0 then |
365 if Dir < 0 then |
372 y:= y - Gear^.Radius |
366 y:= y - Gear^.Radius |
373 else |
367 else |
374 y:= y + Gear^.Radius; |
368 y:= y + Gear^.Radius; |
375 |
369 |
376 TestCollisionY:= true; |
|
377 if (y and LAND_HEIGHT_MASK) = 0 then |
370 if (y and LAND_HEIGHT_MASK) = 0 then |
378 begin |
371 begin |
379 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
372 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
380 i:= x + Gear^.Radius * 2 - 2; |
373 i:= x + Gear^.Radius * 2 - 2; |
381 repeat |
374 repeat |
382 if (x and LAND_WIDTH_MASK) = 0 then |
375 if (x and LAND_WIDTH_MASK) = 0 then |
383 if Land[y, x] > 255 then |
376 if Land[y, x] > 255 then |
384 exit; |
377 exit(Land[y, x]); |
385 inc(x) |
378 inc(x) |
386 until (x > i); |
379 until (x > i); |
387 end; |
380 end; |
388 TestCollisionY:= false |
381 TestCollisionY:= 0 |
389 end; |
382 end; |
390 |
383 |
391 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): boolean; inline; |
384 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): Word; inline; |
392 begin |
385 begin |
393 TestCollisionYwithXYShift:= TestCollisionYwithXYShift(Gear, ShiftX, ShiftY, Dir, true); |
386 TestCollisionYwithXYShift:= TestCollisionYwithXYShift(Gear, ShiftX, ShiftY, Dir, true); |
394 end; |
387 end; |
395 |
388 |
396 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean; |
389 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; |
397 begin |
390 begin |
398 Gear^.X:= Gear^.X + int2hwFloat(ShiftX); |
391 Gear^.X:= Gear^.X + int2hwFloat(ShiftX); |
399 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY); |
392 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY); |
400 |
393 |
401 if withGear then |
394 if withGear then |
402 TestCollisionYwithXYShift:= TestCollisionYwithGear(Gear, Dir) <> 0 |
395 TestCollisionYwithXYShift:= TestCollisionYwithGear(Gear, Dir) |
403 else |
396 else |
404 TestCollisionYwithXYShift:= TestCollisionY(Gear, Dir); |
397 TestCollisionYwithXYShift:= TestCollisionY(Gear, Dir); |
405 |
398 |
406 Gear^.X:= Gear^.X - int2hwFloat(ShiftX); |
399 Gear^.X:= Gear^.X - int2hwFloat(ShiftX); |
407 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY) |
400 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY) |