How to make a realistic roulette ball spinning animation

I'm using PhysicsJS to make a 2D roulette ball spinning animation.

So far, I've implemented the following:

  • used a constraint so that the ball wouldn't "fly away":
    rigidConstraints.distanceConstraint( wheel, ball, 1 );
  • used drag to slow down the ball:
    world.add(Physics.integrator('verlet', { drag: 0.9 }));
  • made the wheel attract the ball, so that it would fall towards it when the drag has slowed down the ball enough
  • My questions:

  • how do I gradually slow down the ball spinning?
    I have already a very high drag value, but it doesn't look like it's doing anything
  • how do I make attraction towards the wheel work?
    The distance constraint should keep the ball from escaping, not from getting closer to the wheel.
  • why does angularVelocity: -0.005 not work at all on the wheel?
  • My code, also on 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();
    });
    

  • Drag has a bug in that version of PhysicsJS, try using the most updated version from github. https://github.com/wellcaffeinated/PhysicsJS/issues/94

  • Unfortunately the distance constraint imposes a fixed distance. So to prevent the ball's escape in that way, you'd need to implement your own behavior. (more below)

  • You'll have to change behavior: "static" to be behavior: "kinematic" . Static bodies don't ever move on their own.

  • To create a custom behavior check out the documentation here: https://github.com/wellcaffeinated/PhysicsJS/wiki/Behaviors#creating-a-custom-behavior

    In order to get the functionality you're describing, you'll need to do something like this:

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

    Of course, this is a "just get it done" way of doing this but it should work.

    链接地址: http://www.djcxy.com/p/21272.html

    上一篇: 这个模板语法是否可以改进?

    下一篇: 如何制作逼真的轮盘球旋转动画