ホーム > タグ > flash

flash

グニャグニャするネットを作る

以前作ったのの続き。
前回のは位置が固定されていて動かせなかったけど、どうにかして動かせるようにしました。
まだ未完ですが、勢いでUPします。


別windowでサンプルを開きます
1.png 2.png

今回はパラメーターを弄れるようにスライダーを付けていて、左からfriction(摩擦 : 0.1~0.98)、spring(バネの係数 : 0.1~1)、_POWER_COEFFICIENT(各点にかかる力を求めるための定数。自分でやっといて良く理解していない : 5~300)です。
スライダーのソース、使い方は書籍『ActionScriptアニメーション』のものを使わせて貰いました。色だけ変えてあります。

Ballクラスにtensionってパラメーターを追加し、マウスとの距離によって変え、バネ運動の際にその値を反映させています。

以下は問題点。

  • 未だにネット部分だけにあたり判定を付けるのが出来てない。
  • なのでスライダーを弄ってもネットが動く。
  • 前回も書いたけど、多分この方法は間違ってる気がする。ちゃんと点どうしが連結されていない。
  • 各値をかなり低くすると、動作がおかしい点がある。

要改善。次は回転させようと思います。

んで、僕は何がやりたいのかと言うと、
The Magic Carpet  —  Manuel’s Coding Blogとか、THE ECO ZOO | ECODA!DOBUTSUENの引っ張れる旗みたいなのを作りたいのです。
といっても3Dにしたい訳ではなく、どういう風に座標を管理しているのか、等の仕組みが知りたい。
同じように、確かFlash8が出たあたり、fladdictさんがグネグネするコーラの缶のデモを作られていた。そこのURLはもう無い(ドメインが違う)し、はっきりとは覚えていないんだけど、テクスチャも貼られていた。そういったのを作りたいのです。

今回のソース一式 net2.zip

