132 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): boolean; |
135 function TestCollisionXwithGear(Gear: PGear; Dir: LongInt): boolean; |
133 var x, y, i: LongInt; |
136 var x, y, i: LongInt; |
134 TestWord: LongWord; |
137 TestWord: LongWord; |
135 begin |
138 begin |
136 if Gear^.IntersectGear <> nil then |
139 if Gear^.IntersectGear <> nil then |
137 with Gear^ do |
140 with Gear^ do |
138 if (hwRound(IntersectGear^.X) + IntersectGear^.Radius < hwRound(X) - Radius) or |
141 if (hwRound(IntersectGear^.X) + IntersectGear^.Radius < hwRound(X) - Radius) |
139 (hwRound(IntersectGear^.X) - IntersectGear^.Radius > hwRound(X) + Radius) then |
142 or (hwRound(IntersectGear^.X) - IntersectGear^.Radius > hwRound(X) + Radius) then |
140 begin |
143 begin |
141 IntersectGear:= nil; |
144 IntersectGear:= nil; |
142 TestWord:= 0 |
145 TestWord:= 0 |
143 end else |
146 end |
144 TestWord:= 255 |
147 else |
145 else TestWord:= 0; |
148 TestWord:= 255 |
|
149 else TestWord:= 0; |
146 |
150 |
147 x:= hwRound(Gear^.X); |
151 x:= hwRound(Gear^.X); |
148 if Dir < 0 then x:= x - Gear^.Radius |
152 if Dir < 0 then |
149 else x:= x + Gear^.Radius; |
153 x:= x - Gear^.Radius |
|
154 else |
|
155 x:= x + Gear^.Radius; |
150 if (x and LAND_WIDTH_MASK) = 0 then |
156 if (x and LAND_WIDTH_MASK) = 0 then |
151 begin |
157 begin |
152 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
158 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
153 i:= y + Gear^.Radius * 2 - 2; |
159 i:= y + Gear^.Radius * 2 - 2; |
154 repeat |
160 repeat |
155 if (y and LAND_HEIGHT_MASK) = 0 then |
161 if (y and LAND_HEIGHT_MASK) = 0 then |
156 if Land[y, x] > TestWord then exit(true); |
162 if Land[y, x] > TestWord then |
157 inc(y) |
163 exit(true); |
158 until (y > i); |
164 inc(y) |
159 end; |
165 until (y > i); |
|
166 end; |
160 TestCollisionXwithGear:= false |
167 TestCollisionXwithGear:= false |
161 end; |
168 end; |
162 |
169 |
163 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
170 function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word; |
164 var x, y, i: LongInt; |
171 var x, y, i: LongInt; |
165 TestWord: LongWord; |
172 TestWord: LongWord; |
166 begin |
173 begin |
167 if Gear^.IntersectGear <> nil then |
174 if Gear^.IntersectGear <> nil then |
168 with Gear^ do |
175 with Gear^ do |
169 if (hwRound(IntersectGear^.Y) + IntersectGear^.Radius < hwRound(Y) - Radius) or |
176 if (hwRound(IntersectGear^.Y) + IntersectGear^.Radius < hwRound(Y) - Radius) or |
170 (hwRound(IntersectGear^.Y) - IntersectGear^.Radius > hwRound(Y) + Radius) then |
177 (hwRound(IntersectGear^.Y) - IntersectGear^.Radius > hwRound(Y) + Radius) then |
171 begin |
178 begin |
172 IntersectGear:= nil; |
179 IntersectGear:= nil; |
173 TestWord:= 0 |
180 TestWord:= 0 |
174 end else |
181 end |
175 TestWord:= 255 |
182 else |
176 else TestWord:= 0; |
183 TestWord:= 255 |
|
184 else |
|
185 TestWord:= 0; |
177 |
186 |
178 y:= hwRound(Gear^.Y); |
187 y:= hwRound(Gear^.Y); |
179 if Dir < 0 then y:= y - Gear^.Radius |
188 if Dir < 0 then |
180 else y:= y + Gear^.Radius; |
189 y:= y - Gear^.Radius |
|
190 else |
|
191 y:= y + Gear^.Radius; |
181 if (y and LAND_HEIGHT_MASK) = 0 then |
192 if (y and LAND_HEIGHT_MASK) = 0 then |
182 begin |
193 begin |
183 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
194 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
184 i:= x + Gear^.Radius * 2 - 2; |
195 i:= x + Gear^.Radius * 2 - 2; |
185 repeat |
196 repeat |
186 if (x and LAND_WIDTH_MASK) = 0 then |
197 if (x and LAND_WIDTH_MASK) = 0 then |
187 if Land[y, x] > TestWord then exit(Land[y, x]); |
198 if Land[y, x] > TestWord then |
|
199 exit(Land[y, x]); |
188 inc(x) |
200 inc(x) |
189 until (x > i); |
201 until (x > i); |
190 end; |
202 end; |
191 TestCollisionYwithGear:= 0 |
203 TestCollisionYwithGear:= 0 |
192 end; |
204 end; |
193 |
205 |
194 function TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean; |
206 function TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean; |
195 var x, y, mx, my, i: LongInt; |
207 var x, y, mx, my, i: LongInt; |
196 flag: boolean; |
208 flag: boolean; |
197 begin |
209 begin |
198 flag:= false; |
210 flag:= false; |
199 x:= hwRound(Gear^.X); |
211 x:= hwRound(Gear^.X); |
200 if Dir < 0 then x:= x - Gear^.Radius |
212 if Dir < 0 then |
201 else x:= x + Gear^.Radius; |
213 x:= x - Gear^.Radius |
|
214 else |
|
215 x:= x + Gear^.Radius; |
202 if (x and LAND_WIDTH_MASK) = 0 then |
216 if (x and LAND_WIDTH_MASK) = 0 then |
203 begin |
217 begin |
204 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
218 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
205 i:= y + Gear^.Radius * 2 - 2; |
219 i:= y + Gear^.Radius * 2 - 2; |
206 repeat |
220 repeat |
207 if (y and LAND_HEIGHT_MASK) = 0 then |
221 if (y and LAND_HEIGHT_MASK) = 0 then |
208 if Land[y, x] > 255 then exit(true) |
222 if Land[y, x] > 255 then |
209 else if Land[y, x] <> 0 then flag:= true; |
223 exit(true) |
210 inc(y) |
224 else if Land[y, x] <> 0 then |
211 until (y > i); |
225 flag:= true; |
212 end; |
226 inc(y) |
|
227 until (y > i); |
|
228 end; |
213 TestCollisionXKick:= flag; |
229 TestCollisionXKick:= flag; |
214 |
230 |
215 if flag then |
231 if flag then |
216 begin |
232 begin |
217 if hwAbs(Gear^.dX) < cHHKick then exit; |
233 if hwAbs(Gear^.dX) < cHHKick then |
218 if (Gear^.State and gstHHJumping <> 0) |
234 exit; |
219 and (hwAbs(Gear^.dX) < _0_4) then exit; |
235 if (Gear^.State and gstHHJumping <> 0) |
220 |
236 and (hwAbs(Gear^.dX) < _0_4) then |
221 mx:= hwRound(Gear^.X); |
237 exit; |
222 my:= hwRound(Gear^.Y); |
238 |
223 |
239 mx:= hwRound(Gear^.X); |
224 for i:= 0 to Pred(Count) do |
240 my:= hwRound(Gear^.Y); |
225 with cinfos[i] do |
241 |
226 if (Gear <> cGear) and |
242 for i:= 0 to Pred(Count) do |
227 (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) and |
243 with cinfos[i] do |
228 ((mx > x) xor (Dir > 0)) then |
244 if (Gear <> cGear) and (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) |
229 if ((cGear^.Kind in [gtHedgehog, gtMine]) and ((Gear^.State and gstNotKickable) = 0)) or |
245 and ((mx > x) xor (Dir > 0)) then |
230 // only apply X kick if the barrel is knocked over |
246 if ((cGear^.Kind in [gtHedgehog, gtMine]) and ((Gear^.State and gstNotKickable) = 0)) or |
231 ((cGear^.Kind = gtExplosives) and ((cGear^.State and gsttmpflag) <> 0)) then |
247 // only apply X kick if the barrel is knocked over |
232 begin |
248 ((cGear^.Kind = gtExplosives) and ((cGear^.State and gsttmpflag) <> 0)) then |
233 with cGear^ do |
249 begin |
234 begin |
250 with cGear^ do |
235 dX:= Gear^.dX; |
251 begin |
236 dY:= Gear^.dY * _0_5; |
252 dX:= Gear^.dX; |
237 State:= State or gstMoving; |
253 dY:= Gear^.dY * _0_5; |
238 Active:= true |
254 State:= State or gstMoving; |
239 end; |
255 Active:= true |
240 DeleteCI(cGear); |
256 end; |
241 exit(false) |
257 DeleteCI(cGear); |
242 end |
258 exit(false) |
243 end |
259 end |
|
260 end |
244 end; |
261 end; |
245 |
262 |
246 function TestCollisionYKick(Gear: PGear; Dir: LongInt): boolean; |
263 function TestCollisionYKick(Gear: PGear; Dir: LongInt): boolean; |
247 var x, y, mx, my, i: LongInt; |
264 var x, y, mx, my, i: LongInt; |
248 flag: boolean; |
265 flag: boolean; |
249 begin |
266 begin |
250 flag:= false; |
267 flag:= false; |
251 y:= hwRound(Gear^.Y); |
268 y:= hwRound(Gear^.Y); |
252 if Dir < 0 then y:= y - Gear^.Radius |
269 if Dir < 0 then |
253 else y:= y + Gear^.Radius; |
270 y:= y - Gear^.Radius |
|
271 else |
|
272 y:= y + Gear^.Radius; |
254 if (y and LAND_HEIGHT_MASK) = 0 then |
273 if (y and LAND_HEIGHT_MASK) = 0 then |
255 begin |
274 begin |
256 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
275 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
257 i:= x + Gear^.Radius * 2 - 2; |
276 i:= x + Gear^.Radius * 2 - 2; |
258 repeat |
277 repeat |
259 if (x and LAND_WIDTH_MASK) = 0 then |
278 if (x and LAND_WIDTH_MASK) = 0 then |
260 if Land[y, x] > 0 then |
279 if Land[y, x] > 0 then |
261 if Land[y, x] > 255 then exit(true) |
280 if Land[y, x] > 255 then |
262 else if Land[y, x] <> 0 then flag:= true; |
281 exit(true) |
263 inc(x) |
282 else if Land[y, x] <> 0 then |
264 until (x > i); |
283 flag:= true; |
265 end; |
284 inc(x) |
|
285 until (x > i); |
|
286 end; |
266 TestCollisionYKick:= flag; |
287 TestCollisionYKick:= flag; |
267 |
288 |
268 if flag then |
289 if flag then |
269 begin |
290 begin |
270 if hwAbs(Gear^.dY) < cHHKick then exit(true); |
291 if hwAbs(Gear^.dY) < cHHKick then |
271 if (Gear^.State and gstHHJumping <> 0) |
292 exit(true); |
272 and (not Gear^.dY.isNegative) |
293 if (Gear^.State and gstHHJumping <> 0) |
273 and (Gear^.dY < _0_4) then exit; |
294 and (not Gear^.dY.isNegative) |
274 |
295 and (Gear^.dY < _0_4) then |
275 mx:= hwRound(Gear^.X); |
296 exit; |
276 my:= hwRound(Gear^.Y); |
297 |
277 |
298 mx:= hwRound(Gear^.X); |
278 for i:= 0 to Pred(Count) do |
299 my:= hwRound(Gear^.Y); |
279 with cinfos[i] do |
300 |
280 if (Gear <> cGear) and |
301 for i:= 0 to Pred(Count) do |
281 (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) and |
302 with cinfos[i] do |
282 ((my > y) xor (Dir > 0)) then |
303 if (Gear <> cGear) and (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) |
283 if (cGear^.Kind in [gtHedgehog, gtMine, gtExplosives]) and ((Gear^.State and gstNotKickable) = 0) then |
304 and ((my > y) xor (Dir > 0)) then |
284 begin |
305 if (cGear^.Kind in [gtHedgehog, gtMine, gtExplosives]) and ((Gear^.State and gstNotKickable) = 0) then |
285 with cGear^ do |
306 begin |
286 begin |
307 with cGear^ do |
287 if (Kind <> gtExplosives) or ((State and gsttmpflag) <> 0) then dX:= Gear^.dX * _0_5; |
308 begin |
288 dY:= Gear^.dY; |
309 if (Kind <> gtExplosives) or ((State and gsttmpflag) <> 0) then |
289 State:= State or gstMoving; |
310 dX:= Gear^.dX * _0_5; |
290 Active:= true |
311 dY:= Gear^.dY; |
291 end; |
312 State:= State or gstMoving; |
292 DeleteCI(cGear); |
313 Active:= true |
293 exit(false) |
314 end; |
294 end |
315 DeleteCI(cGear); |
295 end |
316 exit(false) |
|
317 end |
|
318 end |
296 end; |
319 end; |
297 |
320 |
298 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean; |
321 function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean; |
299 begin |
322 begin |
300 Gear^.X:= Gear^.X + ShiftX; |
323 Gear^.X:= Gear^.X + ShiftX; |
307 end; |
330 end; |
308 function TestCollisionX(Gear: PGear; Dir: LongInt): boolean; |
331 function TestCollisionX(Gear: PGear; Dir: LongInt): boolean; |
309 var x, y, i: LongInt; |
332 var x, y, i: LongInt; |
310 begin |
333 begin |
311 x:= hwRound(Gear^.X); |
334 x:= hwRound(Gear^.X); |
312 if Dir < 0 then x:= x - Gear^.Radius |
335 if Dir < 0 then |
313 else x:= x + Gear^.Radius; |
336 x:= x - Gear^.Radius |
|
337 else |
|
338 x:= x + Gear^.Radius; |
314 if (x and LAND_WIDTH_MASK) = 0 then |
339 if (x and LAND_WIDTH_MASK) = 0 then |
315 begin |
340 begin |
316 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
341 y:= hwRound(Gear^.Y) - Gear^.Radius + 1; |
317 i:= y + Gear^.Radius * 2 - 2; |
342 i:= y + Gear^.Radius * 2 - 2; |
318 repeat |
343 repeat |
319 if (y and LAND_HEIGHT_MASK) = 0 then |
344 if (y and LAND_HEIGHT_MASK) = 0 then |
320 if Land[y, x] > 255 then exit(true); |
345 if Land[y, x] > 255 then |
321 inc(y) |
346 exit(true); |
322 until (y > i); |
347 inc(y) |
323 end; |
348 until (y > i); |
|
349 end; |
324 TestCollisionX:= false |
350 TestCollisionX:= false |
325 end; |
351 end; |
326 |
352 |
327 function TestCollisionY(Gear: PGear; Dir: LongInt): boolean; |
353 function TestCollisionY(Gear: PGear; Dir: LongInt): boolean; |
328 var x, y, i: LongInt; |
354 var x, y, i: LongInt; |
329 begin |
355 begin |
330 y:= hwRound(Gear^.Y); |
356 y:= hwRound(Gear^.Y); |
331 if Dir < 0 then y:= y - Gear^.Radius |
357 if Dir < 0 then |
332 else y:= y + Gear^.Radius; |
358 y:= y - Gear^.Radius |
|
359 else |
|
360 y:= y + Gear^.Radius; |
333 if (y and LAND_HEIGHT_MASK) = 0 then |
361 if (y and LAND_HEIGHT_MASK) = 0 then |
334 begin |
362 begin |
335 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
363 x:= hwRound(Gear^.X) - Gear^.Radius + 1; |
336 i:= x + Gear^.Radius * 2 - 2; |
364 i:= x + Gear^.Radius * 2 - 2; |
337 repeat |
365 repeat |
338 if (x and LAND_WIDTH_MASK) = 0 then |
366 if (x and LAND_WIDTH_MASK) = 0 then |
339 if Land[y, x] > 255 then exit(true); |
367 if Land[y, x] > 255 then |
340 inc(x) |
368 exit(true); |
341 until (x > i); |
369 inc(x) |
342 end; |
370 until (x > i); |
|
371 end; |
343 TestCollisionY:= false |
372 TestCollisionY:= false |
344 end; |
373 end; |
345 |
374 |
346 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean; |
375 function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean; |
347 begin |
376 begin |
348 Gear^.X:= Gear^.X + int2hwFloat(ShiftX); |
377 Gear^.X:= Gear^.X + int2hwFloat(ShiftX); |
349 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY); |
378 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY); |
350 if withGear then TestCollisionYwithXYShift:= TestCollisionYwithGear(Gear, Dir) <> 0 |
379 |
351 else TestCollisionYwithXYShift:= TestCollisionY(Gear, Dir); |
380 if withGear then |
|
381 TestCollisionYwithXYShift:= TestCollisionYwithGear(Gear, Dir) <> 0 |
|
382 else |
|
383 TestCollisionYwithXYShift:= TestCollisionY(Gear, Dir); |
|
384 |
352 Gear^.X:= Gear^.X - int2hwFloat(ShiftX); |
385 Gear^.X:= Gear^.X - int2hwFloat(ShiftX); |
353 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY) |
386 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY) |
354 end; |
387 end; |
355 |
388 |
356 function TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; |
389 function TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; |