FF: Rotate to angle, optimized and removed error
Calculate shortest distance to target angle / rotation given the specific velocity
-------------------------------------------------------------------------------
function rotateAngle( currentAngle:Number, targetAngle:Number, angularVelocity:Number = 1 ):Number
{
angleMin = currentAngle < targetAngle ? currentAngle : targetAngle;
angleMax = currentAngle > targetAngle ? currentAngle : targetAngle;
// angular difference
distance = angleMax - angleMin;
// distance from inverted unit circle
inverse = 360 - distance;
// calc native direction
direction = currentAngle > targetAngle ? (+1) : (-1) ;
// when distance is less then inverted distance, the direction will become inverted.
return distance <= angularVelocity ? 0 : angularVelocity * direction * ( distance < inverse ? -1 : 1 );
}
-------------------------------------------------------------------------------
// controls : click to pause, right-click to update on pause
/**
* Copyright WLAD ( http://wonderfl.net/user/WLAD )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/A1wZ
*/
/// @mxmlc -swf-version 15
// forked from WLAD's Shortest rotation to angle - speed test
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.geom.Point;
[SWF(width="465", height="465")]
public class MXMLC extends Sprite {
private var angleMin:Number;
private var angleMax:Number;
private var distance:Number;
private var inverse:Number;
private var direction:int;
///---------------------------
/// ORIGINAL FUNCTION |
///---------------------------
/*
source : http://wonderfl.net/c/6QOT
/// r - rotation = alpha, t = target rotation = beta.
private function myRotFunc(r:int, t:int, spd:Number = 1 ):Number
{
var trMx:int = t > r ? t : r;
var trMn:int = t < r ? t : r;
var m:int = trMx - trMn;
var s:int = 360 - trMx + trMn;
//var dir:int = (r > t ? 1 : -1) * (m > s ? 1 : -1);
//m = m < s ? m : s;
var dir:int = (r > t ? 1 : -1);
if(m > s)
{ m = m; }
else
{ m = s; dir = -dir; }
return m <= spd ? 0 : spd * dir;
}
*/
///-----------------------
/// NEW FUNCTION |
///-----------------------
private function rotateAngle( currentAngle:Number, targetAngle:Number, angularVelocity:Number = 1 ):Number
{
angleMin = currentAngle < targetAngle ? currentAngle : targetAngle;
angleMax = currentAngle > targetAngle ? currentAngle : targetAngle;
// angular difference
distance = angleMax - angleMin;
// distance from inverted unit circle
inverse = 360 - distance;
// calc native direction
direction = currentAngle > targetAngle ? (+1) : (-1) ;
// when distance is less then inverted distance, the direction will become inverted.
return distance <= angularVelocity ? 0 : angularVelocity * direction * ( distance < inverse ? -1 : 1 );
}
///---------------
/// UPDATE |
///---------------
private function update(e:*=null):void
{
var mouseAngle:Number = Math.atan2( stage.mouseY - arrow.y, stage.mouseX - arrow.x );
var a:Number = arrow.rotation;
var b:Number = mouseAngle * 180 / Math.PI;
var delta:Number = rotateAngle( a, b, 5.33333 );
if( delta == 0 ) arrow.rotation = b;
else arrow.rotation += delta;
debugDraw();
};
///-----------------------
/// DISPLAY |
///-----------------------
private var w:int;
private var h:int;
private var tx:TextField;
private var arrow:Sprite;
private var canvas:Sprite;
private var run:Boolean;
public function MXMLC ()
{
// init stage
stage.align = 'tl';
stage.scaleMode = 'noScale';
stage.frameRate = 40;
w = stage.stageWidth;
h = stage.stageHeight;
graphics.beginFill(0x26274A);
graphics.drawRect(0,0,w,h*0.4);
graphics.endFill();
graphics.beginFill(0xFEE285);
graphics.drawRect(0,h*0.4,w,h);
graphics.endFill();
// text
var ft:TextFormat = new TextFormat();
ft.size = 22;
ft.color = 0xD6E2D6;
ft.leftMargin = 30;
ft.letterSpacing = 4;
ft.tabStops = [232];
tx = new TextField();
tx.textColor = 0xFFFFFF;
tx.mouseEnabled = false;
tx.defaultTextFormat = ft;
tx.setTextFormat( ft );
tx.y = 20;
tx.width = ( w );
tx.height = ( h * 0.4 );
stage.addChild( tx );
///---------------
/// ARROW |
///---------------
arrow = new Sprite();
stage.addChild( arrow );
arrow.scaleX = arrow.scaleY = 4;
arrow.x = w >> 1;
arrow.y = h * 0.7;
arrow.graphics.lineStyle(2,0x0);
arrow.graphics.beginFill( 0xC6F327 );
// (3).
// (1)...(2) ..
// . ..
// . (4)
// . ..
// (7)...(6) ..
// (5).
arrow.graphics.moveTo(-15,-7); // (1)
arrow.graphics.lineTo(2,-7); // (2)
arrow.graphics.lineTo(2,-15); // (3)
arrow.graphics.lineTo(15,0); // (4)
arrow.graphics.lineTo(2,15); // (5)
arrow.graphics.lineTo(2,7); // (6)
arrow.graphics.lineTo(-15,7); //(7)
arrow.graphics.lineTo(-15,-7); // (1)
arrow.graphics.endFill();
arrow.graphics.lineStyle(1,0x0);
arrow.graphics.drawCircle( 0, 0, 2 ); // pivot
// canvas
canvas = new Sprite();
canvas.x = arrow.x;
canvas.y = arrow.y;
addChild( canvas );
// stage events
run = true;
stage.addEventListener('rightMouseDown',update);
stage.addEventListener('click', function(e:*):void {run = !run;});
stage.addEventListener('enterFrame', function(e:*):void {if (!run) return; update(); });
} // constractor
private function debugDraw():void
{
// Trace data
tx.text = "angleMin\t" + angleMin.toFixed(2) +
"\n" + "angleMax\t" + angleMax.toFixed(2) +
"\n" + "distance\t" + distance.toFixed(2) +
"\n" + "inverse\t" + inverse.toFixed(2) +
"\n" + "direction\t" + direction.toFixed(2);
// Draw data
canvas.graphics.clear();
canvas.graphics.lineStyle( 2, 0xFFFFFF );
canvas.graphics.drawCircle( 0,0,120 );
// Draw data - mouse angle
var p:Point = Point.polar( 10, Math.atan2( stage.mouseY - arrow.y, stage.mouseX - arrow.x ));
canvas.graphics.lineStyle( 4, 0xFF0000 );
p.normalize( 100 );
canvas.graphics.moveTo(p.x, p.y);
p.normalize( 150 );
canvas.graphics.lineTo(p.x, p.y);
} // debugDraw
} // class
} // package