Home > flash > バネ運動するネットみたいなのを作る

バネ運動するネットみたいなのを作る

/*
<修正>2008/08/08
一部コードを修正しました。
また、負荷が高い処理なので、swfがアクティブな際のみ処理を行うよう変更しました。
でもMacのSafariだとEvent.DEACTIVATEが起こらないんですね…。どうしよう。
*/

52sec.orgさんのデモを見て、僕も同じようなのを作りたくなった。
ActionScript3.0アニメーションも読んだし、勉強の為に。
でも52sec.orgさんのデモは多分、3次元の座標変換をしているので、僕はもうちょっと簡単な物から作ろうと思う。ブラーも無しで。
で、マウスドラッグできるネットを作ります。

試しに一個のボールを引っ張るデモを作った。

ボールそのものをドラッグするんじゃなくて、ドラッグした距離とか方向に応じてボールが反応する。
それで、ボールの数を増やして線で繋ぐと、ネットみたいになる。

別windowでサンプルを開きます
ピクチャ 1.png ピクチャ 3.png

でもこれ、ちゃんとしたネットのシミュレーションしてないんだよな。きっと。
本当は、ボールの一つが引っ張られると、連結されたボールが引っ張られて、その引っ張られたボールに連結されてるボールが…
の繰り返しでなくちゃいけないんじゃなかろうか。
最初はその方向で作ってたんだけど、うまくいかなくて挫折したのでした。
今回はFlashDevelop使って書いた。慣れてるからなのかもしれないけど快適だな〜。

今回のソース一式 NetSample.zip

一応メインとなるソースだけ載せてみます。
Ballクラスってのを使ってるけど、円を描いて、速度のプロパティvx, vyと、デフォルト位置を記憶させるプロパティを持ってます。

