flash on 2011-6-7
/**
* Copyright bashi ( http://wonderfl.net/user/bashi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/v4js
*/
package {
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
public class FlashTest extends Sprite {
/** 固定するx座標。 */
private var _fixedX:Number;
/** 節間の距離。 */
private var _dist:Number = 20;
/** 節の数。 */
private var _pointCnt:int = 10;
/** 重力加速度。 */
private var _gravity:Number = .8;
/** 硬さ。 */
private var _hardness:int = 3;
/** 重り。 */
private var _sinker:Object;
/** 節の配列。 */
private var _pointArray:Array;
/** 掴んでいる節。 */
private var _graspTarget:Object = null;
/**
* コンストラクタ。
*/
public function FlashTest() {
// ステージの設定をする
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT
// パラメータの初期化をする
_fixedX = stage.stageWidth / 2;
// 節を準備する
_pointArray = [];
for (var i:int = 0; i < _pointCnt; i++) {
var point:Object = createPoint(i);
_pointArray.push(point);
}
// 重りを生成する
_sinker = createSinker();
_pointArray.push(_sinker);
// フレームイベントリスナを登録する
addEventListener(Event.ENTER_FRAME, doEnterFrame);
// マウスアップでつかんでいるものを離す
stage.addEventListener(MouseEvent.MOUSE_UP,
function (e:MouseEvent):void {
_graspTarget = null;
});
}
/**
* フレームイベントハンドラです。
* @param e イベントオブジェクト
*/
protected function doEnterFrame(e:Event):void {
// 節の位置を更新する
for each (var point:Object in _pointArray) {
// 重力加速度により位置を移動する
point.y += _gravity;
// 位置を一旦保存する
var orgX:Number = point.x;
var orgY:Number = point.y;
// 前回位置からの移動量により位置を更新する
point.x += point.x - point.prevX;
point.y += point.y - point.prevY;
// 前回位置を更新する
point.prevX = orgX;
point.prevY = orgY;
}
// 節間の距離を調整する
for (var j:int = 0; j < _hardness; j++) {
for (var i:int = 0, iEnd:int = _pointArray.length - 1; i < iEnd; i++) {
var point1:Object = _pointArray[i];
var point2:Object = _pointArray[i + 1];
// 節間の距離を算出する
var dx:Number = point2.x - point1.x;
var dy:Number = point2.y - point1.y;
var d:Number = Math.sqrt(dx * dx + dy * dy);
// 指定された間隔と現在の距離との差 / 2を各点の移動量とする
dx = (_dist - d) / 2 * dx / d;
dy = (_dist - d) / 2 * dy / d;
// 節を移動する
point1.x -= dx;
point1.y -= dy;
point2.x += dx;
point2.y += dy;
}
// 最初の節は天井に固定する
_pointArray[0].x = _pointArray[0].prevX = _fixedX;
_pointArray[0].y = _pointArray[0].prevY = 0;
// つかんでいる節はマウスカーソルの位置にする
if (_graspTarget) {
_graspTarget.x = _graspTarget.prevX = mouseX;
_graspTarget.y = _graspTarget.prevY = mouseY;
}
}
// 表示オブジェクトの位置を更新する
for (i = 0, iEnd = _pointArray.length; i < iEnd; i++) {
point = _pointArray[i];
point.sprite.x = point.x;
point.sprite.y = point.y;
}
// 重りの向きを調整する
var lastPointSprite:Sprite = _pointArray[_pointArray.length - 2].sprite;
var angle:Number = Math.atan2(
lastPointSprite.y - _sinker.sprite.y,
lastPointSprite.x - _sinker.sprite.x);
_sinker.sprite.rotation = angle * 180 / Math.PI;
}
/**
* 節を生成し、戻します。
* @param idx インデックス
* @return 節をあらわすオブジェクト
*/
protected function createPoint(idx:int):Object {
// 表示オブジェクトを生成する
var sprite:Sprite = new Sprite();
sprite.graphics.lineStyle(1, 0x0000FF);
sprite.graphics.beginFill(0xFFFFFF);
sprite.graphics.drawCircle(0, 0, 10);
sprite.graphics.endFill();
sprite.x = _fixedX + _dist * idx;
sprite.y = 0;
addChild(sprite);
// オブジェクトを生成する
var obj:Object = {sprite:sprite, x:sprite.x, y:sprite.y, prevX:sprite.x, prevY:sprite.y};
// マウスダウンで掴む
sprite.addEventListener(MouseEvent.MOUSE_DOWN, createMouseDownHandler(obj));
return obj;
}
/**
* 重りを生成し、戻します。
* @return 重りをあらわすオブジェクト
*/
protected function createSinker():Object {
// 表示オブジェクトを生成する
var sprite:Sprite = new Sprite();
sprite.graphics.beginFill(0x9999FF);
sprite.graphics.drawCircle(0, 0, 20);
sprite.graphics.endFill();
sprite.graphics.beginFill(0x0000FF);
sprite.graphics.drawCircle(10, 0, 10);
sprite.graphics.endFill();
sprite.x = _fixedX + _dist * _pointCnt;
sprite.y = 0;
addChild(sprite);
// オブジェクトを生成する
var obj:Object = {sprite:sprite, x:sprite.x, y:sprite.y, prevX:sprite.x, prevY:sprite.y};
// マウスダウンで掴む
sprite.addEventListener(MouseEvent.MOUSE_DOWN, createMouseDownHandler(obj));
return obj;
}
/**
* マウスダウンイベントハンドラを生成し、戻します。
* @param point 対象となる節
* @return ハンドラ
*/
private function createMouseDownHandler(point:Object):Function {
return function (e:MouseEvent):void {
// 対象を保持する
_graspTarget = point;
};
}
}
}