メインとなるソースだけ載せてみます。

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.5;
		private static const _FRICTION:Number = 0.5;
		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 = 20;
		private static const _DIFF_Y:uint = 20;
		private static const _START_X:uint = 200;
		private static const _START_Y:uint = 200;
		private static const _BALL_RADIUS:uint = 4;

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

		/**
		 * コンストラクタ
		 */
		public function Net()
		{
			if (stage)
				init();
			else
				addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private var _mousePressX:Number;
		private var _mousePressY:Number;
		private var _isDragging:Boolean = false;
		private var _lastMouseX:Number;
		private var _lastMouseY:Number;
		private var _balls:Array/* of Ball */
		private var _horizontalBallArray:Array/* of Array */
		private var _verticalBallsArray:Array/* of Array */
		private var _frictionSlider:SimpleSlider;
		private var _springSlider:SimpleSlider;
		private var _powerCoefficientSlider:SimpleSlider;

		private function init():void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			stage.scaleMode = StageScaleMode.NO_SCALE;

			_frictionSlider = new SimpleSlider(0.1, 0.98, _FRICTION);
			_frictionSlider.x = 10;
			_frictionSlider.y = 10;
			addChild(_frictionSlider);

			_springSlider = new SimpleSlider(0.1, 1, _SPRING);
			_springSlider.x = 30;
			_springSlider.y = 10;
			addChild(_springSlider);

			_powerCoefficientSlider = new SimpleSlider(5, 300, _POWER_COEFFICIENT);
			_powerCoefficientSlider.x = 50;
			_powerCoefficientSlider.y = 10;
			addChild(_powerCoefficientSlider);

			_balls = [];

			//ボールを繋ぐ線を描くため、縦、横に分けて配列に入れて纏める。
			//縦に並ぶボールを入れた配列をまとめる配列
			_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();
			stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}

		/**
		 * ボール同士を線で繋ぐ
		 */
		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);
				}
			}
		}

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

			ball.vx *= _frictionSlider.value;
			ball.vy *= _frictionSlider.value;

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

		private function enterFrameHandler(e:Event):void
		{
			if (_isDragging)
			{
				//マウスが移動した距離を調べる
				var dxMouse:Number = mouseX - _lastMouseX;
				var dyMouse:Number = mouseY - _lastMouseY;
			}

			for (var i:uint = 0; i < _NUM_BALLS; i++)
			{
				var ball:Ball = Ball(_balls[i]);
				if (_isDragging)
				{
					//マウスが押された地点とボールの距離を調べる
					var dx:Number = mouseX - ball.x;
					var dy:Number = mouseY - ball.y;
					var distance:Number = Math.sqrt(dx * dx + dy * dy);

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

					//目的地を算出
					var toX:Number = ball.defaultX + dxMouse;
					var toY:Number = ball.defaultY + dyMouse;
				}
				else
				{
					toX = ball.defaultX;
					toY = ball.defaultY;
				}

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

			drawLine();

			//マウス位置を記憶
			_lastMouseX = mouseX;
			_lastMouseY = mouseY;
		}

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

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

球が通り抜ける布みたいなのを作る

前回(バネ運動するネットみたいなのを作る)からの続き。
ドラッグすると球が大きくなります。

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

今回のソース一式 net2.zip

前回(バネ運動するネットみたいなのを作る)は引っ張るネットを作りましたが、やっぱりProcreoFlashDesign Laboratory ボールと布や、52sec.orgさんのデモのようなのを作りたいので、挑戦しました。

まずは一個のボールをマウスに反応させるところから。
マウスとボールの位置を計算して、その距離に応じてボールが反応するようなのを作ってみた。

次は数を増やしていきます。
今回は線を連結しているボールは表示せず、ただ位置のプロパティを持っているだけのPlotPointってクラスを作って、マス目だけを引く事にしました。

球の座標の求め方が最初は分からなくて試行錯誤してしまったのですが、
ググったらすぐ出てきました。
<参考URL>
座標変換公式
1から始める数学 ベクトル解析 座標系 (ここの球座標系のところ。)

最初から調べればよかった…。
球の座標を求めた後、更に透視投影で座標変換してみたですが、変換しなかった際と比べ、あまり差がなかったので、結局、透視投影での変換はしてません。なのでZ値は無視しています。

一応今回のメインコード。
前回と変わったのはenterFrameHandler内ぐらいで、あとは大体やってる事は一緒です。

package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import org.miniapp.point.PlotPoint;

	[SWF(backgroundColor="0xFFFFFF", width="700", height="700", frameRate="60")]
	public class SphereNet extends Sprite
	{
		private static const _THETA_LIMIT:Number = Math.PI / 2; //90度
		private static const _MAX_RADIUS:uint = 200;
		private static const _MIN_RADIUS:uint = 100;
		private static const _SPRING:Number = 0.2;
		private static const _FRICTION:Number = 0.9;
		private static const _COLUM:uint = 20;
		private static const _ROW:uint = 20;
		private static const _NUM_POINTS:uint = _COLUM * _ROW;
		private static const _DIFF_X:uint = 20;
		private static const _DIFF_Y:uint = 20;
		private static const _START_X:uint = 160;
		private static const _START_Y:uint = 160;

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

		private var _sphereRadius:uint = SphereNet._MIN_RADIUS;
		private var _points:Array/* of PlotPoint */
		private var _horizontalPointsArray:Array/* of Array */
		private var _verticalPointsArray:Array/* of Array */

		public function init():void
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			_points = [];

			//ポイントを繋ぐ線を描くため、縦、横に分けて配列に入れて纏める。
			//縦に並ぶポイントを入れた配列をまとめる配列
			_horizontalPointsArray = [];
			//横に並ぶポイントを入れた配列をまとめる配列
			_verticalPointsArray = [];

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

			//ポイント生成
			for (i = 0; i < SphereNet._ROW; i++)
			{
				//横に並ぶボールを管理する配列を作る
				var verticalPoints:Array/* of PlotPoint */ = [];
				for (var j:uint = 0; j < SphereNet._COLUM; j++)
				{
					var point:PlotPoint = new PlotPoint();
					point.x = point.defaultX = _START_X + _DIFF_X * j;
					point.y = point.defaultY = _START_Y + _DIFF_Y * i;
					_points.push(point);

					//縦に並ぶポイントを入れる
					(_horizontalPointsArray[j] as Array).push(point);
					//横に並ぶポイントを入れる
					verticalPoints.push(point);
				}
				_verticalPointsArray.push(verticalPoints);
			}

			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}

		/**
		 * ボールを元の大きさにする
		 * @param	e
		 */
		private function mouseUpHandler(e:MouseEvent):void
		{
			_sphereRadius = SphereNet._MIN_RADIUS;
		}

		/**
		 * ボールを大きくする
		 * @param	e
		 */
		private function mouseDownHandler(e:MouseEvent):void
		{
			_sphereRadius = SphereNet._MAX_RADIUS;
		}

		private function enterFrameHandler(e:Event):void
		{
			for (var i:uint = 0; i < SphereNet._NUM_POINTS; i++)
			{
				var point:PlotPoint = PlotPoint(_points[i]);

				var dx:Number = point.defaultX - mouseX;
				var dy:Number = point.defaultY - mouseY;
				var distance:Number = Math.sqrt(dx * dx + dy * dy);

				//球の半径内にいる点に対して球の上に乗った時の座標計算
				//参考 http://kenpei-web.hp.infoseek.co.jp/math/coordinates/index.html
				if (distance <= _sphereRadius)
				{
					//距離と球の半径の関係から力がかかる倍率を決める
					var powerRate:Number = distance / _sphereRadius;

					//Z軸からXY平面への角度
					var theta:Number = SphereNet._THETA_LIMIT * powerRate;

					//真上から見た角度
					var angle:Number = Math.atan2(dy, dx);

					var sin:Number = Math.sin(theta);
					var toX:Number = mouseX + _sphereRadius * sin * Math.cos(angle);
					var toY:Number = mouseY + _sphereRadius * sin * Math.sin(angle);

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

		/**
		 * ポイントをバネ運動させる
		 * @param	point
		 * @param	targetX
		 * @param	targetY
		 */
		private function springTo(point:PlotPoint, targetX:Number, targetY:Number):void
		{
			point.vx += (targetX - point.x) * SphereNet._SPRING;
			point.vy += (targetY - point.y) * SphereNet._SPRING;

			point.vx *= SphereNet._FRICTION;
			point.vy *= SphereNet._FRICTION;

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

		/**
		 * ポイント同士を線で繋ぐ
		 */
		private function drawLine():void
		{
			graphics.clear();
			graphics.lineStyle(1, 0x000000);

			//縦のラインを引く
			for (var i:uint = 0; i < SphereNet._COLUM; i++)
			{
				var horizontalPoints:Array = _horizontalPointsArray[i] as Array;
				var firstPoint:PlotPoint = PlotPoint(horizontalPoints[0]);
				graphics.moveTo(firstPoint.x, firstPoint.y);
				for (var j:uint = 1; j < SphereNet._COLUM; j++)
				{
					var point:PlotPoint = PlotPoint(horizontalPoints[j]);
					graphics.lineTo(point.x, point.y);
				}
			}

			//横のラインを引く
			for (i = 0; i < SphereNet._ROW; i++)
			{
				var verticalPoints:Array = _verticalPointsArray[i] as Array;
				firstPoint = PlotPoint(verticalPoints[0]);
				graphics.moveTo(firstPoint.x, firstPoint.y);
				for (j = 1; j < SphereNet._ROW; j++)
				{
					point = PlotPoint(verticalPoints[j]);
					graphics.lineTo(point.x, point.y);
				}
			}
		}
	}
}

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

/*
<修正>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();
		}
	}
}

Spark project 勉強会 #01に行ってきました。

Spark project 勉強会 #01行ってきました。
とても濃い内容のスーパー勉強会でした。こういうの待ってました!
食い入って見てましたよ。

ほとんどの方がノートPC持参。
そしてMac率高い。

僕はノート持って無くてペンとノート(紙)。
やっぱノート(PC)欲しい。

既にminacoさんが、まとめを書かれています。
MinaLoぐぅぅ» Blog Archive » SparkProjectの勉強会

ぼくはyossyさんのActionScript Thread Library 1.0 (そうめん)の発表から書こうと思います。

1. ActionScript Thread Library 1.0 (そうめん) by yossy:BeInteractiveさん

既に有名なそうめん。
javaのスレッドを擬似的に再現しているそうで、その為、結城浩さんの『増補改訂版Java言語で学ぶデザインパターン入門マルチスレッド編』で紹介されているデザインパターンが使えるそうです。
とうわけで昨日帰ってから早速アマゾンで注文しました。もう届きました。すごい速さだアマゾン…。
早速そうめんでASスレッド入門しようと思う。

発表資料がUPされていますね。
BeInteractive! [Spark project 勉強会 #01 ありがとうございました]

2. GeniusFramework by seagirlさん

Flex用フレームワーク。ターミナルからコマンドを打って、必要なディレクトリ、ファイル群を一発生成。
Windowsで使うにはCygwinなどのアプリケーションが必要とのこと。
似たようなフレームワークとしてCairngorm(けあんごーむ) – Adobe Labsというのがあるそうだ。しかし、複雑で分かりにくい為、GeniusFrameworkの開発に至ったとのこと。

■2008/07/25 20:42追記 発表資料がseagirlさんのBlogにUPされています。
Spark project 勉強会 #1 – yoshizu@S2F

3. Frocessing by NUTSUさん

ProcessingのAS3版(SparkProjectの方には「あくまでライクです。移植ではなくリファレンス実装なので〜」と書かれていますね。)
Processingらしいウネウネしたライン描画とか、RADIOHEADのGoogleCodeにあがってるアレとか動かしてらっしゃった。Blogで既にUPされていた物とはちょっと違っていたかな? 口元が動いていたような。
懇親会で教えてもらったのですが、公開されているProcessingのサンプルもAS3の書き方に直す(変数宣言の部分とか)だけで、そのまま動かす事が可能とのこと。ただ、flight404の人の様なProcessingの達人な方は、ほとんどProcessingでは無くなっているそうで、直接OpenGLを操作していたりするそうだ。

4. Flash Player Mental Model by arkwさん

1フレームの中でどのような処理が行われているかの話。
ENTER_FRAMEとTimer、マウスイベントを使ったサンプルを動かし説明されていた。
まだ良く理解できていないので、arkwさんのエントリを読んで理解する。

5. sazameki by zk33さん

オーディオ操作ライブラリ。サウンドを動的に生成したり、エフェクトを付けたり。
単音にディレイをかけてロックマンのやられたときの音(ティウンティウン)を作ってらした。
FlashPlayer10 beta2がインストールされていれば、最後に発表されたリズムマシン?のデモがzk33さんの発表記事から体験できます。

2008/07/24 記事訂正しました。 デモswfファイルへの直リンクをしていましたが、不適切と感じたのでリンク先を変更しました。すみません。

これで簡単な曲を作ってらっしゃった。リズムがだんだん曲になっていく様子はやっぱ楽しい。
これには会場が沸きました。

デモではスイングも実装されてた。デモの右下にあるボタンで調整されてたかな?? 以下はスイングの参考リンク(いいのが見つからなかった。ちょっと違うかも)。
DTMでのグルーヴ設定方法(swing)

発表資料がご本人のBlogにUPされています。
Spark project勉強会#1で発表してきましたよ – zk_diary

6. 昨今の(X)HTMLに準拠したswfの埋め込みについて(embedタグ使わないとか、swfobject 2とか) by ksakaiさん

swfをHTMLに埋め込む際の注意点。
embedは今後廃止の方向。
safariでのHTMLからの変数の受け渡しなど。
DreamWeaver CS4ではswfObjectを使ったHTMLが書き出されていた。←ここはうろ覚えです、すみません…。)

そのほか

拡張子のswfって、「すぅいふ」って読むんですね。
Adobeの方も発表者の方も、皆さん、この読み方だったので間違いない。きっと。
今まで「えすだぶりゅえふ」って読んでました。
Shockwave Flashの略だと思うんですがどうなんでしょう。

というわけで、とても充実した勉強会でした。
お疲れ様でした。そして有り難うございました。
僕も発表できるよう頑張ろ。超頑張ろ。

Flash OOP for AS3の本で

昔、少しだけ書いて、現在は放置してしまっているblogがあるんですが、
そこに書いた下記のjsflがFlash OOP for AS3の109ページで取り上げてもらってました。

  座標の小数点以下を四捨五入するjsfl作った by 9server.net

すごくビックリ&興奮。目を疑ったわ。
なんてこと無いjsflなんですが、宜しければお使い下さい。

他にも四捨五入するjsflはあったと思うのですが、僕のを選んでくださった
執筆者のnagggさん、ありがとうございます!

なんで放置しちゃったかと言うと、
最初が数字だとパッケージ名として使えないことに気付いたからです。
だから最初が数字で始まるドメインって取りやすかったんだ〜と納得。
昔のブログ書き始めたときは、そんなことも知りませんでした。

  _parentするならSingletonのお話2とか書いたけど、
今見ると良くない例っぽいのでどうしよう。他のも。
動いちゃうからタチが悪いんだな。

ActionScript3.0アニメーション読み終えた

やっとです。
噂に違わぬいい本だった。
パーティクル、キネマティクスの章が特に面白かった。

最後の章で行列とかを少し突っ込んで解説してるけど、
あそこは良くわからないかも。専門書読んだ方が分かりやすい。

三角関数まではそこそこ解説するけど、それより複雑な箇所は
本の範疇から外れるから公式丸暗記で、というスタイル。
気になる部分は専門書読んで掘り下げてみよっと。

覚えたテクニック使って何かサンプル作ってみないとね。

ActionScript3.0アニメーション

なんだか全くFlashを触っていなくて不安になったので、途中になっていたActionScript 3.0 アニメーションをやっています。
まだまだ途中ですが、この本のChapter8でこういうのが出来ました。本では3つのボールをバネで繋いでますが、何個でも増やせるようにしました。増やしすぎると訳が分からなくなりますが…。
黒いボールはドラッグ出来ます。


ピクチャ 3.png ピクチャ 4.png

バネ運動をやっているのですが、綾取りみたいになって面白い。
やっぱこの本凄い。基本的なところから徐々にレベルアップしていって、無理なく覚えられる。
全部一気に詰め込むのでなくて、細かい部品の作り方を徹底的に教えてくれて、あとでそれを組み立てて大きい面白い物を作ろう、ってかんじ。

欠点は大きくて分厚くて持ち運びに向かないこと。結構余白が残っている印象で、文字も小さくすればかなりコンパクトになると思うけど、見やすさの為しょうがないですね。

ここから先が楽しみ。

今までFlashDevelopでやっていけど、今回はFlexを使った。補完はFlashDevelopの方が使いやすいな。ガンガン補完してくれるんだもん。でもFlexは逐一文法エラーだとかを教えてくれる。
かなりうっかり者の僕にはありがたい。つまらないミスに気付かず何時間もハマルってのが減るかも?
それとリファクタリング機能がやはり便利。これはFlashDevelopには無い。そのうち実装される予定らしい?

一応コードを載せます。
まず、本の至る所で使うBall.as。サンプルのまんま。

package {
	import flash.display.Sprite;

	public class Ball extends Sprite {
		public var radius:Number;
		private var color:uint;
		public var vx:Number = 0;
		public var vy:Number = 0;

		public function Ball(radius:Number=40, color:uint=0xff0000) {
			this.radius = radius;
			this.color = color;
			init();
		}
		public function init():void {
			graphics.beginFill(color);
			graphics.drawCircle(0, 0, radius);
			graphics.endFill();
		}
	}
}

次に、今回用に拡張したBallクラス。

package
{
	public class CustomBall extends Ball
	{
		public function CustomBall(radius:Number=40, color:uint=0x000000)
		{
			super(radius, color);
		}

		private var _isDragging:Boolean = false;
		private var _id:uint;

		public function get isDragging():Boolean{return _isDragging;}
		public function set isDragging(value:Boolean):void
		{
			_isDragging = value;
		}

		public function get id():uint{return _id;}
		public function set id(value:uint):void
		{
			_id = value;
		}
	}
}

最後にメインとなるクラス。
コメントにも書いたけど、macのfirefoxだとstage.stageWidth、stage.stageHeightが0になる。
なんでだ。それとmacのブラウザで見るとCPUを喰ってる。parallels上のwinows版Firefoxは全然CPUを喰わないし、ローカルでの速さとほぼ同じ。なんでなんだ。

package
{
	import flash.display.Sprite;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;

	public class SpringTest extends Sprite
	{
		public function SpringTest()
		{
			init();
		}

		private var balls:Array/* of CustumBall */;
		private var ballNum:int = 5;
		private var friction:Number = 0.95;
		private var spring:Number = 0.05;
		private var springLength:Number = 100;

		private function init():void
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			balls = [];
			for(var i:uint = 0; i < ballNum; i++)
			{
				var ball:CustomBall = new CustomBall(20);
				ball.id = i;//動作確認用

				//trueにすると多少軽くなる?が、エッジが欠ける
				//ball.cacheAsBitmap = true;
				ball.addEventListener(MouseEvent.MOUSE_DOWN, onBallMouseDown);
				ball.addEventListener(MouseEvent.MOUSE_UP, onBallMouseUp);

				//mac firefoxだとstage.stageWidth、stage.stageHeightが0になる
				//ball.x = Math.random() * stage.stageWidth;
				//ball.y = Math.random() * stage.stageHeight;

				var STAGE_SIZE:uint = 600;
				ball.x = Math.random() * STAGE_SIZE;
				ball.y = Math.random() * STAGE_SIZE;
				balls.push(ball);
				addChild(ball);
			}
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}

		private function onEnterFrame(e:Event):void
		{
			for(var i:uint = 0; i < ballNum; i++)
			{
				var ball:CustomBall = CustomBall(balls[i]);
				if(!ball.isDragging)
				{
					for(var j:uint = 0; j < ballNum; j++)
					{
						var objectivePointBall:CustomBall = CustomBall(balls[j]);
						//自分以外のボールに対して位置を調整する
						if( objectivePointBall != ball)
							springTo(ball, objectivePointBall);
					}
				}
			}

			//ラインを引く
			graphics.clear();
			graphics.lineStyle(1, 0x000000);
			graphics.moveTo(CustomBall(balls[0]).x, CustomBall(balls[0]).y);
			for(var i:uint = 1; i < ballNum; i++)
			{
				graphics.lineTo(CustomBall(balls[i]).x, CustomBall(balls[i]).y);
			}
			graphics.lineTo(CustomBall(balls[0]).x, CustomBall(balls[0]).y);
		}

		private function onBallMouseDown(e:MouseEvent):void
		{
			var ball:CustomBall = CustomBall(e.target);
			ball.startDrag();
			ball.isDragging = true;
		}

		private function onBallMouseUp(e:MouseEvent):void
		{
			var ball:CustomBall = CustomBall(e.target);
			ball.stopDrag();
			ball.isDragging = false;
		}

		/**
		 * バネ運動の処理
		 * @param ball 動かす対象のボール
		 * @param objectivePointBall 目標位置とするボール
		 *
		 */
		private function springTo(ball:CustomBall, objectivePointBall:CustomBall):void
		{
			var angle:Number = Math.atan2(objectivePointBall.y - ball.y, objectivePointBall.x - ball.x);
			var targetX:Number = objectivePointBall.x - Math.cos(angle) * springLength;
			var targetY:Number = objectivePointBall.y - Math.sin(angle) * springLength;
			ball.vx += (targetX - ball.x) * spring;
			ball.vy += (targetY - ball.y) * spring;
			ball.x += (ball.vx *= friction);
			ball.y += (ball.vy *= friction);
		}
	}
}

