13 * |
13 * |
14 * You should have received a copy of the GNU General Public License |
14 * You should have received a copy of the GNU General Public License |
15 * along with this program; if not, write to the Free Software |
15 * along with this program; if not, write to the Free Software |
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
17 *) |
17 *) |
|
18 |
|
19 procedure doStepPerPixel(Gear: PGear; step: TGearStepProcedure; onlyCheckIfChanged: boolean); |
|
20 var |
|
21 dX, dY, sX, sY: hwFloat; |
|
22 i, steps: LongWord; |
|
23 caller: TGearStepProcedure; |
|
24 begin |
|
25 dX:= Gear^.dX; |
|
26 dY:= Gear^.dY; |
|
27 steps:= max(abs(hwRound(Gear^.X+dX)-hwRound(Gear^.X)), abs(hwRound(Gear^.Y+dY)-hwRound(Gear^.Y))); |
|
28 |
|
29 // Gear is still on the same Pixel it was before |
|
30 if steps < 1 then |
|
31 begin |
|
32 if onlyCheckIfChanged then |
|
33 begin |
|
34 Gear^.X := Gear^.X + dX; |
|
35 Gear^.Y := Gear^.Y + dY; |
|
36 EXIT; |
|
37 end |
|
38 else |
|
39 steps := 1; |
|
40 end; |
|
41 |
|
42 if steps > 1 then |
|
43 begin |
|
44 sX:= dX / steps; |
|
45 sY:= dY / steps; |
|
46 end |
|
47 else |
|
48 begin |
|
49 sX:= dX; |
|
50 sY:= dY; |
|
51 end; |
|
52 |
|
53 caller:= Gear^.doStep; |
|
54 |
|
55 for i:= 1 to steps do |
|
56 begin |
|
57 Gear^.X := Gear^.X + sX; |
|
58 Gear^.Y := Gear^.Y + sY; |
|
59 step(Gear); |
|
60 if (Gear^.doStep <> caller) |
|
61 or ((Gear^.State and gstCollision) <> 0) |
|
62 or ((Gear^.State and gstMoving) = 0) then |
|
63 break; |
|
64 end; |
|
65 end; |
18 |
66 |
19 procedure makeHogsWorry(x, y: hwFloat; r: LongInt); |
67 procedure makeHogsWorry(x, y: hwFloat; r: LongInt); |
20 var |
68 var |
21 gi: PGear; |
69 gi: PGear; |
22 d: LongInt; |
70 d: LongInt; |
3155 end; |
3203 end; |
3156 |
3204 |
3157 procedure doStepPortal(Gear: PGear); |
3205 procedure doStepPortal(Gear: PGear); |
3158 var |
3206 var |
3159 iterator, conPortal: PGear; |
3207 iterator, conPortal: PGear; |
3160 s, acptRadius, cdxy: hwFloat; |
3208 s, acptRadius, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed: hwFloat; |
3161 noTrap, hasdxy: Boolean; |
3209 noTrap, hasdxy: Boolean; |
3162 begin |
3210 begin |
3163 doPortalColorSwitch(); |
3211 doPortalColorSwitch(); |
3164 |
3212 |
3165 // destroy portal if ground it was attached too is gone |
3213 // destroy portal if ground it was attached too is gone |
3210 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) |
3258 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) |
3211 and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = |
3259 and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = |
3212 gtRope) then |
3260 gtRope) then |
3213 continue; |
3261 continue; |
3214 |
3262 |
|
3263 // check if gear fits through portal |
3215 if (iterator^.Radius > Gear^.Radius) then |
3264 if (iterator^.Radius > Gear^.Radius) then |
3216 continue; |
3265 continue; |
3217 // sorry, you're too fat! |
3266 |
3218 |
3267 // this is the max range we accept incoming gears in |
3219 // this is the range we accept incoming gears in |
|
3220 acptRadius := Int2hwFloat(iterator^.Radius+Gear^.Radius); |
3268 acptRadius := Int2hwFloat(iterator^.Radius+Gear^.Radius); |
3221 |
3269 |
|
3270 // too far away? |
3222 if (iterator^.X < Gear^.X - acptRadius) |
3271 if (iterator^.X < Gear^.X - acptRadius) |
3223 or (iterator^.X > Gear^.X + acptRadius) |
3272 or (iterator^.X > Gear^.X + acptRadius) |
3224 or (iterator^.Y < Gear^.Y - acptRadius) |
3273 or (iterator^.Y < Gear^.Y - acptRadius) |
3225 or (iterator^.Y > Gear^.Y + acptRadius) then |
3274 or (iterator^.Y > Gear^.Y + acptRadius) then |
3226 continue; |
3275 continue; |
3227 // too far away! |
|
3228 |
3276 |
3229 hasdxy := ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)); |
3277 hasdxy := ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)); |
3230 |
3278 |
|
3279 // won't port stuff that moves away from me! |
3231 if hasdxy and not (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then |
3280 if hasdxy and not (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then |
3232 continue; |
3281 continue; |
3233 // won't port stuff that moves away from me! |
3282 |
3234 |
3283 if (iterator^.Kind <> gtCake) then |
3235 // wow! good candidate there, let's see if the distance really is small enough! |
3284 begin |
3236 if (Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y) > acptRadius) then |
3285 // wow! good candidate there, let's see if the distance and direction is okay! |
3237 continue; |
3286 if hasdxy then |
|
3287 begin |
|
3288 s := int2hwFloat(iterator^.Radius) / Distance(iterator^.dX, iterator^.dY); |
|
3289 ox:= iterator^.X + s * iterator^.dX; |
|
3290 oy:= iterator^.Y + s * iterator^.dY; |
|
3291 end |
|
3292 else |
|
3293 begin |
|
3294 ox:= iterator^.X; |
|
3295 oy:= iterator^.Y + Int2hwFloat(iterator^.Radius); |
|
3296 end; |
|
3297 |
|
3298 if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius) then |
|
3299 continue; |
|
3300 end; |
|
3301 |
3238 (* |
3302 (* |
3239 noTrap := ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) |
3303 noTrap := ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) |
3240 // can't be entered from above |
3304 // can't be entered from above |
3241 or ((conPortal^.dY.isNegative and not (conPortal^.dY.QWordValue = 0)))); |
3305 or ((conPortal^.dY.isNegative and not (conPortal^.dY.QWordValue = 0)))); |
3242 // can't be left downwards; |
3306 // can't be left downwards; |
3250 DeleteCI(iterator); |
3314 DeleteCI(iterator); |
3251 |
3315 |
3252 // Until loops are reliably broken |
3316 // Until loops are reliably broken |
3253 inc(iterator^.PortalCounter); |
3317 inc(iterator^.PortalCounter); |
3254 |
3318 |
3255 // TODO: more accurate porting |
3319 // find out how much speed parallel to the portal vector |
3256 cdxy := Distance(conPortal^.dX, conPortal^.dY); |
3320 // the gear has, also get the vector offset |
3257 s := (Int2hwFloat(Gear^.Radius)) / cdxy; |
3321 pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY); |
3258 |
3322 ox := (iterator^.X - Gear^.X); |
|
3323 oy := (iterator^.Y - Gear^.Y); |
|
3324 poffs:= (Gear^.dX * ox + Gear^.dY * oy); |
|
3325 // create a normal of the portal vector |
|
3326 nx := - Gear^.dY; |
|
3327 ny := Gear^.dX; |
|
3328 // pick the normal vector that's pointing skywards |
|
3329 if (not ny.isNegative) then |
|
3330 begin |
|
3331 nx.isNegative := not nx.isNegative; |
|
3332 ny.isNegative := not ny.isNegative; |
|
3333 end; |
|
3334 // now let's find out how much speed the gear has in the |
|
3335 // direction of that normal |
|
3336 nspeed:= (nx * iterator^.dX + ny * iterator^.dY); |
|
3337 noffs:= (nx * ox + ny * oy); |
|
3338 |
|
3339 // now let's project those back to the connected portal's vectors |
|
3340 nx := - conPortal^.dY; |
|
3341 ny := conPortal^.dX; |
|
3342 if ny.isNegative then |
|
3343 begin |
|
3344 nx.isNegative := not nx.isNegative; |
|
3345 ny.isNegative := not ny.isNegative; |
|
3346 end; |
|
3347 //AddFileLog('poffs:'+cstr(poffs)+' noffs:'+cstr(noffs)+' pspeed:'+cstr(pspeed)+' nspeed:'+cstr(nspeed)); |
|
3348 iterator^.dX := -pspeed * conPortal^.dX - nspeed * nx; |
|
3349 iterator^.dY := -pspeed * conPortal^.dY - nspeed * ny; |
3259 if iterator^.Kind = gtCake then |
3350 if iterator^.Kind = gtCake then |
3260 begin |
3351 poffs := poffs * _0_5; |
3261 iterator^.X := conPortal^.X ; |
3352 iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx; |
3262 iterator^.Y := conPortal^.Y ; |
3353 iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny; |
3263 end |
|
3264 else |
|
3265 begin |
|
3266 iterator^.X := conPortal^.X + s * conPortal^.dX; |
|
3267 iterator^.Y := conPortal^.Y + s * conPortal^.dY; |
|
3268 |
|
3269 s := Distance(iterator^.dX, iterator^.dY) / cdxy; |
|
3270 |
|
3271 iterator^.dX := s * conPortal^.dX; |
|
3272 iterator^.dY := s * conPortal^.dY |
|
3273 end; |
|
3274 |
3354 |
3275 FollowGear := iterator; |
3355 FollowGear := iterator; |
3276 |
3356 //AddFileLog('portal''d'); |
|
3357 |
|
3358 { |
3277 s := _0_2 + _0_008 * Gear^.Health; |
3359 s := _0_2 + _0_008 * Gear^.Health; |
3278 iterator^.dX := s * iterator^.dX; |
3360 iterator^.dX := s * iterator^.dX; |
3279 iterator^.dY := s * iterator^.dY; |
3361 iterator^.dY := s * iterator^.dY; |
|
3362 } |
3280 |
3363 |
3281 if Gear^.Health > 1 then dec(Gear^.Health); |
3364 if Gear^.Health > 1 then dec(Gear^.Health); |
3282 //dec(iterator^.Health);?? |
3365 |
3283 |
3366 { // breaks (some) loops |
3284 // breaks (some) loops |
|
3285 if Distance(iterator^.dX, iterator^.dY) > _0_96 then |
3367 if Distance(iterator^.dX, iterator^.dY) > _0_96 then |
3286 begin |
3368 begin |
3287 iterator^.dX := iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX); |
3369 iterator^.dX := iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX); |
3288 iterator^.dY := iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY); |
3370 iterator^.dY := iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY); |
3289 s := _0_96 / Distance(iterator^.dX, iterator^.dY); |
3371 s := _0_96 / Distance(iterator^.dX, iterator^.dY); |
3290 iterator^.dX := s * iterator^.dX; |
3372 iterator^.dX := s * iterator^.dX; |
3291 iterator^.dY := s * iterator^.dX; |
3373 iterator^.dY := s * iterator^.dX; |
3292 end; |
3374 end; |
3293 end; |
3375 } |
3294 end; |
3376 end; |
3295 |
3377 end; |
3296 procedure doStepMovingPortal(Gear: PGear); |
3378 |
|
3379 procedure doStepMovingPortal_real(Gear: PGear); |
3297 var |
3380 var |
3298 x, y, tx, ty: LongInt; |
3381 x, y, tx, ty: LongInt; |
3299 //, bx, by, tangle: LongInt; |
|
3300 s: hwFloat; |
3382 s: hwFloat; |
3301 |
3383 |
3302 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); |
3384 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); |
3303 var |
3385 var |
3304 flags: LongWord; |
3386 flags: LongWord; |
3320 |
3402 |
3321 if destroyGear then oldPortal^.Timer:= 0; |
3403 if destroyGear then oldPortal^.Timer:= 0; |
3322 end; |
3404 end; |
3323 |
3405 |
3324 begin |
3406 begin |
3325 if (Gear^.Timer < 1) |
|
3326 or (PHedgehog(Gear^.Hedgehog) <> CurrentHedgehog) then |
|
3327 begin |
|
3328 deleteGear(Gear); |
|
3329 EXIT; |
|
3330 end; |
|
3331 |
|
3332 doPortalColorSwitch(); |
|
3333 |
|
3334 Gear^.X := Gear^.X + Gear^.dX; |
|
3335 Gear^.Y := Gear^.Y + Gear^.dY; |
|
3336 x := hwRound(Gear^.X); |
3407 x := hwRound(Gear^.X); |
3337 y := hwRound(Gear^.Y); |
3408 y := hwRound(Gear^.Y); |
3338 tx := 0; |
3409 tx := 0; |
3339 ty := 0; |
3410 ty := 0; |
3340 // avoid compiler hints |
3411 // avoid compiler hints |
3341 |
3412 |
3342 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then |
3413 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then |
3343 begin |
3414 begin |
|
3415 Gear^.State := Gear^.State or gstCollision; |
|
3416 Gear^.State := Gear^.State and not gstMoving; |
3344 if not calcSlopeTangent(Gear, x, y, tx, ty, 255) |
3417 if not calcSlopeTangent(Gear, x, y, tx, ty, 255) |
3345 or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain |
3418 or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain |
3346 begin |
3419 begin |
3347 loadNewPortalBall(Gear, true); |
3420 loadNewPortalBall(Gear, true); |
3348 EXIT; |
3421 EXIT; |
3369 loadNewPortalBall(Gear, true); |
3442 loadNewPortalBall(Gear, true); |
3370 end |
3443 end |
3371 else if (y > cWaterLine) or (y < -LAND_WIDTH) |
3444 else if (y > cWaterLine) or (y < -LAND_WIDTH) |
3372 or (x > 2*LAND_WIDTH) or (x < -LAND_WIDTH) then |
3445 or (x > 2*LAND_WIDTH) or (x < -LAND_WIDTH) then |
3373 loadNewPortalBall(Gear, true); |
3446 loadNewPortalBall(Gear, true); |
|
3447 end; |
|
3448 |
|
3449 procedure doStepMovingPortal(Gear: PGear); |
|
3450 begin |
|
3451 doPortalColorSwitch(); |
|
3452 doStepPerPixel(Gear, @doStepMovingPortal_real, true); |
|
3453 if (Gear^.Timer < 1) |
|
3454 or (PHedgehog(Gear^.Hedgehog) <> CurrentHedgehog) then |
|
3455 deleteGear(Gear); |
3374 end; |
3456 end; |
3375 |
3457 |
3376 procedure doStepPortalShot(newPortal: PGear); |
3458 procedure doStepPortalShot(newPortal: PGear); |
3377 var |
3459 var |
3378 iterator: PGear; |
3460 iterator: PGear; |