3040 end; |
3040 end; |
3041 end; |
3041 end; |
3042 |
3042 |
3043 //////////////////////////////////////////////////////////////////////////////// |
3043 //////////////////////////////////////////////////////////////////////////////// |
3044 procedure doStepPortal(Gear: PGear); |
3044 procedure doStepPortal(Gear: PGear); |
3045 var iterator: PGear; |
3045 var iterator, conPortal: PGear; |
3046 s: hwFloat; |
3046 s, acptRadius: hwFloat; |
3047 begin |
3047 noTrap, hasdxy: Boolean; |
3048 if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then |
3048 begin |
3049 begin |
3049 // destroy portal if ground it was attached too is gone |
3050 if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= nil; |
3050 if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then deleteGear(Gear); |
3051 DeleteGear(Gear); |
3051 |
3052 EXIT; |
3052 // abort if there is no other portal connected to this one |
3053 end; |
3053 if Gear^.IntersectGear = nil then |
|
3054 exit; |
|
3055 |
|
3056 conPortal:= Gear^.IntersectGear; |
|
3057 |
|
3058 // check all gears for stuff to port through |
|
3059 iterator:= nil; |
|
3060 while true do |
|
3061 begin |
|
3062 |
|
3063 if iterator = nil then |
|
3064 iterator:= GearsList // start |
|
3065 else |
|
3066 iterator:= iterator^.NextGear; // iterate through GearsList |
3054 |
3067 |
3055 if Gear^.IntersectGear <> nil then |
3068 if iterator = nil then |
3056 //if (Gear^.IntersectGear <> nil) then |
3069 break; // end of list |
3057 begin |
3070 |
3058 iterator:= GearsList; |
3071 // don't port portals or other gear that wouldn't make sense |
3059 while iterator <> nil do |
3072 if (iterator^.Kind = gtPortal) |
|
3073 or (iterator^.Kind = gtHealthTag) then |
|
3074 continue; |
|
3075 |
|
3076 { |
|
3077 if (((iterator^.State and gstMoving) = 0) // we don't port non-moving stuff IF the portal entry... |
|
3078 and (iterator^.Active = false) |
|
3079 and ) then //... |
|
3080 continue; |
|
3081 } |
|
3082 |
|
3083 if (iterator^.Radius > Gear^.Radius) then |
|
3084 continue; // sorry, you're too fat! |
|
3085 |
|
3086 // this is the range we accept incoming gears in |
|
3087 acptRadius:= Int2hwFloat(iterator^.Radius+Gear^.Radius); |
|
3088 |
|
3089 if (iterator^.X < Gear^.X - acptRadius) |
|
3090 or (iterator^.X > Gear^.X + acptRadius) |
|
3091 or (iterator^.Y < Gear^.Y - acptRadius) |
|
3092 or (iterator^.Y > Gear^.Y + acptRadius) then |
|
3093 continue; // too far away! |
|
3094 |
|
3095 hasdxy:= ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)); |
|
3096 |
|
3097 if hasdxy and not (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then |
|
3098 continue; // won't port stuff that moves away from me! |
|
3099 |
|
3100 // wow! good candidate there, let's see if the distance really is small enough! |
|
3101 if (Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y) > acptRadius) then |
|
3102 continue; |
|
3103 |
|
3104 noTrap:= ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) // can't be entered from above |
|
3105 or ((conPortal^.dY.isNegative or (conPortal^.dY.QWordValue = 0)))); // can't be left downwards; |
|
3106 |
|
3107 |
|
3108 // lets see if this one is just stuck in a stuck-loop |
|
3109 if noTrap and (iterator^.dY.QWordValue < _0_1.QWordValue) then |
|
3110 continue; |
|
3111 |
|
3112 iterator^.Active:= true; |
|
3113 iterator^.State:= iterator^.State or gstMoving; |
|
3114 DeleteCI(iterator); |
|
3115 |
|
3116 s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(conPortal^.dX, conPortal^.dY); |
|
3117 iterator^.X:= conPortal^.X + s * conPortal^.dX; |
|
3118 iterator^.Y:= conPortal^.Y + s * conPortal^.dY; |
|
3119 s:= Distance(iterator^.dX, iterator^.dY) / Distance(conPortal^.dX, conPortal^.dY); |
|
3120 iterator^.dX:= s * conPortal^.dX; |
|
3121 iterator^.dY:= s * conPortal^.dY; |
|
3122 |
|
3123 if iterator^.dY.isNegative and (iterator^.dY.QWordValue <> 0) then |
|
3124 iterator^.dY:= iterator^.dY + hwAbs(Int2hwFloat(iterator^.Radius) / iterator^.dY) * cGravity; |
|
3125 |
|
3126 // breaks (some) loops |
|
3127 if Distance(iterator^.dX, iterator^.dY) > _0_96 then |
3060 begin |
3128 begin |
3061 if (iterator^.Kind <> gtPortal) and (iterator^.PortedCounter < 20) then |
3129 iterator^.dX:= iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX); |
3062 if (((iterator^.State and gstMoving) <> 0) or (Gear^.IntersectGear^.dY.isNegative and not Gear^.dY.isNegative)) |
3130 iterator^.dY:= iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY); |
3063 and (hwRound(Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y)) < iterator^.Radius+Gear^.Radius) then // Let's check this one more closely |
3131 s:= _0_995 / Distance(iterator^.dX, iterator^.dY); |
3064 if (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then // make sure object moves towards the portal |
3132 iterator^.dX:= s * iterator^.dX; |
3065 begin |
3133 iterator^.dY:= s * iterator^.dX; |
3066 inc(iterator^.PortedCounter); |
|
3067 s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(Gear^.IntersectGear^.dX, Gear^.IntersectGear^.dY); |
|
3068 iterator^.X:= Gear^.IntersectGear^.X + s * Gear^.IntersectGear^.dX; |
|
3069 iterator^.Y:= Gear^.IntersectGear^.Y + s * Gear^.IntersectGear^.dY; |
|
3070 s:= Distance(iterator^.dX, iterator^.dY) / Distance(Gear^.IntersectGear^.dX, Gear^.IntersectGear^.dY); |
|
3071 iterator^.dX:= s * Gear^.IntersectGear^.dX; |
|
3072 iterator^.dY:= s * Gear^.IntersectGear^.dY; |
|
3073 end; |
|
3074 |
|
3075 iterator:= iterator^.NextGear; |
|
3076 end; |
3134 end; |
3077 // do portal stuff |
3135 |
3078 end |
3136 iterator:= iterator^.NextGear; |
|
3137 end; |
3079 |
3138 |
3080 (* |
3139 (* |
3081 |
3140 |
3082 2) From then on, if doStepPortal is called and a gear of a radius less than or equal to the portal is within X pixels of the portal (we could also check on moving toward the portal I guess, depends how accurate this needs to be) the portal will then locate the first other portal of the opposite type (there should only be one other one), and move that gear's X/Y to that other portal's location, and modify dX/dY to be relative to that other portal's orientation relative to this portal's orientation. This might require some tweaking with offsets of a few pixels to avoid getting gears stuck in land. |
3141 2) From then on, if doStepPortal is called and a gear of a radius less than or equal to the portal is within X pixels of the portal (we could also check on moving toward the portal I guess, depends how accurate this needs to be) the portal will then locate the first other portal of the opposite type (there should only be one other one), and move that gear's X/Y to that other portal's location, and modify dX/dY to be relative to that other portal's orientation relative to this portal's orientation. This might require some tweaking with offsets of a few pixels to avoid getting gears stuck in land. |
3083 |
3142 |
3084 *) |
3143 *) |
3085 end; |
3144 end; |
3086 |
3145 |
3087 procedure doStepMovingPortal(Gear: PGear); |
3146 procedure doStepMovingPortal(Gear: PGear); |
3088 var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt; |
3147 var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt; |
3089 iterator: PGear; |
|
3090 s, dx, dy: hwFloat; |
3148 s, dx, dy: hwFloat; |
3091 begin |
3149 begin |
3092 Gear^.X:= Gear^.X + Gear^.dX; |
3150 Gear^.X:= Gear^.X + Gear^.dX; |
3093 Gear^.Y:= Gear^.Y + Gear^.dY; |
3151 Gear^.Y:= Gear^.Y + Gear^.dY; |
3094 x:= hwRound(Gear^.X); |
3152 x:= hwRound(Gear^.X); |
3149 begin |
3207 begin |
3150 if CurrentHedgehog <> nil then |
3208 if CurrentHedgehog <> nil then |
3151 if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3209 if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3152 else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 |
3210 else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 |
3153 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; |
3211 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; |
3154 DeleteGear(Gear) |
3212 deleteGear(Gear) |
3155 end |
3213 end |
3156 else |
3214 else |
3157 begin |
3215 begin |
3158 if CurrentHedgehog <> nil then |
3216 if CurrentHedgehog <> nil then |
3159 if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3217 if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3160 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2; |
3218 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2; |
3161 inc(Gear^.Tag); |
3219 inc(Gear^.Tag); |
3162 Gear^.doStep:= @doStepPortal; |
3220 Gear^.doStep:= @doStepPortal; |
3163 if Gear^.IntersectGear <> nil then |
3221 if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= Gear; |
3164 begin |
|
3165 Gear^.IntersectGear^.IntersectGear:= Gear; |
|
3166 AllInactive:= false; |
|
3167 // This jiggles gears, to ensure a portal connection just placed under a gear takes effect. |
|
3168 iterator:= GearsList; |
|
3169 while iterator <> nil do |
|
3170 begin |
|
3171 if iterator^.Kind <> gtPortal then |
|
3172 begin |
|
3173 iterator^.Active:= true; |
|
3174 if iterator^.dY.QWordValue = _0.QWordValue then iterator^.dY.isNegative:= false; |
|
3175 iterator^.State:= iterator^.State or gstMoving; |
|
3176 DeleteCI(iterator); |
|
3177 inc(iterator^.dY.QWordValue,10); |
|
3178 end; |
|
3179 iterator:= iterator^.NextGear |
|
3180 end; |
|
3181 doStepPortal(Gear); |
|
3182 if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.doStep(Gear^.IntersectGear); |
|
3183 end |
|
3184 end |
3222 end |
3185 end |
3223 end |
3186 else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then |
3224 else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then |
3187 begin |
3225 begin |
3188 if CurrentHedgehog <> nil then |
3226 if CurrentHedgehog <> nil then |
3189 if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3227 if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3190 else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 |
3228 else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 |
3191 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; |
3229 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; |
3192 DeleteGear(Gear); |
3230 deleteGear(Gear); |
3193 end; |
3231 end; |
3194 end; |
3232 end; |
3195 |
3233 |
3196 procedure doStepPiano(Gear: PGear); |
3234 procedure doStepPiano(Gear: PGear); |
3197 var r0, r1: LongInt; |
3235 var r0, r1: LongInt; |