Flash Player 10 beta

ここで新機能を紹介してるMovieを見たのだけど、すんげー。
Adobe Labs – Flash Player 10 Feature Demos and Videos

akihiro kamijo: Flash Player 10 beta 公開
Adobe Labs – Flash Player 10

個人的にこれが好き。画像ぐりんぐりん弄るやつ。
Watch Justin Everett-Church demonstrate custom filters and effects

Pixcel Bender Toolkitっていうの使うみたいだけど、
このページAdobe Labs – Flash Player 10にはAfter Effects CS3で使われているフィルターと同じ技術が使われているって書いてあんのかな?
After Effectsで使ってるエフェクトをそのまま持ってきたり出来るんだろうか。
AIF ToolkitがPixcel Bender Toolkitになったのかな??
AIF Toolkitのデモとレビュー
Richardさん凄い。

新 masafumi’s Diary: Pixel Blender動かしてみた
もう動かしている方がいるのか〜。

それと音の生成。バナー張ってるけど、Adobe, MAKE SOME NOISEキャンペーン(?)は成功みたいな感じなのかな。goolge翻訳で読んだだけだから分かんなかったけど。

これがAS書かなくてもタイムライン・アニメーションで出来れば一昔前のFlashブームみたいなのが再来しそうなのに。
現在は一部の超凄い人オンリーな表現が簡単に出来ちゃったら夢のようだわ。
競争率かなり上がりそうだけど。

