I want to make my body fly at constant speed, how to make it fly at constant speed before and after collision? I set restitution of my body to 1.0 but after some direct and powerful collisions my objects begins to slow, I want it to fly same speed as before. I heard this can be done by setting liner damping of the object, I think it can prevent only from fast flying objects not slow. Thanks in advance.
Edit* I can simply modify velocity of the object every frame, is it a solution?
var velocity:b2Vec2=b.GetLinearVelocity();
var speed:Number=velocity.Length();
var ratio:Number=circleSpeed/speed;
velocity.Multiply(ratio);
b.SetLinearVelocity(velocity);
Answer
Ok here's the dealio.
Forget box2d for the next little while. Just think about physics.
First of all, recall the definition for the coefficient of restitution:
The coefficient of restitution (COR) of two colliding objects is a fractional value representing the ratio of speeds after and before an impact, taken along the line of the impact.
Also, lets keep things simple and restrict ourselves to thinking about head-on collisions between two circles. This means that the line of impact will be coincident with the axis along which the circle(s) are moving (one may be at rest), as shown below:
Image Courtesy of ecourses.ou.edu
Consider the set-up in the figure above, where ball A
is moving towards ball B
and their masses are significant relative to each other. When the collision occurs, B
will gain some momentum in the direction A
was initially travelling, but A
can do one of three things depending on the initial velocity of A
and the masses of the two balls:
A
will bounce offB
, reversing its direction and travelling with a smaller speed than it entered the collision withA
will completely transfer its momentum toB
, and will stop as a result.A
will continue along its initial direction, but with a smaller speed.
Any high-school or 1st year university physics text will walk you through this, and show the equations that can be used to solve for any parameter you desire.
Ok now this is important: in cases 1-3 the kinetic energies (speeds) for each of the balls change before and after the collision, even though the COR = 1. Why is that? The Wikipedia definition sacrifices a little clarity for the sake of compactness, but it is still correct. Take a look at the equation below from the wiki article:
This is just the conservation of momentum equation and the COR equation, written from their definitions.
It is quite clear that, even with COR = 1, the speeds of the colliding objects before and after the collision need not be maintained. All that's required is that the difference in their speeds before and after the collision remain the same.
Given this brief explanation I can point out some problems with your question. You are asking that the speed of an object be maintained before and after a collision, when this is non-physical behaviour. box2d is built to simulate physically realistic behaviours (within computational limits), and you are not letting it do that. So my advice is to think carefully about what you want to achieve in your game, and make your next move based on that. There are a few options:
Don't use box2d - if you just want simple axis-aligned bounding boxes bouncing around, always maintaining the same speed, then you should be able to write that yourself without too much trouble
Make everything travel at a constant speed - Do the following:
- set gravity to zero
- set the mass of all the bodies to the same value (or adjust each fixture's density so the final mass of all the bodies is the same)
- set the initial velocity of all bodies to the same value
- turn off rotation for all bodies
- set friction to zero for all fixtures
- don't use any joints
- don't apply any forces or impulses
- don't create bodies on top of other bodies (this is not an error, but it will solve the collision and give both bodies new velocities)
This should give the effect you are looking for, but it severely restricts what you can do. After listing all these restrictions this really looks like a poor choice, but it's here nonetheless.
Store the desired speed somewhere else and set the body velocity as necessary - you could implement a Collision Callback and have it set the bodies' speed's based on a speed stored elsewhere (e.g. on the entity that owns the body). That way it would reset the speed of a body after every collision. Warning: this will produce the non-physical behaviour I was talking about, and many things will end up looking funky as a result
- e.g. Ball
A
hits a slower moving ballB
as in the figure (where both are travelling in the same direction). Also, the masses and initial velocities work out so that case 3. from above applies. This means thatA
andB
will both have the same final direction. This is all fine and dandy in a normal collision because at mostA
will be moving with the same velocity asB
an they will remain in contact. However, if you try to enforce that the speeds before and after are the same, then after the collisionA
will be overlapping B! Now what? Maybe you can find an answer to this but it's not going to be pretty.
Also, your are going to have oblique collisions that will exchange some linear kinetic energy for rotational kinetic energy (reducing the linear velocity of the center of mass, while causing it to spin). Setting fixed rotation will solve this problem, at the cost of your objects not being able to rotate.
- e.g. Ball
Change your game - figure out a different design solution that's based around physically correct collisions, then use box2d normally. This is my preferred solution. I don't know your game design at all, so this may not be an option, but I encourage you to think creatively.
Please do not change the velocities after every step, that would be a huge waste of cpu time, not to mention you will still have to figure out ways to get around the problems arising in solution 3.
linearDamping in box2d works like Aerodynamic Drag. In layman's terms this means that fast moving objects will be slowed much quickly than slower moving objects. Increasing the linearDamping exaggerates this effect. angularDamping works exactly the same, except it applies to rotation instead of linear motion. Neither linearDamping nor angularDamping affect collisions.
I hope this helps!
No comments:
Post a Comment