0

How to: clamp influence of thrust, while allowing other forces to be infinite.

Example: A rocket can thrust in its rotated direction. Only explosions can push it past its top-speed. I'm looking for a theory more than code.

Any help would be appreciated.

SOLVED

EDIT: top-speed is determined by thrust speed and friction.

Thrust can stack onto velocity, but top-speed can be reached when friction is stronger than thrust speed.

vx = (vx + fx) *fr -- velocity = (velocity + force) *friction
vy = (vy + fy) *fr

When the velocity is high enough, addition of force will be deducted by friction.

fr = .9 : hard to see top speed

fr = .6 : easy to see top-speed

John Moore
  • 91
  • 1
  • 7
  • please provide your code and some more info so people who don't know love2d in detail will be able to help you easier. if this is possible in the love2d-framework simply apply a max speed only to self-propelled motion – Piglet Apr 18 '16 at 11:06
  • 1
    The speed of object is the sum of two independent speeds: "self-propelled motion" (which is limited by some constant) and "other factors" (which is unlimited). – Egor Skriptunoff Apr 18 '16 at 12:30
  • object `max = 50`, `if vel > 50` how can object `force` influence `vel`? Would `vel` absorb `force` .. – John Moore Apr 18 '16 at 12:57
  • `vel = vel1 + vel2`. `vel1` absorb `force` if force means running. `vel2` absorbs `force` if force means launching by man-cannon. `vel1` gets clamped, `vel2` is not. – Egor Skriptunoff Apr 18 '16 at 13:29

2 Answers2

0

Controls: left, right and thrust

The top speed of thrust can be adjusted with friction.

-- VARIABLES
player = {
    frc = .95, -- friction
    acc = .05, -- acceleration
    max = .5, -- acceleration max
    deg = 0, -- rotation in degree
    rad = 0 -- rotation in radian
    -- rotation is CW and 0 points to the right
}

-- MAIN UPDATE
function love.update()
    control(player)
    applyVelocity(player)
end

-- UPDATE
function control(a)
    if  L then addRotation(a,-5) end
    if  R then addRotation(a, 5) end
    if  U then thrustOn(a) else thrustOff(a) end
end
function applyVelocity(a)
    -- velocity + force
    a.vx = (a.vx + a.fx) *a.fr
    a.vy = (a.vy + a.fy) *a.fr
    -- position + velocity
    a.x = a.x + a.vx
    a.y = a.y + a.vy
end

-- OTHER
function thrustOn(a)
    accelerate(a)
    rotateDist(a)
end
function thrustOff(a)
    a.f = 0 -- integer of force is used to convert to point (x,y) with (rad)
    a.fx = 0
    a.fy = 0
end
function addRotation(a,deg)
    a.deg = a.deg + deg
    a.rad = math.rad(a.deg) -- math.sin/cos functions use radian instead of degree
end
function accelerate(a)
    a.f = a.f + a.acc
    if a.f > a.max then a.f = a.max end
end
function rotateDist(a)
    -- end point of force rotated from player
    a.fx = a.f *math.sin(a.rad)
    a.fy = a.f *math.cos(a.rad)
end
John Moore
  • 91
  • 1
  • 7
0

Using friction limited acceleration to set a max velocity precisely

The previous answer is correct that friction can set a limit to the velocity but the answer missed some details in regard to setting the limit.

First your velocity variable

vel = 0; //in pixels per frame. Start at 0 (or wherever you want)

And you want a particular max velocity in pixels per frame

maxVelocity  = 100; // set the maximum speed

And you have a particular maximum acceleration in pixels per frame2

maxAccel = 1; // The max acceleration will occur when accelerating from 0 

You now need to get the friction needed to stop the acceleration when the velocity reaches 100. We will call the unknown friction

friction = null;  // what we need to find out

You will be using the equation

vel = vel + maxAccel;  // accelerate 
vel = vel * friction;  // add friction

You know that friction should reduce the velocity after acceleration so it does not go over maxVelocity. So we need a value for friction that when applied to the maxVelocity + maxAccel is equal to maxVelocity

maxVelocity  = (maxVelocity + maxAccel) * friction;

Now just rearrange the equation to solve for the unknown friction to get

friction = maxVelocity / (maxVelocity + maxAccel);

Now you have a value for friction that will ensure your velocity will not exceed maxVelocity.

To extend it a little, you may want to add a boost that will give you short term extra velocity but you do not want that boost velocity to go over a limit. You could just recalculate friction to a new maxVelocity but that may not give you the kick you want as the top end of the velocity curve has low acceleration.

Another way is to provide additional acceleration while still keeping the same friction is to calculate additional acceleration required. We need to new vars.

maxBoostVelocity = 120; // max boost velocity
boostAccel = null; // this will have to be calculated using the friction we have

Using the same logic as above but rearranging the friction solution in terms of the new max velocity and with the known friction we get

boostAccel = ((maxBoostVelocity / friction )- maxBoostVelocity);

I like to use only the additional acceleration for boost so I don't have to touch the existing acceleration values. So I just subtract the original acceleration from the calculated boost to get what I want.

boostAccel = boostAccel - maxAccel;

So in some code

// the known limits
vel = 0;                 //in pixels per frame. Start at 0 (or wherever you want)
maxVelocity  = 100;      // set the maximum speed
maxAccel = 1;            // The max acceleration will occur when accelerating from 0 
maxBoostVelocity = 120;  // max boost velocity
accelerate = false;      // flag to indicate that we want to accelerate
boost = false;           // flag to indicate we want to boost
// the unknown friction and boost accel
boostAccel = null;       // this will have to be calculated using the friction we       
friction = null;         // what we need to find out
function applyAcceleration()
    if(boost){                 // is boosr flag true then add boost
        vel += boostAccel ;    // boost
    }
    if(accelerate || boost){   // is accelerate or boost flag true 
        vel += maxAccel;       // accelerate 
    }
    // always apply the friction after the accelerations 
    vel *= friction;           // apply friction
}
// in the init function calculate the friction and boost acceleration
function init(){
    friction = maxVelocity / (maxVelocity + maxAccel);
    boostAccel = ((maxBoostVelocity / friction )- maxBoostVelocity) - maxAccel;
}
Blindman67
  • 51,134
  • 11
  • 73
  • 136