少なくとも3DはFlash CS4でタイムラインでもOKになるんじゃないかな。
画像いじりは無理そう…。
After Effectsと連携したりするんか!?

というかAS書けたとしても、更に画像処理とかの知識が必要になったら、
Flashは更にとっつきづらい、一部の人のものな感じがになるな〜。
僕も付いていけんかもしれん。

(追記)
もう和訳が!
FlashPlayer/10/ReleaseNote – Spark project
早!助かります。
やっぱPixel Blender使おうとすると画像処理のプログラム知識が必須なのかなー。
数学とかも必須か。
なんか便利ツールも一緒に出ないのかなー。
GUIで簡単にエフェクトが作れます、みたいな。

追記
Pixel Blenderじゃないですね。
正しくはPixel Bender。

ごはんとFlashに行ってきた

「ごはんとFlash」に参加しに、鎌倉のbowlsまで行ってきました!
★マークのTシャツ着てた者です。

こういうイベントに行くのは初めてで、しかも一人で参加だったので、思いっきり腰が引けてしまいました。しかも時間の配分を思いっきり間違えて20分遅刻…。

しかし皆さん気さくな方で、沢山質問して色々と情報を聞いてしまった!ありがとうございます!
なかなか社外のFlashをやっている方と触れあう機会というのはないので、日々、「他の人はここをどうやっているんだろう???」と悩む事が多々あったのですが、そういう疑問点をたっぷり聞かせてもらえました。本当に感謝です。
沢山あたまに詰め込みすぎて、帰ってから頭の中パンパンになってしまった。

返ってから何人くらいの方に挨拶できたのかと数えたら、20人ほどだった。60人参加ということだったので、1/3の方としか喋れていない。ご挨拶できなかった方、すみません。

僕が一方的に知っていて、web上で良く見かける、勝手にお世話になっている方々と沢山お会いできて感無量だった。
この人がーー!!みたいな。
kayac、cuppyの方も沢山いらっしゃって、話を聞いて、とても楽しい会社なのだな~と。
旅する支社 – 面白法人カヤック
これにはビックリした。

KAYAC:道家さんtrick7:寺井さんFICC:福岡さん、素敵な場を作ってくださってありがとうございます! 今後もこういう集まりには積極的に参加していきたい!

まだFlashの技術的なエントリを書いてませんが、近々いいかげん書きます。よろしくお願いします!

Home > Tags > flash

Return to page top