flash on 2016-7-18
Trammel of Archimedes
アルキメデスの楕円コンパスです。
/**
* Copyright H.S ( http://wonderfl.net/user/H.S )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/gX6K
*/
package {
import com.bit101.components.CheckBox;
import com.bit101.components.HUISlider;
import com.bit101.components.RadioButton;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
public class Main extends Sprite {
private var longSide:Number = 180;
private var shortSide:Number = longSide * 0.4;
private var angleOfTrammel:Number = 0;
private var angleOfTrammelPrev:Number = 0;
private var rotationAngleOfBall:Number = 0;
private var radiusOfBall:Number = 22;
private var point1:Point = new Point();
private var point2:Point = new Point();
private var point3:Point = new Point();
private var point3Prev:Point = new Point();
private var centerOfBall:Point = new Point();
private var autoMoveFlag:Boolean = true;
private var drawTrammelFlag:Boolean = true;
public function Main():void {
x = y = 465 / 2;
var checkBox:CheckBox = new CheckBox(stage, 13, 13, "AUTO", function(event:Event):void {
autoMoveFlag = checkBox.selected;
});
checkBox.selected = true;
var radioButton1:RadioButton = new RadioButton(stage, 79, 13, "TRAMMEL", true, function(event:Event):void {
drawTrammelFlag = true;
});
var radioButton2:RadioButton = new RadioButton(stage, 149, 13, "BALL", false, function(event:Event):void {
drawTrammelFlag = false;
});
var slider:HUISlider = new HUISlider(stage, 12, 31, "ELLIPTICITY", function(event:Event):void {
shortSide = longSide * slider.value / 100;
});
slider.maximum = 100;
slider.value = 40;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.setChildIndex(this, stage.numChildren - 1);
}
private function onEnterFrame(event:Event):void {
point1.setTo(0, -(longSide - shortSide) * Math.sin(angleOfTrammel));
point2.setTo((longSide - shortSide) * Math.cos(angleOfTrammel), 0);
point3Prev.setTo(point3.x, point3.y);
point3.setTo(point2.x + shortSide * Math.cos(angleOfTrammel),
point2.y + shortSide * Math.sin(angleOfTrammel));
var focus:Number = Math.sqrt(longSide * longSide - shortSide * shortSide);
var rad_f1:Number = Math.atan2(point3.y, (point3.x - focus));
var rad_f2:Number = Math.atan2(point3.y, (point3.x + focus));
var angleOfNormal:Number = (rad_f1 + rad_f2) / 2;
if (point3.y == 0 && angleOfTrammel != 0 ) angleOfNormal = Math.PI / 2 * -point1.y / Math.abs(point1.y);
centerOfBall.setTo(point3.x + radiusOfBall * Math.cos(angleOfNormal),
point3.y + radiusOfBall * Math.sin(angleOfNormal));
var turn:Number = (angleOfTrammel > angleOfTrammelPrev)? 1 : -1;
if (Math.abs(angleOfTrammel - angleOfTrammelPrev) > Math.PI) turn *= -1;
rotationAngleOfBall += Point.distance(point3Prev, point3) / radiusOfBall * turn;
angleOfTrammelPrev = angleOfTrammel;
if(autoMoveFlag) angleOfTrammel += 3 * Math.PI / 180;
else angleOfTrammel = Math.atan2(mouseY - point1.x, mouseX);
if (angleOfTrammel < 0) angleOfTrammel += Math.PI * 2;
graphics.clear();
//レール
graphics.lineStyle(2, 0xDCDCDC);
graphics.moveTo(-465 / 2, -10);
graphics.lineTo(-10, -10);
graphics.lineTo(-10, -465 / 2);
graphics.moveTo(465 / 2, -10);
graphics.lineTo(10, -10);
graphics.lineTo(10, -465 / 2);
graphics.moveTo(-465 / 2, 10);
graphics.lineTo(-10, 10);
graphics.lineTo(-10, 465 / 2);
graphics.moveTo(465 / 2, 10);
graphics.lineTo(10, 10);
graphics.lineTo(10, 465 / 2);
if(drawTrammelFlag){
//楕円コンパス
graphics.lineStyle(2, 0x000000);
graphics.drawRect(point1.x - 10, point1.y - 20, 20, 40);
graphics.drawRect(point2.x - 20, point2.y - 10, 40, 20);
graphics.moveTo(point1.x, point1.y);
graphics.lineTo(point2.x, point2.y);
graphics.lineTo(point3.x, point3.y);
graphics.beginFill(0x000000);
graphics.drawCircle(point1.x, point1.y, 3);
graphics.drawCircle(point2.x, point2.y, 3);
graphics.drawCircle(point3.x, point3.y, 3);
graphics.endFill();
}
else {
//ボール
graphics.lineStyle(2, 0x000000);
graphics.drawCircle(centerOfBall.x, centerOfBall.y, radiusOfBall);
for (var i:int = 0; i < 4; i++) {
var X:Number = centerOfBall.x + radiusOfBall * Math.cos(angleOfNormal + Math.PI * i / 2 + rotationAngleOfBall);
var Y:Number = centerOfBall.y + radiusOfBall * Math.sin(angleOfNormal + Math.PI * i / 2 + rotationAngleOfBall);
graphics.moveTo(centerOfBall.x, centerOfBall.y);
graphics.lineTo(X, Y);
}
}
//楕円
if (Point.distance(point3Prev, point3) < 80) {
addChild(new line(point3Prev, point3));
}
}
}
}
import flash.display.Shape;
import flash.events.Event;
import flash.geom.Point;
class line extends Shape {
public function line(pointStart:Point, pointEnd:Point):void {
graphics.lineStyle(2, 0x000000, 1, false, "normal", "none");
graphics.moveTo(pointStart.x, pointStart.y);
graphics.lineTo(pointEnd.x, pointEnd.y);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void {
alpha -= 0.004;
if (alpha <= 0) {
graphics.clear();
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
}