【问题标题】:How to make a realistic roulette ball spinning animation如何制作逼真的轮盘赌球旋转动画
【发布时间】:2014-07-01 02:24:51
【问题描述】:

我正在使用PhysicsJS 制作一个 2D 轮盘赌球旋转动画。

到目前为止,我已经实现了以下内容:

  • 使用了constraint,这样球就不会“飞走”:
    rigidConstraints.distanceConstraint( wheel, ball, 1 );
  • 使用drag 让球减速:
    world.add(Physics.integrator('verlet', { drag: 0.9 }));
  • 让轮子吸引球,这样当阻力使球足够慢时,它会朝它下落

我的问题:

  1. 如何逐渐减慢球的旋转速度?
    我的drag 值已经很高了,但它看起来并没有做任何事情
  2. 如何让车轮产生吸引力?
    距离限制应防止球逃逸,而不是靠近车轮。
  3. 为什么 angularVelocity: -0.005 在方向盘上根本不起作用?

我的代码,也在JSfiddle

Physics(function (world) {
    var viewWidth = window.innerWidth
        ,viewHeight = window.innerHeight
        ,renderer
        ;

    world.add(Physics.integrator('verlet', {
        drag: 0.9
    }));

    var rigidConstraints = Physics.behavior('verlet-constraints', {
        iterations: 10
    });

    // create a renderer
    renderer = Physics.renderer('canvas', {
        el: 'viewport'
        ,width: viewWidth
        ,height: viewHeight
    });

    // add the renderer
    world.add(renderer);
    // render on each step
    world.on('step', function () {
        world.render();
    });

    // create some bodies
    var ball = Physics.body('circle', {
        x: viewWidth / 2
        ,y: viewHeight / 2 - 300
        ,vx: -0.05
        ,mass: 0.1
        ,radius: 10
        ,cof: 0.99
        ,styles: {
            fillStyle: '#cb4b16'
            ,angleIndicator: '#72240d'
        }
    })

    var wheel = Physics.body('circle', {
        x: viewWidth / 2
        ,y: viewHeight / 2
        ,angularVelocity: -0.005
        ,radius: 100
        ,mass: 100
        ,restitution: 0.35
        // ,cof: 0.99
        ,styles: {
            fillStyle: '#6c71c4'
            ,angleIndicator: '#3b3e6b'
        }
        ,treatment: "static"
    });

    world.add(ball);
    world.add(wheel);

    rigidConstraints.distanceConstraint( wheel, ball, 1 );

    world.add( rigidConstraints );

    // add things to the world
    world.add([
        Physics.behavior('interactive', { el: renderer.el })
        ,Physics.behavior('newtonian', { strength: 5 })
        ,Physics.behavior('body-impulse-response')
        ,Physics.behavior('body-collision-detection')
        ,Physics.behavior('sweep-prune')
    ]);

    // subscribe to ticker to advance the simulation
    Physics.util.ticker.on(function( time ) {
        world.step( time );
    });

    // start the ticker
    Physics.util.ticker.start();
});

【问题讨论】:

  • 这个问题似乎跑题了,因为它是关于物理的。
  • @duffymo 这是关于编程物理的,使用一个众所周知的 JS 库。游戏制作者一直都在这样做,并且有很多 SO 问题。
  • @mikemaccana 在我编辑之前,它可能被误认为是一个物理问题。现在措辞应该更清楚了。
  • 你可以滥用一个众所周知的 JS 库 b/c 你不了解物理。我认为这是其中一种情况。
  • @duffymo 如果您检查我的代码,您会看到例如角速度作为选项给出但被忽略。我不知道你为什么会把它或其他问题与缺乏对物理学的理解联系起来——这显然是一个代码问题。

标签: javascript physicsjs


【解决方案1】:
  1. Drag 在该版本的 PhysicsJS 中存在错误,请尝试使用 github 上的最新版本。 https://github.com/wellcaffeinated/PhysicsJS/issues/94

  2. 不幸的是,距离约束强加了一个固定的距离。所以为了防止球以这种方式逃跑,你需要实现你自己的行为。 (更多下文)

  3. 您必须将 behavior: "static" 更改为 behavior: "kinematic"。静态物体永远不会自行移动。

要创建自定义行为,请查看此处的文档:https://github.com/wellcaffeinated/PhysicsJS/wiki/Behaviors#creating-a-custom-behavior

为了获得您所描述的功能,您需要执行以下操作:

// in the behave method
// calculate the displacement of the ball from the wheel... something like....
disp.clone( wheel.state.pos ).vsub( ball.state.pos );
// if it's greater than max distance, then move it back inside the max radius
if ( disp.norm() > maxDist ){
    var moveBy = disp.norm() - maxDist;
    disp.normalize(); // unit vector towards the wheel
    disp.mult( moveBy );
    ball.state.pos.vadd( disp ); // move it back inside the max radius
}

当然,这是一种“直接完成”的方式,但它应该可以工作。

【讨论】:

  • 这回答了我 90% 的问题 - 唯一缺少的是 disp,它应该类似于 var disp = Physics.vector();(或从头开始)。感谢您的回答和图书馆!
  • 没错。您可以创建向量(并重复使用)或使用便签本功能
猜你喜欢
  • 1970-01-01
  • 2020-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多