package
{
	import flash.display.Sprite;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import org.miniapp.customFigure.Ball;

	[SWF(backgroundColor="0x000000", width="800", height="800", frameRate="60")]
	public class Net extends Sprite
	{
		private static const _SPRING:Number = 0.3;
		private static const _FRICTION:Number = 0.9;
		private static const _COLUM:uint = 20
		private static const _ROW:uint = 20;
		private static const _NUM_BALLS:uint = _COLUM * _ROW;
		private static const _DIFF_X:uint = 30;
		private static const _DIFF_Y:uint = 30;
		private static const _START_X:uint = 100;
		private static const _START_Y:uint = 100;
		private static const _BALL_RADIUS:uint = 4;

		//TODO 名前も数値も適当。ちゃんとしたい。
		private static const _POWER_COEFFICIENT:uint = 100;

		/**
		 * コンストラクタ
		 */
		public function Net()
		{
			init();
		}

		private var _isDragging:Boolean = false;
		private var _mousePressPointX:Number;
		private var _mousePressPointY:Number;
		private var _balls:Array/* of Ball */
		private var _horizontalBallArray:Array/* of Array */
		private var _verticalBallsArray:Array/* of Array */
		private var _canvas:Sprite;

		private function init():void
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;

			_balls = [];

			//マウスドラッグ用の線を描画するためのキャンバス
			_canvas = new Sprite();
			addChild(_canvas);

			//ボールを繋ぐ線を描くため、縦、横に分けて配列に入れて纏める。
			//縦に並ぶボールを入れた配列をまとめる配列
			_horizontalBallArray = [];
			//横に並ぶボールを入れた配列をまとめる配列
			_verticalBallsArray = [];

			for (var i:uint = 0; i < _COLUM; i++)
			{
				//縦に並ぶボールを管理する配列を作る
				var horizontalBalls:Array/* of Ball */ = [];
				_horizontalBallArray.push(horizontalBalls);
			}

			//ボール生成、配置
			for (i = 0; i < _ROW; i++)
			{
				//横に並ぶボールを管理する配列を作る
				var verticalBalls:Array/* of Ball */ = [];
				for (var j:uint = 0; j < _COLUM; j++)
				{
					var ball:Ball = new Ball(_BALL_RADIUS, 0xFFFFFF);
					ball.x = ball.defaultX = _START_X + _DIFF_X * j;
					ball.y = ball.defaultY = _START_Y + _DIFF_Y * i;
					_balls.push(ball);

					//縦に並ぶボールを入れる
					(_horizontalBallArray[j] as Array).push(ball);
					//横に並ぶボールを入れる
					verticalBalls.push(ball);
					ball.cacheAsBitmap = true;
					addChild(ball);
				}
				_verticalBallsArray.push(verticalBalls);
			}

			drawLine();
			addEventListener(Event.DEACTIVATE, deadActiveHandler);
			addEventListener(Event.ACTIVATE, activateHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}

		/**
		 * バネ運動させる
		 * @param	ball バネ運動させるボール
		 * @param	targetPoint 目標位置
		 */
		private function springTo(ball:Ball, targetX:Number, targetY:Number):void
		{
			ball.vx += (targetX - ball.x) * _SPRING;
			ball.vy += (targetY - ball.y) * _SPRING;

			ball.vx *= _FRICTION;
			ball.vy *= _FRICTION;

			ball.x  += ball.vx;
			ball.y  += ball.vy;
		}

		/**
		 * ボール同士を線で繋ぐ
		 */
		private function drawLine():void
		{
			graphics.clear();
			graphics.lineStyle(1, 0xFFFFFF);

			//縦のラインを引く
			for (var i:uint = 0; i < _COLUM; i++)
			{
				var horizontalBalls:Array = _horizontalBallArray[i] as Array;
				var firstBall:Ball = Ball(horizontalBalls[0]);
				graphics.moveTo(firstBall.x, firstBall.y);
				for (var j:uint = 1; j < _COLUM; j++)
				{
					var ball:Ball = Ball(horizontalBalls[j]);
					graphics.lineTo(ball.x, ball.y);
				}
			}

			//横のラインを引く
			for (i = 0; i < _ROW; i++)
			{
				var verticalBalls:Array = _verticalBallsArray[i] as Array;
				firstBall = Ball(verticalBalls[0]);
				graphics.moveTo(firstBall.x, firstBall.y);
				for (j = 1; j < _ROW; j++)
				{
					ball = Ball(verticalBalls[j]);
					graphics.lineTo(ball.x, ball.y);
				}
			}
		}

		private function enterFrameHandler(e:Event):void
		{
			if (_isDragging)
			{
				//マウスがドラッグされた距離を調べる
				var dxMouse:Number = mouseX - _mousePressPointX;
				var dyMouse:Number = mouseY - _mousePressPointY;
				var lengthMouthDrag:Number = Math.sqrt(dxMouse * dxMouse + dyMouse * dyMouse);
				//マウスがドラッグされた角度を求める
				var angleMouseDrag:Number = Math.atan2(dyMouse, dxMouse);

				drawMouseDragLine();
			}

			for (var i:uint = 0; i < _NUM_BALLS; i++)
			{
				var ball:Ball = Ball(_balls[i]);
				if (_isDragging)
				{

					//マウスが押された地点とボールのデフォルト地点の距離を調べる
					var dx:Number = _mousePressPointX - ball.defaultX;
					var dy:Number = _mousePressPointY - ball.defaultY;
					var lengthBetweenMousePressPostionAndBallPosition:Number = Math.sqrt(dx * dx + dy * dy);

					//マウスとボールの位置からボールにかかる力を算出
					//マウスから近いボールほど引っ張られる力が大きくなる
					var powerRate:Number =
					_POWER_COEFFICIENT / ( _POWER_COEFFICIENT + lengthBetweenMousePressPostionAndBallPosition);

					var power:Number = lengthMouthDrag * powerRate;

					//位置関係から移動する目的地を算出
					var toX:Number = ball.defaultX + power * Math.cos(angleMouseDrag);
					var toY:Number = ball.defaultY + power * Math.sin(angleMouseDrag);

					springTo(ball, toX, toY);
				}
				else
					springTo(ball, ball.defaultX, ball.defaultY);
			}
			drawLine();
		}

		/**
		 * マウスドラッグ時の線を引く
		 * @param	e
		 */
		private function drawMouseDragLine():void
		{
			_canvas.graphics.clear();
			_canvas.graphics.lineStyle(1, 0xFFFFFF);
			_canvas.graphics.moveTo(_mousePressPointX, _mousePressPointY);
			_canvas.graphics.lineTo(mouseX, mouseY);
		}

		/**
		 * swfがactiveになったら処理開始
		 * @param	e
		 */
		private function activateHandler(e:Event):void
		{
			//レンダリング開始
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}

		/**
		 * swfがアクティブでなくなったら処理中断
		 * @param	e
		 */
		private function deadActiveHandler(e:Event):void
		{
			removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}

		private function mouseDownHandler(e:MouseEvent):void
		{
			_isDragging = true;
			_mousePressPointX = mouseX;
			_mousePressPointY = mouseY;
		}

		private function mouseUpHandler(e:MouseEvent):void
		{
			_isDragging = false;

			//マウスドラッグの線の描画をやめる
			_canvas.graphics.clear();
		}
	}
}

Comments:0

Comment Form
Remember personal info

Home > flash > バネ運動するネットみたいなのを作る

Return to page top