Home > Archives > 2008-08

2008-08

emacsキーバインド & Happy Hacking Keyboard

以前からemacsキーバインドって慣れると便利なんだろなー、って思ってたので、
macだとKeyRemap4MacBook、WindowsだとXKeymacs使って、他のアプリケーションでemacsキーバインドを使ってます。
特にXKeymacsはかなり色々できて凄いです。はてなの伊藤直也さんも愛用しているようですね。
ですが肝心のFlashDevelopではいくつかの機能が動いてくれませんでした。残念。

やっぱり慣れると楽ちんです。矢印キーまで手を移動させなくて済むのは快適。
遠いエンターキーも押さなくて済んでます。

キーボードはMac純正 US配列のWirelessKeyboardを使っていたんだけど、日本語配列のHHKB Lite2 for Macにしました。
理由はスペースキーが小さめで、その周りのボタンが多い&押しやすい位置にあったから。
大きいスペースキーが苦手なのです。

追記
またUS配列に戻しました…。

さらに、KeyRemap4MacBookのソースは公開されているので、英数キーとかなキーの設定を他のキーとのコンビネーションで押したときはCmmandにする機能を弄り、Optionにする機能に変更。
Windowsの方も変換、無変換キーをAltに変更。こちらはコンビネーションの時だけってのは見つからなかった。

それとSandSは便利です。スペースキー単体で押すとそのままのスペース、他のキーとのコンビネーションでShiftになる機能。KeyRemap4MacBookとXKeymacsの両方で出来ます。

親指でいろんな修飾キーが操作できて快適。

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

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

別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);
				}
			}
		}
	}
}

Home > Archives > 2008-08

Return to page top