钳位球员的推力影响力

时间:2016-04-18 09:22:54

标签: lua game-physics velocity love2d clamp

如何:钳制推力的影响,同时让其他力量无限。

示例:火箭可以沿其旋转方向推进。只有爆炸才能超越它的最高速度。我正在寻找的理论不仅仅是代码。

任何帮助都将不胜感激。

解决

编辑:最高速度取决于推力和摩擦力。

推力可以叠加到速度上,但是当摩擦力比推力速度更强时,可以达到最高速度。

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

当速度足够高时,摩擦会减去力的增加。

fr = .9:很难看到最高速度

fr = .6:很容易看到最高速度

2 个答案:

答案 0 :(得分:0)

控制:左,右和推力

可以通过摩擦调节最高推力速度。

-- 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

答案 1 :(得分:0)

使用摩擦限制加速度精确设置最大速度

之前的答案是正确的,摩擦可以设定速度限制,但答案错过了设置限制的一些细节。

首先是你的速度变量

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

你想要一个特定的最大速度,以每帧像素为单位

maxVelocity  = 100; // set the maximum speed

你有一个特定的最大加速度,每帧像素 2

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

当速度达到100时,你现在需要获得停止加速所需的摩擦力。我们将称之为未知摩擦

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

您将使用等式

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

你知道friction应该在加速后降低速度,因此它不会超过maxVelocity。因此,我们需要friction的值,当应用于maxVelocity + maxAccel时,该值等于maxVelocity

maxVelocity  = (maxVelocity + maxAccel) * friction;

现在只需重新排列方程式即可解决未知friction来获取

friction = maxVelocity / (maxVelocity + maxAccel);

现在您拥有friction的值,可确保您的速度不会超过maxVelocity

为了延长它,您可能需要添加一个能够为您提供短期额外速度的提升,但您不希望提升速度超过限制。您可以重新计算friction到新maxVelocity,但由于速度曲线的顶端加速度较低,可能无法为您提供所需的踢法。

另一种方法是提供额外的加速度,同时仍然保持相同的摩擦力来计算所需的额外加速度。我们需要新的变种。

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

使用与上述相同的逻辑,但根据新的最大速度和已知摩擦重新排列摩擦解决方案

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

我只想使用额外的加速度来提升,所以我不必触及现有的加速度值。所以我只是从计算出的加速中减去原始加速度,得到我想要的东西。

boostAccel = boostAccel - maxAccel;

所以在某些代码中

// 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;
}