Search code examples
luagame-physicsvelocitylove2dclamp

Clamp player thrust influence


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


Solution

  • 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