132 |
132 |
133 // If the object (practically player) has a pivot point add |
133 // If the object (practically player) has a pivot point add |
134 // a force towards that |
134 // a force towards that |
135 if (pivot != NULL) { |
135 if (pivot != NULL) { |
136 applyForce(getPivotForce()); |
136 applyForce(getPivotForce()); |
|
137 |
137 if (pivot->type == PLAYER) { |
138 if (pivot->type == PLAYER) { |
138 pivot->applyForce(getPivotForce()*(-1)); |
139 pivot->applyForce(-getPivotForce()); |
139 } |
140 } |
140 } |
141 } |
141 |
142 |
142 std::pair<Force, TimeMS> force; |
143 std::pair<Force, TimeMS> force; |
143 std::queue<std::pair<Force, TimeMS> > newfq; |
144 std::queue<std::pair<Force, TimeMS> > newfq; |
|
145 |
144 Force total; |
146 Force total; |
|
147 |
145 while (!forceq.empty()) { |
148 while (!forceq.empty()) { |
146 force = forceq.front(); |
149 force = forceq.front(); |
|
150 |
147 if (force.second > dt) { |
151 if (force.second > dt) { |
148 force.second -= dt; |
152 force.second -= dt; |
149 newfq.push(force); |
153 newfq.push(force); |
150 } |
154 } |
|
155 |
151 total += force.first; |
156 total += force.first; |
152 forceq.pop(); |
157 forceq.pop(); |
153 } |
158 } |
|
159 |
154 forceq = newfq; |
160 forceq = newfq; |
155 |
161 |
156 // If the player has stopped and there's some ground under some of the 3 some of the 3t |
162 // If the player has stopped and there's some ground under some of the 3 some of the 3t |
157 // set inAir false |
163 // set inAir false |
158 if (this->velocity == Vector(0,0)) { |
164 if (this->velocity == Vector(0,0)) { |
159 this->inAir = !world.terrain.collides(this->position+shape[1]+Vector(0, 1)) |
165 this->inAir = !world.terrain.collides(this->position + shape[1] + Vector(0, 1)) |
160 && !world.terrain.collides(this->position+shape[2]+Vector(0, 1)) |
166 && !world.terrain.collides(this->position + shape[2] + Vector(0, 1)) |
161 && !world.terrain.collides(this->position+shape[3]+Vector(0, 1)); |
167 && !world.terrain.collides(this->position + shape[3] + Vector(0, 1)); |
162 // If, however, there's a force caused by a bomb, e.g., set it in air. |
168 // If, however, there's a force caused by a bomb, e.g., set it in air. |
163 // Still, we have to be able to separate forces caused by walking attempts |
169 // Still, we have to be able to separate forces caused by walking attempts |
164 // and bombs etc (+0.1 because float comparison can be dangerous) |
170 // and bombs etc (+0.1 because float comparison can be dangerous) |
165 if (total.y < 0.01 || fabs(total.x) > PLAYER_MOVE_FORCE + 0.1) |
171 if (total.y < 0.01 || fabs(total.x) > PLAYER_MOVE_FORCE + 0.1) |
166 this->inAir = true; |
172 this->inAir = true; |
167 } |
173 } |
168 |
174 |
169 if(!possibleLocation(position)) { |
175 if (!possibleLocation(position)) { |
170 //if we are trapped in ground form dirtball or something |
176 //if we are trapped in ground form dirtball or something |
171 //we might want to just return and set velocity to some value |
177 //we might want to just return and set velocity to some value |
172 //return; |
178 //return; |
173 } |
179 } |
174 |
180 |
237 |
243 |
238 // In case of some float error check the final coordinate |
244 // In case of some float error check the final coordinate |
239 if (!collided) { |
245 if (!collided) { |
240 if (!possibleLocation(newPosition)) { |
246 if (!possibleLocation(newPosition)) { |
241 newPosition = reached; |
247 newPosition = reached; |
|
248 |
242 } else { |
249 } else { |
243 // This means everything was ok, so no need to do anything |
250 // This means everything was ok, so no need to do anything |
244 } |
251 } |
245 |
252 |
246 setPosition (newPosition); |
253 setPosition(newPosition); |
247 |
254 |
248 } else { |
255 } else { |
249 newPosition = reached; |
256 newPosition = reached; |
250 setPosition (newPosition); |
257 setPosition(newPosition); |
251 |
258 |
252 // the following may delete this object, so it must be the last thing called |
259 // the following may delete this object, so it must be the last thing called |
253 onCollision(collisionPoint); |
260 onCollision(collisionPoint); |
254 |
261 |
255 return; |
262 return; |
262 */ |
269 */ |
263 void PhysicsObject::bounce (Vector normal) { |
270 void PhysicsObject::bounce (Vector normal) { |
264 // normal.sqrLength can't be 0 when got from getNormal() |
271 // normal.sqrLength can't be 0 when got from getNormal() |
265 if (normal.sqrLength() != 0) { |
272 if (normal.sqrLength() != 0) { |
266 Vector nvel = velocity; |
273 Vector nvel = velocity; |
|
274 |
267 // We project the velocity on normal and remove twice that much from velocity |
275 // We project the velocity on normal and remove twice that much from velocity |
268 nvel = nvel - ((2)*((nvel*normal)/(normal*normal))*normal); |
276 nvel = nvel - (2 * ((nvel * normal) / (normal * normal)) * normal); |
269 velocity = nvel; |
277 velocity = nvel; |
|
278 |
270 // We lose some of our speed on collision |
279 // We lose some of our speed on collision |
271 this->velocity *= this->collision_elasticity; |
280 this->velocity *= this->collision_elasticity; |
272 } |
281 } |
273 } |
282 } |
274 |
283 |
276 * Integrates given force over time and stores new position to |
285 * Integrates given force over time and stores new position to |
277 * posAfterTick and new velocity to velAfterTick. |
286 * posAfterTick and new velocity to velAfterTick. |
278 * @param force Force vector. |
287 * @param force Force vector. |
279 * @param dt The time the force is applied (<=PHYSICS_TICK_MS) |
288 * @param dt The time the force is applied (<=PHYSICS_TICK_MS) |
280 */ |
289 */ |
281 void PhysicsObject::integrate(Force force, TimeMS dt, Vector &posAfterTick, Vector &velAfterTick) { |
290 void PhysicsObject::integrate (Force force, TimeMS dt, Vector &posAfterTick, Vector &velAfterTick) { |
282 posAfterTick = position; |
291 posAfterTick = position; |
283 velAfterTick = velocity; |
292 velAfterTick = velocity; |
|
293 |
284 Derivative tmpd; |
294 Derivative tmpd; |
285 Derivative k1 = evaluate(force, 0, tmpd, posAfterTick, velAfterTick); |
295 Derivative k1 = evaluate(force, 0, tmpd, posAfterTick, velAfterTick); |
286 Derivative k2 = evaluate(force, dt / 2, k1, posAfterTick, velAfterTick); |
296 Derivative k2 = evaluate(force, dt / 2, k1, posAfterTick, velAfterTick); |
287 Derivative k3 = evaluate(force, dt / 2, k2, posAfterTick, velAfterTick); |
297 Derivative k3 = evaluate(force, dt / 2, k2, posAfterTick, velAfterTick); |
288 Derivative k4 = evaluate(force, dt, k3, posAfterTick, velAfterTick); |
298 Derivative k4 = evaluate(force, dt, k3, posAfterTick, velAfterTick); |
289 |
299 |
290 |
300 const Vector dxdt = (k1.dx + (k2.dx + k3.dx) * 2.0f + k4.dx) * 1.0f / 6.0f; |
291 const Vector dxdt = (k1.dx + (k2.dx + k3.dx) * 2.0f + k4.dx) * 1.0f/6.0f; |
301 const Vector dvdt = (k1.dv + (k2.dv + k3.dv) * 2.0f + k4.dv) * 1.0f / 6.0f; |
292 const Vector dvdt = (k1.dv + (k2.dv + k3.dv) * 2.0f + k4.dv) * 1.0f/6.0f; |
302 |
293 |
303 posAfterTick = posAfterTick + (dxdt * dt) / 1000; |
294 // Engine::log(DEBUG, "PhysicsObject.integrate") << "Changes: "<< dxdt << " " << dvdt << " Time: " <<dt; |
304 velAfterTick = velAfterTick + (dvdt * dt) / 1000; |
295 posAfterTick = posAfterTick + (dxdt * dt)/1000; |
305 } |
296 velAfterTick = velAfterTick + (dvdt * dt)/1000; |
306 |
297 //Engine::log(DEBUG, "PhysicsObject.integrate") << "velAfterTick: " << velAfterTick; |
307 Derivative PhysicsObject::evaluate (Force force, TimeMS dt, const Derivative &d, const Vector &posAfterTick, const Vector &velAfterTick) { |
298 } |
308 Vector curPos = posAfterTick + (d.dx * dt) / 1000; |
299 |
309 Vector curVel = velAfterTick + (d.dv * dt) / 1000; |
300 Derivative PhysicsObject::evaluate(Force force, TimeMS dt, Derivative &d, const Vector &posAfterTick, const Vector &velAfterTick) { |
310 |
301 Vector curPos = posAfterTick + (d.dx*dt)/1000; |
311 return Derivative(curVel, acceleration(force)); |
302 Vector curVel = velAfterTick + (d.dv*dt)/1000; |
|
303 |
|
304 Derivative out; |
|
305 out.dx = curVel; |
|
306 out.dv = acceleration(force); |
|
307 //Engine::log(DEBUG, "PhysicsObject.evaluate") << "Out.dx: " << out.dx; |
|
308 return out; |
|
309 } |
312 } |
310 |
313 |
311 Vector PhysicsObject::acceleration(const Force &force) { |
314 Vector PhysicsObject::acceleration(const Force &force) { |
312 return (force/mass); |
315 return (force / mass); |
313 } |
316 } |
314 |
317 |
315 void PhysicsObject::applyForce (Force force, TimeMS dt) { |
318 void PhysicsObject::applyForce (Force force, TimeMS dt) { |
316 // Add applied force to the queue |
319 // Add applied force to the queue |
317 forceq.push(std::make_pair(force, dt)); |
320 forceq.push(std::make_pair(force, dt)); |
321 this->aim += da; |
324 this->aim += da; |
322 |
325 |
323 if (this->aim > PLAYER_AIM_MAX) this->aim = PLAYER_AIM_MAX; |
326 if (this->aim > PLAYER_AIM_MAX) this->aim = PLAYER_AIM_MAX; |
324 if (this->aim < PLAYER_AIM_MIN) this->aim = PLAYER_AIM_MIN; |
327 if (this->aim < PLAYER_AIM_MIN) this->aim = PLAYER_AIM_MIN; |
325 //Engine::log(DEBUG, "PhysicsObject.changeAim") << "Player aim: " << this->aim; |
328 //Engine::log(DEBUG, "PhysicsObject.changeAim") << "Player aim: " << this->aim; |
326 } |
|
327 |
|
328 ObjectType PhysicsObject::getType (void) const { |
|
329 return this->type; |
|
330 } |
|
331 |
|
332 void PhysicsObject::setFacing (FacingDirection facing) { |
|
333 this->facing = facing; |
|
334 } |
329 } |
335 |
330 |
336 void PhysicsObject::updatePhysics (Vector position, Vector velocity, bool inAir, FacingDirection facing, float aim) { |
331 void PhysicsObject::updatePhysics (Vector position, Vector velocity, bool inAir, FacingDirection facing, float aim) { |
337 setPosition (position); |
332 setPosition (position); |
338 this->velocity = velocity; |
333 this->velocity = velocity; |
339 this->inAir = inAir; |
334 this->inAir = inAir; |
340 this->facing = facing; |
335 this->facing = facing; |
341 this->aim = aim; |
336 this->aim = aim; |
342 } |
337 } |
343 |
338 |
344 Vector PhysicsObject::getPosition (void) const { |
|
345 return position; |
|
346 } |
|
347 |
|
348 Vector PhysicsObject::getPreviousPosition (void) const { |
|
349 return previousPosition; |
|
350 } |
|
351 |
|
352 PixelCoordinate PhysicsObject::getCoordinate (void) const { |
339 PixelCoordinate PhysicsObject::getCoordinate (void) const { |
353 return world.terrain.getPixelCoordinate(position); |
340 return world.terrain.getPixelCoordinate(position); |
354 } |
341 } |
355 |
342 |
356 Vector PhysicsObject::getVelocity (void) const { |
|
357 return velocity; |
|
358 } |
|
359 |
|
360 FacingDirection PhysicsObject::getFacing (void) const { |
|
361 return facing; |
|
362 } |
|
363 |
|
364 float PhysicsObject::getAim (void) const { |
|
365 return aim; |
|
366 } |
|
367 |
|
368 Vector PhysicsObject::getDirection (void) const { |
343 Vector PhysicsObject::getDirection (void) const { |
369 return facing == FACING_RIGHT ? Vector(cos(aim), -sin(aim)) : Vector(-cos(aim), -sin(aim)); |
344 return facing == FACING_RIGHT ? Vector(cos(aim), -sin(aim)) : Vector(-cos(aim), -sin(aim)); |
370 } |
|
371 |
|
372 const std::vector<Vector>& PhysicsObject::getShape () const { |
|
373 return shape; |
|
374 } |
|
375 |
|
376 void PhysicsObject::setShape (std::vector<Vector> shape) { |
|
377 this->shape = shape; |
|
378 } |
|
379 |
|
380 PhysicsObject *PhysicsObject::getPivot (void) { |
|
381 return this->pivot; |
|
382 } |
|
383 |
|
384 void PhysicsObject::setPivot (PhysicsObject *pivot) { |
|
385 this->pivot = pivot; |
|
386 } |
345 } |
387 |
346 |
388 void PhysicsObject::tick (TimeMS tick_length) { |
347 void PhysicsObject::tick (TimeMS tick_length) { |
389 this->updatePosition(tick_length); |
348 this->updatePosition(tick_length); |
390 } |
349 } |