Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ease on spinning wheel

I'm creating a Wheel of Fortune like game and currently working on the wheel. I want to add ease out effect to the wheel to make the spin realistic. I have no prior knowledge on easing, so I implemented the code in Introduction to Easing in JavaScript.

JSFiddle

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var img = new Image();
img.src = "data:image/png;base64,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";

context.resetTransform();
context.translate(205, 205);
context.drawImage(img, -201,-201,402,402);

var angle = 0;
var angularVelocity = .01;

function draw() {
	// ease out
	angularVelocity	+= .0035;
	angle -= (1 / angularVelocity);
	
	context.resetTransform();
	context.clearRect(0, 0, canvas.width, canvas.height);
	context.translate(205, 205);
	context.rotate(angle * Math.PI/180);
	context.drawImage(img, -201,-201,402,402);
	
	spin = requestAnimationFrame(draw);
}

function startSpin() {
	spin = requestAnimationFrame(draw);
}
body {
  background: gainsboro;
  margin: 0;
}
#container {
  position: relative;
  margin: 20px;
  margin-left: 40px;
  display: table;
}
canvas {
  background: white;
  box-shadow: 0 0 3px rgba(0,0,0,.2);
}
input {
  display: block;
  padding: 5px 10px;
  margin: auto;
}
img {
  height: 40px;
  position: absolute;
  top: 185px;
  left: -33px;
}
<div id="container">
	<img src="http://i1115.photobucket.com/albums/k544/akinuri/arrow.png" />
	<canvas id="canvas" width="410" height="410"></canvas>
	<input type="button" value="Spin" onclick="startSpin()"/>
</div>

Ease out works fine but it's not complete. Spin doesn't end. I want to end it when it's too slow. I don't know what I should be checking to end the spinning. How do I end it?


Update: Alex's answer solved the problem, but I wanted to add another feature. Spin always ends at 100. This isn't realistic. It should vary. So I used a dynamic max velocity instead of 1.

JSFiddle

var angle           = 0;
var angularVelocity = 0.001;
var minVelocity     = 0.9;
var maxVelocity     = 0;

function draw() {
    angularVelocity += .0025;
    angle -= (1 / angularVelocity);

    context.resetTransform();
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.translate(205, 205);
    context.rotate(angle * Math.PI/180);
    context.drawImage(img, -201,-201,402,402);

    if (angularVelocity < maxVelocity){ 
        spin = requestAnimationFrame(draw);
    }
}

function startSpin() {
    angularVelocity = 0.001;
    maxVelocity     = (Math.random() * 1.5).toFixed(2);
    while (maxVelocity < minVelocity) {
        maxVelocity     = (Math.random() * 1.5).toFixed(2);
    }
    spin = requestAnimationFrame(draw);
}
like image 712
akinuri Avatar asked Feb 26 '16 12:02

akinuri


2 Answers

Try this=) Updated:

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var img = new Image();
img.src = "data:image/png;base64,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";

context.resetTransform();
context.translate(205, 205);
context.drawImage(img, -201,-201,402,402);

var angle = 0;
var angularVelocity = .01;

function draw() {
	// ease out
	angularVelocity	+= .0035;
    
	angle -= (1 / angularVelocity);
    
	context.resetTransform();
	context.clearRect(0, 0, canvas.width, canvas.height);
	context.translate(205, 205);
	context.rotate(angle * Math.PI/180);
	context.drawImage(img, -201,-201,402,402);
	if (angularVelocity+0.1<1){ 
         	 spin = requestAnimationFrame(draw);
        }
}

function startSpin() {
    
        angularVelocity = .01;
	spin = requestAnimationFrame(draw);
}
body {
  background: gainsboro;
  margin: 0;
}
#container {
  position: relative;
  margin: 20px;
  margin-left: 40px;
  display: table;
}
canvas {
  background: white;
  box-shadow: 0 0 3px rgba(0,0,0,.2);
}
input {
  display: block;
  padding: 5px 10px;
  margin: auto;
}
img {
  height: 40px;
  position: absolute;
  top: 185px;
  left: -33px;
}
<div id="container">
	<img src="data:image/png;base64,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" id="arrow" />
	<canvas id="canvas" width="410" height="410"></canvas>
	<input type="button" value="Spin" onclick="startSpin()"/>
