11.巴士停不下来:使用固定或按比例方式实现减速

11.The Bus That Couldn’t Slow Down: implementing braking using fixed or proportional slow-down

This post is about two different ways of implementing braking.

这篇帖子讨论两种实现减速的不同途径。

In a recent post, we saw how to implement a drifting, asteroids-style of movement (andhow to limit the maximum speed). As is traditional in asteroids, there was no braking: you just accelerate in the opposite direction to slow down. In this post, we’ll look at how two different ways to implement braking (and to fit with the title, our spaceship will become a bus).

在最近的帖子里,我们了解了如何实现漂移,即类似星球大战游戏风格的运动(以及如何限制最大速度值)。在传统的大战游戏里没有减速功能:你仅能通过朝着相反的方向加速来使运行减慢。在这篇帖子里,我们将看到如何通过两种不同的途径实现减速(为了迎合主题,飞船将改为巴士)。

Fixed Braking

固定的减速

One way to implement braking is to subtract a fixed amount from the current speed. (In effect, this performs an acceleration in the opposite direction to the one in which you are currentlytravelling — not pointing).We saw in our last post how to convert from cartesian to polar speeds, where speed becomes a single number. We can augment the code from our last post to add braking:

实现减速的一种途径是给当前的速度减去一个固定值。(实际上,这是给当前行进方向施加了一个反向的加速度)。从上一篇帖子里我们了解了如何将速度值从笛卡尔坐标形式转换为极坐标形式,从而将速度值变成了一个单独的数字。我们不妨给上一篇帖子里的代码添加减速功能:

    private void clampSpeedAndBrake()
    {
        double dir = calculateDirection(speedX, speedY);
        double speed = calculateMagnitude(speedX, speedY);
        
        final double MAX_SPEED = 10;
        
        if (speed > MAX_SPEED)
        {
            speed = MAX_SPEED;
        }
        
        if (Greenfoot.isKeyDown("down"))
        {
            speed = speed - 0.1;
        }
        
        speedX = calculateX(dir, speed);
        speedY = calculateY(dir, speed);
    }

The braking is the second if-statement: if they’re pressing the down arrow, reduce the speed.

第二个if语句里便是减速功能:如何按下down键,速度值将减少。

Problem: Pedalling Backwards To Brake

有一个问题:减速时倒退

In the code above, braking works fine. But if you increase the strength of the braking, you’ll find a very strange effect. If that speed reduction is set to, say, 1.5, you’ll find that holding the brake key when stopped will jiggle you around. Consider what the above code does if your speed is zero: it reduces the speed to a negative number, but once that gets converted back to cartesian, it means that you are no longer stationary. This problem is quite easy to fix, by using the maximum function to make sure that speed is either reduced or zero, whichever is larger (you might need to think about that for a minute):

在上面代码能很好地实现减速。但是如果增加减速的力度,你回发现一个奇怪的效果。例如,若是速度降低到1.5,你会发现按住减速键时巴士会不停地摇动。如果速度为0的话考虑以上代码会做些什么:它将速度值减少为一个负数,但是一旦将其转回到笛卡尔坐标,这将意味着巴士不可能固定不动。这个问题很容易解决,可以使用极大值函数去保证速度要么减少要么为0,而不论其值有多大(你或许需要思考一会)。

        if (Greenfoot.isKeyDown("down"))
        {
            speed = Math.max(0, speed - 0.1);
        }

Proportional Braking

按比例减速

The alternative to what I’ve called fixed braking (which reduces your speed by a fixed amount each frame) is proportional braking. The idea behind proportional braking is that instead of subtracting a fixed amount from your speed, you instead take off a proportion. So let’s say that each frame you brake should slow you by 2%: you just multiply the speed by 0.98, making the braking code:

固定减速(在每一帧中给速度减去一个固定值)的一种替代方式是按比例减速。该方式的原理是给速度乘上一个比例来代替减去一个固定值。因此假如每一帧应该减速2%:你仅仅需要将速度值乘以0.98即可,代码如下:

        if (Greenfoot.isKeyDown("down"))
        {
            speed = speed * 0.98;
        }

Problem: Coming To A Complete Stop

有一个问题:难以完全停下来

One problem with proportional braking is that it gets a bit irritating as you come close to stopping. There is a thought experiment (not to be confused withZeno’s paradox) that runs: “if every second you halve the distance between you and your destination, will you ever get there?”. And so it is in proportional braking: if your speed always reduces by 2%, will it ever actually hit zero — will you ever actually stop? In mathematics, the answer is: no (\forall n. 0.98^n > 0). In computing the answer is: eventually (because eventually the number will become so small it will be represented by zero).

使用按比例减速的一个问题是巴士没法完全停止下来,这是很让人气恼的。有一个思维实验提到:“如果每一秒将自己和目的地的距离减半,那么你将最终能到达目的吗?”同样地在按比例减速中:如果速度一直减少2%,最终会到达零——即最终停下来吗?在数学中,答案是:否(\forall n. 0.98^n > 0)。在计算机信息处理中答案是:最终是(因为最后数字会变得足够小从而用零来表示)。

Practically speaking (ignoring all this theory fluff!), the best thing to do is add a special case that once your speed is close enough to zero, just set it to zero. Not elegant, but effective:

事实上来说(忽略所有理论上的误差),最好的办法是添加一个特殊的情况,即一旦速度值足够接近于零则将其设为零。不够优美,但是实用:

        if (Greenfoot.isKeyDown("down"))
        {
            speed = speed * 0.98;
        }
        if (speed <= 0.05)
        {
            speed = 0;
        }

You can have a play with the two different styles of braking in this scenario. The bus with an “F” on it is controlled by WASD and does fixed braking, while the bus with a “P” on it is controlled by the arrow keys and does proportional braking. There’s no single right answer to which is a better system, but having played around, I prefer the fixed braking — the proportional braking takes a long time to come to a complete halt.

你可以玩一下这个游戏剧本,体会两种不同的减速方式。标记为“F”的巴士使用WASD键来控制,使用固定减速,而标记为“P”的使用方向键控制,使用按比例减速。关于哪个系统更好没有确切的答案,但是通过试玩我更加青睐固定减速方式——按比例减速需要很长时间来达到完全停止。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值