Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  1. 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
  2. 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.
  3. 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();
});
like image 686
Razor Avatar asked Jun 27 '14 16:06

Razor


People also ask

How does a roulette wheel work?

To determine the winning number, a croupier spins a wheel in one direction, then spins a ball in the opposite direction around a tilted circular track running around the outer edge of the wheel.

Are roulette wheels balanced?

The majority of casinos worldwide tend to use roulette wheels of extremely high quality, wheels that are balanced with high precision.


1 Answers

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

  2. 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)

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

like image 137
Jasper Avatar answered Sep 25 '22 09:09

Jasper