</div>
like image 50
Alexandr Kudryashov Avatar answered Sep 21 '22 21:09

Alexandr Kudryashov


A better ease

Though the answer given solves the problem there is a general solution to the ease function. The reason I give this answer even though there is an accepted answer is that the accepted answer suffers from one major drawback. It requires that the animation runs at a constant frame rate. If the frame rate drops the wheel will appear to slow down. If you include the time in the equation the use of the derivative to change the position will change the stop position making the whole function indeterminate (angularVelocity += .0035 * timeStep) does not work, there is no linear solution to this method. (I have worked in the (gambling) gaming industry and an indeterminate function would never pass accreditation, nor would an operator want to use such a function in their machines).

You need a function that you can precisely set the prize before the spin, you want an equation that is not affected by frame time, and not on the previous machine state.

The solution is a general ease function of which there are many flavours. It is simply the anti derivative of the function in the previous answer in a more usable form.

Ease

If you graph the math function y = x2 you will see a parabola centered at x = 0 and at x = 1 it has risen to y = 1. If you consider the values from x = 0 to x = 1 to be our range this simple formula has given us an easeOut function. For any value of x in the range x >= 0and x <= 1 we get an adjusted value for y. Effectively converting a linear value into a curve.

But need EaseIn

We want the opposite, we need the formula that has the parabola upside down, with the maxima at y = 1 when x = 1 and at x = 0 we want y = 0. This is easy to do with the above formula.

  • First to flip it make the result negative. y = -x2
  • Then we need to move the maxima up the y axis by 1 so add one: y = 1-x2
  • Now we need to move the parabola to the right by one unit so sub one from x. y = 1 - (x - 1)2

So now we have a new curve for x >= 0 and x <= 1 that eases in as x approaches 1.

Let's create two functions for the easeIn and easeOut, we will put them in a ease object to keep it organised. In the functions we want to ensure that if x < 0 and x > 1 we don't get bad values so we need to clamp x to the range 0 to 1.

var easing = {
    easeOut : function( x ) {        
        return Math.pow( Math.min(1, Math.max(0, x) ), 2);
    },
    easeIn : function( x ) {
        return 1 - Math.pow( Math.min(1, Math.max(0, x) ) - 1, 2);
    }
}

Normalised Units.

But 0 to 1 does not fit my solution. No is does not but one is easy to change via multiplication.

So you have the wheel you want to spin. You know how long you want it to spin and you know where you want it to stop.

const NUMBER_PRIZES = 10; // number of prizes on the wheel.
const PRIZE_CENTER = Math.PI / NUMBER_PRIZES; // center of the prize
const DEG360 = Math.PI * 2; // use PI * two a few times so make a constant to represent 360 deg.
var timeToSpin = 10;  // ten seconds.
var whereToStop = 0; // Start pos
var startTime = 0 ; // if the value of start time is undefined this will mean we want to start
var startPos = 0; // wheel start pos

As we want to reset the wheel many times lets create a function to get a spin

var spinTheWheel = function(toPrize){
    whereToStop %= DEG360;  // Normalise the current position. This will not move it
    startPos = whereToStop;  // we need the start pos
    // We need to move the wheel to the start so we can get the correct prize
    whereToStop += DEG360 - whereToStop; 

    whereToStop += DEG360 * 2;  // At least two turns
    // Now get a random prize add a random position to the wheel stopping pos
    whereToStop += (toPrize / NUMBER_PRIZES) * DEG360;
    // we want the wheel to stop in the center of the prize so rotate by half a prize sector
    whereToStop += PRIZE_CENTER;
}

An event handler for the spin button

var spin = function () {
    var time = new Date().valueOf();
    // make sure we are not spinning
    if(time - startTime > timeToSpin * 1000){
        startTime = undefined;  // reset start time
        // get a random prize
        spinTheWheel ( Math.floor(Math.Random() * NUMBER_PRIZES));
    }
}

So now we are ready to animate. I will assume that the animation is running continuously.

