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