回転砲台のアルゴリズム
回転砲台のアルゴリズム
* どっちに回したほうが近いか、やり方をよく忘れるのでメモ
/**
* Copyright alumican_net ( http://wonderfl.net/user/alumican_net )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/t6u8
*/
/**
* 回転砲台のアルゴリズム
* どっちに回したほうが近いか、やり方をよく忘れるのでメモ
*/
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import com.bit101.components.*;
public class RotationPath extends Sprite
{
/**
* 右回りと左回りでどっちが近いか計算する
*
* @param startAngle 開始角度(rad)
* @param targetAngle 終了角度(rad)
* return 差分の角度
*/
public function calc(startAngle:Number, targetAngle:Number):Number
{
var angle0:Number = startAngle % PI2;
var angle1:Number = targetAngle % PI2;
if (angle0 < 0) angle0 += PI2;
if (angle1 < 0) angle1 += PI2;
var d:Number = angle1 - angle0;
if (d < 0 ) d += PI2;
if (d > PI) d -= PI2;
return d;
}
private const PI:Number = Math.PI;
private const PI2:Number = PI * 2;
private const TO_DEGREE:Number = 180 / PI;
private const TO_RADIAN:Number = PI / 180;
private var _canvas:Sprite;
private var _center:Sprite;
private var _handle_0:Handle;
private var _handle_1:Handle;
private var _label:Label;
private var _title:String;
public function RotationPath():void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
_canvas = addChild( new Sprite() ) as Sprite;
//中心点
_center = addChild( new Sprite() ) as Sprite;
_center.x = stage.stageWidth * 0.5;
_center.y = stage.stageHeight * 0.5;
_center.graphics.beginFill(0x0);
_center.graphics.drawCircle(0, 0, 5);
_center.graphics.endFill();
//ハンドル
_handle_0 = addChild( new Handle(stage, update, 0xff0000) ) as Handle;
_handle_1 = addChild( new Handle(stage, update, 0x0000ff) ) as Handle;
_title = "SHORTEST ANGULAR PATH FROM RED POINT TO BLUE POINT";
_label = new Label(this, 10, 10, "");
update();
}
public function update():void
{
var g:Graphics = _canvas.graphics;
var cx:Number = _center.x;
var cy:Number = _center.y;
var x0:Number = _handle_0.x;
var y0:Number = _handle_0.y;
var x1:Number = _handle_1.x;
var y1:Number = _handle_1.y;
var angle0:Number = Math.atan2(y0 - cy, x0 - cx);
var angle1:Number = Math.atan2(y1 - cy, x1 - cx);
var angle:Number = calc(angle0, angle1);
_label.text = _title + "\n\n"
+ "START ANGLE : " + (angle0 * TO_DEGREE) + "\n"
+ "TARGET ANGLE : " + (angle1 * TO_DEGREE) + "\n\n"
+ "SHORTEST ANGULAR PATH : " + (angle * TO_DEGREE);
g.clear();
g.lineStyle(0, 0xcccccc);
g.moveTo(cx, cy);
g.lineTo(x0, y0);
g.moveTo(cx, cy);
g.lineTo(x1, y1);
}
}
}
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
internal class Handle extends Sprite
{
private var _stage:Stage;
private var _update:Function;
public function Handle(stage:Stage, update:Function, color:uint):void
{
_stage = stage;
_update = update;
graphics.beginFill(0x0, 0);
graphics.drawCircle(0, 0, 10);
graphics.endFill();
graphics.beginFill(color);
graphics.drawCircle(0, 0, 5);
graphics.endFill();
var margin:Number = 30;
x = margin + Math.random() * (stage.stageWidth - margin * 2);
y = margin + Math.random() * (stage.stageHeight - margin * 2);
addEventListener(MouseEvent.MOUSE_DOWN, _mouseDownHandler);
buttonMode = true;
}
private function _mouseDownHandler(e:MouseEvent):void
{
startDrag(false, new Rectangle(0, 0, _stage.stageWidth, _stage.stageHeight));
stage.addEventListener(MouseEvent.MOUSE_UP, _mouseUpHandler);
stage.addEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);
}
private function _mouseUpHandler(e:MouseEvent):void
{
stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_UP, _mouseUpHandler);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);
}
private function _mouseMoveHandler(e:MouseEvent):void
{
_update();
}
}