// function to draw the wheel.
function drawWheel (wheelPos) {} // todo

// main animation loop
function update(time) {  // request frame gives us the time as an argument.

    var spinTime, wheel;  // vars we need

    // is there a new spin ???
    if(startTime === undefined) { // new start 
        startTime = time;   // set the time now;
    }

    // get the amount of time the wheel has been spinning
    spinTime = (time - startTime);

    // now as the spin time is in seconds and we want normalise it to a range of 0 - 1;
    // we dont care if the spin time goes out of range as the easeOut function is clamped
    spinTime /= timeToSpin * 1000; // so divide by number of milliseconds.

    // Now use the easeOut function to get the wheel pos in terms of spin time
    wheel = easing.ease(spinTime);

    // the wheel pos is in the range 0 to 1 so scale it to fit the requiered spin
    wheel *= whereToStop - startPos;

    // Now add the startPos back to the wheel pos.
    wheel += startPos;

    // Draw the wheel.
    drawWheel(wheel);

    // to know if the wheel is at a prize
    if(spinTime >= 1) { 
        // todo 
        // your prize code here
    }


    requestAnimationFrame(update)
}
// start it.
requestAnimationFrame(update)

This method will always stop the wheel at the correct time and correct position. The ease function gives a value from 0 to 1 and we use that to get wheel position with a simple multiplication. The input value is simply the normalised time. Which just needs us to divide the time by the length of time for the spin. As the ease functions are clamped we don't have to worry about values out side the range as the math takes care of that for us.

Changing the curve.

The ease function I provided does not give you the ability to change the ease amount. We may want to have the ease very fast at the start and then ease in very slowly, or have it only have a very slight ease. Luck has it that in math the power of a number between 0 and 1 never gets greater than 1. We can use this to change the ease amount by providing a value to set the ease power. It requires a little modification of the easeIn function.

var easing = {
    easeOut : function( x ) {        
        return Math.pow( Math.min(1, Math.max(0, x) ), 2);
    },
    easeIn : function( x ) {
        return 1 - Math.pow( Math.min(1, Math.max(0, x) ) - 1, 2);
    },    
    ease : function( x , pow) {  // add the power. the ease amount
        // need to clamp the power so it does not go in the negative        
        return 1 - Math.pow(1 - Math.min(1, Math.max(0, x) ), Math.max(0, pow));
    }
}

You now have a general purpose ease function. Changing the value of pow will change the ease. As raising a number to the power of a fraction is the same as the root of the inverse of the fraction 40.5 = 22 the ease function also does ease out when the value is less than 1. If pow is one then there is no ease. A value greater then one starts to ease the function in.

easing.ease(val, 0.5); // is an ease out
easing.ease(val, 2); // is an ease in
easing.ease(val, 1); // is no easing at all
easing.ease(val, 6); // is a very strong easein. fast at start slow to stop.

Bonus easeInOut

While I am here I might as well add the function for easeInOut

var easing = {
    easeOut : function( x ) {        
        return Math.pow( Math.min(1, Math.max(0, x) ), 2);
    },
    easeIn : function( x ) {
        return 1 - Math.pow( Math.min(1, Math.max(0, x) ) - 1, 2);
    },    
    ease : function( x , pow) {  // add the power. the ease amount
        // need to clamp the power so it does not go in the negative        
        return 1 - Math.pow(1 - Math.min(1, Math.max(0, x) ), Math.max(pow));
    },
    easeInOut = function (x, pow) {
        pow = Math.max(0, pow); // clamp pow to >= 0
        x = Math.min(1, Math.max(0, x)); // clamp x >= 0 and <= 1
        var xx = Math.pow(x, pow);
        return xx / (xx + Math.pow(1-x, pow))
    }
}

There are many ease functions and they can do a wide range of motions, they can even return outside the range to give bounces at the start and end if wanted, or even add notches (step downs) to the spin. The important thing is that the input value of the ease function is with in the normalised range and that the start x = 0 and end x = 1 end at y = 0 and y = 1 respectively. This makes the function totally determinate and time invariant, You can go backward as easily as forward.

like image 45
Blindman67 Avatar answered Sep 17 '22 21:09

Blindman67