Hello everyone,
I've been playing around with Box2D and I'm quite surprised there's no simple way to limit an object's velocity.
A workaround I found is to check the current velocity of the object and if it's too high, just apply a counter-force to the desired value. But this is very brutal and looks somewhat a bit jittery.
Is there a better way to do that?
Thanks in advance.
Physics - Limit velocity
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
- FullyLucid
- Prole
- Posts: 5
- Joined: Fri Dec 04, 2015 6:36 pm
- Location: Salt Lake City, Utah
- Contact:
Re: Physics - Limit velocity
You should be able to just set it's linear velocity if it's higher than you want. Other than that, there's a settings file in Box2D itself that has a maximum linear velocity for all solid bodies, not individually.
You could also play with body:setLinearDamping() since you're getting oscillation you don't want, but I think applying an inverse impulse and adjusting for oscillation is plenty slower than changing the linear velocity by hand.
Code: Select all
local xvel, yvel = body:getLinearVelocity()
body:setLinearVelocity( math.min(xvel, max_xvel), math.min(yvel, max_yvel) )
One rogue, one life.
Re: Physics - Limit velocity
Hey there, thanks for your answer! Unfortunately, that still is very buggy and looks really jittery, especially on small frame drops. Is there a less brutal way of doing it?FullyLucid wrote:-snip-
- ArchAngel075
- Party member
- Posts: 319
- Joined: Mon Jun 24, 2013 5:16 am
Re: Physics - Limit velocity
I would look at it by taking collisions with the limited body and after resolving check velocity and alter/decrease etc.
This should catch that instant it speeds up or slows down on collide and instead 'lock' the velocity after collisions.
Similarly any 'addForce/addVelocity' calls can be wrapped to prevent it from exceeding the limit?
This should catch that instant it speeds up or slows down on collide and instead 'lock' the velocity after collisions.
Similarly any 'addForce/addVelocity' calls can be wrapped to prevent it from exceeding the limit?
Re: Physics - Limit velocity
Sorry for reviving this old thread, but I've a problem with this code. I want to limit the velocity of my object that got it through applyLinearImpulse:FullyLucid wrote: ↑Thu Dec 10, 2015 6:19 pm You should be able to just set it's linear velocity if it's higher than you want. Other than that, there's a settings file in Box2D itself that has a maximum linear velocity for all solid bodies, not individually.You could also play with body:setLinearDamping() since you're getting oscillation you don't want, but I think applying an inverse impulse and adjusting for oscillation is plenty slower than changing the linear velocity by hand.Code: Select all
local xvel, yvel = body:getLinearVelocity() body:setLinearVelocity( math.min(xvel, max_xvel), math.min(yvel, max_yvel) )
Code: Select all
if love.mouse.isDown(1) and canShot
canShot = false
local clickVector = Vector(love.mouse:getX(), love.mouse:getY())
local bulletVector = Vector(body:getX(), body:getY())
local distVector = (clickVector - bulletVector)
local dirVector = distVector:normalized()
body:applyLinearImpulse(dirVector.x * power, dirVector.y * power) --power is defined somewhere else
end
local velX, velY = body:getLinearVelocity()
body:setLinearVelocity(math.min(velX, maxSpeed), math.min(velY, maxSpeed)) --maxSpeed is defined somewhere else
In result applyLinearImpulse + existing force from bouncing back is stronger than my maxSpeed, eventually, and for some reason it does not get limited with the code above. However, once my impulse is over and the object reaches it highest point and falls down again, it gets limited, and thus slowly falls down.
What is the correct way to limit the speed of my object when the velocity is resulting from applyLinearImpulse?
Visual Studio Code Template • RichLÖVE Mobile (AdMob+UnityAds+PlayGamesServices+GameCenter) • Add me on Discord
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░█░░░░░█░░█────
─▄▄──█░░░▀█▀░░░█──▄▄─
█░░█─▀▄░░░░░░░▄▀─█░░█
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░█░░░░░█░░█────
─▄▄──█░░░▀█▀░░░█──▄▄─
█░░█─▀▄░░░░░░░▄▀─█░░█
Re: Physics - Limit velocity
I recommend:
changeInVelocity = finalVelocity - initialVelocity
impulse = mass*changeInVelocity
Apply the impulse only once to achieve the DESIRED velocity.
The "desired" velocity should remain constant unless one of the following is involved:
1.gravity 2.collisions 3.linear damping 4.joints.
If you want to maintain a constant velocity over time, then use ApplyForce.
setLinearVelocity is not recommended for dynamic bodies, because it overrides the effects of "collision responses" and doesn't look realistic.
Code: Select all
--- Clamp length
-- @param v vector
-- @param d maximum length
-- @return initial length of the vector
function clamp(v, d)
local x, y = v.x, v.y
local d2 = math.sqrt(x*x + y*y)
if d2 > d then
v.x = x/d2*d
v.y = y/d2*d
end
return d2
end
If you want to change the velocity using impulses then:What is the correct way to limit the speed of my object when the velocity is resulting from applyLinearImpulse?
changeInVelocity = finalVelocity - initialVelocity
impulse = mass*changeInVelocity
Apply the impulse only once to achieve the DESIRED velocity.
The "desired" velocity should remain constant unless one of the following is involved:
1.gravity 2.collisions 3.linear damping 4.joints.
If you want to maintain a constant velocity over time, then use ApplyForce.
setLinearVelocity is not recommended for dynamic bodies, because it overrides the effects of "collision responses" and doesn't look realistic.
Re: Physics - Limit velocity
Thank you for your reply, this helped a lot, although it took me a while to get my head around this. Indeed, it makes more sense to calculate the correct vector in before-hand, instead of correcting the vector with additional forces afterwards.ivan wrote: ↑Fri Dec 08, 2017 3:46 pm If you want to change the velocity using impulses then:
changeInVelocity = finalVelocity - initialVelocity
impulse = mass*changeInVelocity
Apply the impulse only once to achieve the DESIRED velocity.
The "desired" velocity should remain constant unless one of the following is involved:
1.gravity 2.collisions 3.linear damping 4.joints.
If you want to maintain a constant velocity over time, then use ApplyForce.
setLinearVelocity is not recommended for dynamic bodies, because it overrides the effects of "collision responses" and doesn't look realistic.
First of all, I didn't know that any impulses respecting the mass of my body, but this makes sense. I couldn't see this effect when changing my mass, because I was setting the mass before creating fixtures for my body. After creating the fixtures it changed my mass.
So to sum it up with my own words:
- I get the linear velocity of my body
- I multiply my power with my direction and subtract the current linear velocity from it
- I multiply the result with the mass of the body
- The result is the force that will move my object the same distance without respecting mass and ignoring initial velocity <- this gonna be applied as impulse
- since the initial velocity of my object needs to be multiplied by the mass to get enough counter force on the impulse, I have to multiply the mass to it, always
For the community, here is my solution: An update function code to shoot an object in the direction of my mouse click without respecting mass and ignoring initial velocity. (setMass will be called at the end of the enter function, canShot will be set true on ground collision, power is pre-configured):
Code: Select all
if love.mouse.isDown(1) and canShot and not releasedShot then
canShot = false
releasedShot = true
local clickVector = Vector(love.mouse:getX(), love.mouse:getY())
local bulletPosVector = Vector(body:getX(), body:getY())
local bulletVelVector = Vector(body:getLinearVelocity())
local distVector = (clickVector - bulletPosVector)
local dirVector = distVector:normalized()
body:applyLinearImpulse(body:getMass() * (power * dirVector.x - bulletVelVector.x), body:getMass() * (power * dirVector.y - bulletVelVector.y))
body:applyAngularImpulse(dirVector.x * power, dirVector.y * power) -- rotation can stay wild!!!
elseif canShot and releasedShot and not love.mouse.isDown(1) then
releasedShot = false
end
Any suggestions? I'm new to this and I appreciate any feedback to improve myself.
I've to admit, I don't get the exact use for this function. Can you explain further?ivan wrote: ↑Fri Dec 08, 2017 3:46 pm I recommend:Code: Select all
--- Clamp length -- @param v vector -- @param d maximum length -- @return initial length of the vector function clamp(v, d) local x, y = v.x, v.y local d2 = math.sqrt(x*x + y*y) if d2 > d then v.x = x/d2*d v.y = y/d2*d end return d2 end
Visual Studio Code Template • RichLÖVE Mobile (AdMob+UnityAds+PlayGamesServices+GameCenter) • Add me on Discord
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░█░░░░░█░░█────
─▄▄──█░░░▀█▀░░░█──▄▄─
█░░█─▀▄░░░░░░░▄▀─█░░█
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░█░░░░░█░░█────
─▄▄──█░░░▀█▀░░░█──▄▄─
█░░█─▀▄░░░░░░░▄▀─█░░█
Re: Physics - Limit velocity
modiX, you're on the right path, but your terminology is slightly off.
Please note that force and power mean very specific things in physics.
Ok, back to your question - you want to limit the velocity of a body.
The easiest way to do that is using linear damping.
If you want to "clamp" the velocity to an exact value without the "easing" effect of damping you can try:
1. Limit the velocity ONLY if it exceeds maxSpeed
2. Overwrite the velocity if it's non-zero
3. Using a linear impulse to achieve an exact velocity
in your case the "target velocity" can be calculated as:
Again, the linear impulse must be applied once and it won't work precisely if there is gravity,joints or damping involved.
Please note that force and power mean very specific things in physics.
Ok, back to your question - you want to limit the velocity of a body.
The easiest way to do that is using linear damping.
If you want to "clamp" the velocity to an exact value without the "easing" effect of damping you can try:
1. Limit the velocity ONLY if it exceeds maxSpeed
Code: Select all
function clamp(x, y, d)
local d2 = math.sqrt(x*x + y*y)
if d2 > d then
x = x/d2*d
y = y/d2*d
end
return x, y, d2
end
--- Example:
local vx, vy = body:getLinearVelocity()
-- limits the velocity ONLY if it exceeds maxSpeed:
vx, vy = clamp(vx, vy, maxSpeed)
body:setLinearVelocity(vx, vy)
Code: Select all
function normalize(x, y, d)
d = d or 1
local d2 = math.sqrt(x*x + y*y)
if d2 > 0 then
x = x/d2*d
y = y/d2*d
end
return x, y, d2
end
--- Example:
local vx, vy = body:getLinearVelocity()
vx, vy = normalize(vx, vy, maxSpeed)
body:setLinearVelocity(vx, vy)
Code: Select all
local tx, ty = ? -- target or final velocity
local vx, vy = body:getLinearVelocity() -- initial velocity
local dx, dy = tx - vx, ty - vy -- change in velocity
local ix, iy = dx*mass, dy*mass -- impulse = change in velocity*mass
body:applyLinearImpulse(ix, iy)
Code: Select all
local mx, my = love.mouse.getPosition()
local bx, by = body:getPosition()
local cx, cy = mx - bx, my - by
-- target velocity:
local tx, ty = normalize(cx, cy, targetSpeed)
Re: Physics - Limit velocity
Hey ivan, you are right, my terminology is slightly off, indeed. My solution will not limit the vector, it will apply a static force in the clicked direction, always. So even when my click is only few pixels away, it will still apply a strong force. But, tbh, I like it this way, I'm satisfied with the result.ivan wrote: ↑Sat Dec 09, 2017 7:21 am modiX, you're on the right path, but your terminology is slightly off.
Please note that force and power mean very specific things in physics.
Ok, back to your question - you want to limit the velocity of a body.
The easiest way to do that is using linear damping.
Now, I also get your clamp function. It's like the hump's vector:normalized(), but instead of changing the vector to always have a length of 1, it will decrease the vector to the given length d. d2 is my current length (result of Pythagoras) and then you use a simple rule of three to determine the new vector coordinates. This function will be helpful for me in future, I know.
Thank you for this, much love.
Visual Studio Code Template • RichLÖVE Mobile (AdMob+UnityAds+PlayGamesServices+GameCenter) • Add me on Discord
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░█░░░░░█░░█────
─▄▄──█░░░▀█▀░░░█──▄▄─
█░░█─▀▄░░░░░░░▄▀─█░░█
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░█░░░░░█░░█────
─▄▄──█░░░▀█▀░░░█──▄▄─
█░░█─▀▄░░░░░░░▄▀─█░░█
Who is online
Users browsing this forum: Bing [Bot] and 10 guests