ドラッグで投げてみる

by tenasaku forked from ドラッグで投げるには (diff: 141)
--------
2010年4月2日
マウスで物をドラッグして速度を与える(つまり投げる)ためには
投げる動きをどのように捕捉するべきか...
ドラッグ中のマウスの動きを記録してみる
--------
翌 4月3日
自分 fork
MouseUpイベントから後ろ向きに
MouseMoveイベントを最大10回ぶんさかのぼって、
二点間の移動距離のいちばん大きかったところを
初速度ベクトルとして採用してみよう
... これでインベーダーゲームとか作ったら
すごく難しくなりそう
手裏剣で宇宙人の侵略を止められるか...
--------
♥0 | Line 168 | Modified 2010-04-03 15:59:40 | MIT License
play

ActionScript3 source code

/**
 * Copyright tenasaku ( http://wonderfl.net/user/tenasaku )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/i7zG
 */

// forked from tenasaku's ドラッグで投げるには
// --------
// 2010年4月2日
// マウスで物をドラッグして速度を与える(つまり投げる)ためには
// 投げる動きをどのように捕捉するべきか...
// ドラッグ中のマウスの動きを記録してみる
// --------
// 翌 4月3日
// 自分 fork
// MouseUpイベントから後ろ向きに
// MouseMoveイベントを最大10回ぶんさかのぼって、
// 二点間の移動距離のいちばん大きかったところを
// 初速度ベクトルとして採用してみよう
// ... これでインベーダーゲームとか作ったら
// すごく難しくなりそう
// 手裏剣で宇宙人の侵略を止められるか...
// --------
package {

	import flash.display.*;
	import flash.events.*;
	import flash.text.*;

	public class Main extends Sprite {

		private const INITIAL_MESSAGE:String = "ドラッグで投げる動作をしてみてください";
		private const MOUSETRACK_LIMIT:int = 20;

		private var mouseTrack:Array;
		private var screen:Shape;
		private var ball:MyBall;
		private var monitor:TextField;

		private function onMouseDown(e:MouseEvent):void {
			stage.removeEventListener(Event.ENTER_FRAME, ballMoves);
			mouseTrack = [e.stageX,e.stageY];
			ball.visible = false;
			monitor.text = "...";
			screen.graphics.clear();
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave);
		}

		private function onMouseMove(e:MouseEvent):void {
			if ( mouseTrack.unshift(e.stageX,e.stageY) > MOUSETRACK_LIMIT ) {
				mouseTrack.pop();
				mouseTrack.pop();
			}
		}

		private function onMouseLeave(e:Event):void {
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeave);
			screen.graphics.clear();
			monitor.text = "ファウルです";
		}

		private function onMouseUp(e:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeave);
			var Vx:Number,Vy:Number;
			var X1:Number = e.stageX;
			var Y1:Number = e.stageY;
			var i:int;
			var best_i:int = 0;
			var best_ell:Number = 0;
			ball.Vx = 0;
			ball.Vy = 0;
			for ( i = 0 ; i < mouseTrack.length/2 ; ++i ) {
				var X0:Number = mouseTrack[i*2];
				var Y0:Number = mouseTrack[i*2+1];
				var ell:Number = Math.sqrt((X1-X0)*(X1-X0)+(Y1-Y0)*(Y1-Y0));
				if (ell > best_ell) {
					best_ell = ell;
					best_i = i;
				}
				X1 = X0;
				Y1 = Y0;
			}
			if ( best_i*2+1 < mouseTrack.length ) {
				screen.graphics.beginFill(0xff0000);
				screen.graphics.drawCircle(mouseTrack[best_i*2],mouseTrack[best_i*2+1],3);
				screen.graphics.endFill();
				if ( best_i>0 ) {
					screen.graphics.beginFill(0x0000ff);
					screen.graphics.drawCircle(mouseTrack[best_i*2-2],mouseTrack[best_i*2-1],3);
					screen.graphics.endFill();
					ball.Vx = mouseTrack[best_i*2-2]-mouseTrack[best_i*2];
					ball.Vy = mouseTrack[best_i*2-1]-mouseTrack[best_i*2+1];
				}
			} else {
				screen.graphics.beginFill(0xff0000);
				screen.graphics.drawCircle(e.stageX,e.stageY,3);
			}
			ball.x = e.stageX;
			ball.y = e.stageY;
			ball.visible = true;
			stage.addEventListener(Event.ENTER_FRAME, ballMoves);
		}

		private function ballMoves(e:Event):void {
			if ( (ball.x >= 0)&&(ball.x < stage.stageWidth)&&(ball.y >= 0)&&(ball.y < stage.stageHeight) ) {
				monitor.text = "velocity: "
					+ Math.sqrt(ball.Vx*ball.Vx+ball.Vy*ball.Vy).toFixed(2)
					+ "\nx = " + ball.x.toFixed(2)
					+ "\ny = " + ball.y.toFixed(2);
				ball.x += ball.Vx/stage.frameRate*2;
				ball.y += ball.Vy/stage.frameRate*2;
			} else {
				ball.visible = false;
				ball.x = 0;
				ball.y = 0;
				ball.Vx = 0;
				ball.Vy = 0;
				stage.removeEventListener(Event.ENTER_FRAME, ballMoves);
				monitor.text = INITIAL_MESSAGE;
				screen.graphics.clear();
			}
		}

		private function drawHorizon():void {
			this.graphics.clear();
			this.graphics.beginFill(0x006600);
			this.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
			this.graphics.endFill();
		}

		private function initMonitor():void {
			var tfmt:TextFormat = new TextFormat();
			tfmt.font = null;
			tfmt.size = 14;
			tfmt.leading = 2;
			tfmt.leftMargin = 2;
			tfmt.rightMargin = 2;
			tfmt.color = 0xffffff;
			monitor.defaultTextFormat = tfmt;
			monitor.autoSize = TextFieldAutoSize.LEFT;
			monitor.x = 0;
			monitor.y = 2;
		}

		private function initScreen():void {
			screen.graphics.clear();
		}

		private function onResize(e:Event):void {
			drawHorizon();
			initMonitor();
			initScreen();
		}

		private function initialize(e:Event):void {
			this.removeEventListener(Event.ADDED_TO_STAGE, initialize);
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			monitor = new TextField();
			screen = new Shape();
			ball = new MyBall();
			ball.visible = false;
			drawHorizon();
			initMonitor();
			initScreen();
			monitor.text = INITIAL_MESSAGE;
			this.addChild(screen);
			this.addChild(monitor);
			this.addChild(ball);
			mouseTrack = [];
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.addEventListener(Event.RESIZE, onResize);
		}
		// The Main constructor simply calles initialize() function.

		public function Main():void {
			if ( stage != null ) {
				initialize(null);
			} else {
				this.addEventListener(Event.ADDED_TO_STAGE, initialize);
			}
		}

	} // end of class Main
} // end of package

import flash.display.*;

class MyBall extends Shape {
	public var Vx:Number;
	public var Vy:Number;
	public function MyBall() {
		Vx = 0;
		Vy = 0;
		this.graphics.clear();
		this.graphics.lineStyle(1,0x000000);
		this.graphics.beginFill(0xcccccc);
		this.graphics.drawCircle(1,0,20);
		this.graphics.endFill();
		this.graphics.beginFill(0x999999);
		this.graphics.drawCircle(1,0,12);
		this.graphics.endFill();
	}
}