package { import flash.geom.Point; public class IRMouse{ private var translatePoint:Point = new Point(612, 384); private var pd:Point; private var toDEGREES:Number = 180/Math.PI; private var p1isLeft:Boolean; private var twoPointsFound:Boolean = false; private var mtx1 = Mtx33Translate(-translatePoint.x, -translatePoint.y); private var mtx3 = Mtx33Translate(translatePoint.x, translatePoint.y); private var _x:Number = 0; private var _y:Number = 0; private var _rotation:Number = 0; private var _width:Number; private var _height:Number; private var _xscale:Number = 1; private var _yscale:Number = 1; private var w:Object; //; public function IRMouse(w:Number = 1024 ,h:Number = 768){ this._width = w; this._height = h; this._xscale = 1024/this._width; this._yscale = 768/this._height; } public function update(w:Object) { this.w = w; var vec1; if (w.p1Found && w.p2Found) { //IR1とIR2が2点両方とも表示されている場合 vec1 = getMousePoint(new Point(1024-w.p1dX, w.p1dY), new Point(1024-w.p2dX, w.p2dY), true); twoPointsFound = true; } else if (twoPointsFound) { //今は2点表示されていないが、さっきまで2点表示されていた場合 if (w.p1Found) { //ポイント1が表示されている場合 vec1 = getMousePointFrom1Point(new Point(1024-w.p1dX, w.p1dY), p1isLeft); } else if (w.p2Found) { //ポイント2が表示されている場合 vec1 = getMousePointFrom1Point(new Point(1024-w.p2dX, w.p2dY), !p1isLeft); } else { //どちらも表示されていない場合 twoPointsFound = false; } } if (twoPointsFound) { this._x = vec1.x; this._y = vec1.y; this._rotation = vec1.rotation; } }; public function get x():Number{ return this._x/this._xscale; } public function get y():Number{ return this._y/this._yscale; } public function get rotation():Number{ return this._rotation; } public function get width():Number{ return this._width; } public function set width(w:Number):void{ this._width = w; this._xscale = 1024/this._width; } public function get height():Number{ return this._height; } public function set height(h:Number):void{ this._height = h; this._yscale = 768/this._height; } //加速度XとZからリモコンの角度を求める private function getRadian(wcX:Number, wcZ:Number):Number { var retval; //Zの値を畳み込む if (wcZ>Math.PI/4) { wcZ = Math.PI/4; } else if (-wcZ>Math.PI/4) { wcZ = -Math.PI/4; } //XとZのうち精度が高い方を利用して角度を求める if (Math.abs(wcX)<=Math.PI/4) { retval = Math.asin(wcX); if (wcZ<0) retval = Math.PI-retval; } else { retval = -Math.asin(wcZ); if (wcX<0) retval = Math.PI-retval; retval += Math.PI/2; } return retval; } //2点が表示されている場合の角度と中点を求める private function getMousePoint(p1:Point, p2:Point, twoPoint:Boolean):Object { pd = p1.subtract(p2); //角度を求める; var angleInRadians:Number = Math.atan2(pd.y, -pd.x); //角度を4つの範囲に当てはめて、加速度Xまたは加速度Zと比較する; var isWrongAngle:Boolean = false; p1isLeft = true; switch (Math.round(angleInRadians/Math.PI*2)) { case 0 : if (w.wcZ<0) isWrongAngle = true; break; case 1 : if (w.wcX<0) isWrongAngle = true; break; case -1 : if (w.wcX>0) isWrongAngle = true; break; default : if (w.wcZ>0) isWrongAngle = true; } if (isWrongAngle) { angleInRadians = angleInRadians+Math.PI; p1isLeft = false; } return getTransformedMiddlePoint(p1, p2, angleInRadians); } //1点のみ表示されている場合の角度と中点を求める private function getMousePointFrom1Point(p:Point, pIsLeft:Boolean):Object { var angleInRadians:Number = getRadian(w.wcX, w.wcZ); var pOther:Point = Point.polar(pd.length, -angleInRadians); pOther = (pIsLeft) ? p.add(pOther) : p.subtract(pOther); return getTransformedMiddlePoint(p, pOther, angleInRadians); } //ベクトルを用いて中点を求める処理 private function getTransformedMiddlePoint(p1:Point, p2:Point, angleInRadians:Number):Object { var degree:Number = angleInRadians*toDEGREES; var pm = Point.interpolate(p1, p2, 0.5); var mtx2 = Mtx33Rotate(angleInRadians); var mtx4 = Mtx33Transform(mtx1, mtx2); mtx4 = Mtx33Transform(mtx4, mtx3); var vec1 = Vec2dTransformPoint(pm.x, pm.y, mtx4); var retObj:Object = {x:vec1.x, y:vec1.y, rotation:degree}; return retObj; } private function Mtx33Translate(x, y){ return [[1, 0], [0, 1], [x, y]]; } private function Mtx33Rotate(rad) { var cos = Math.cos(rad); var sin = Math.sin(rad); return [[cos, sin], [-sin, cos], [0, 0]]; } private function Mtx33Transform(m1, m2) { return [[m1[0][0]*m2[0][0]+m1[0][1]*m2[1][0], m1[0][0]*m2[0][1]+m1[0][1]*m2[1][1]], [m1[1][0]*m2[0][0]+m1[1][1]*m2[1][0], m1[1][0]*m2[0][1]+m1[1][1]*m2[1][1]], [m1[2][0]*m2[0][0]+m1[2][1]*m2[1][0]+m2[2][0], m1[2][0]*m2[0][1]+m1[2][1]*m2[1][1]+m2[2][1]]]; } private function Vec2dTransformPoint(x, y, m) { return {x:x*m[0][0]+y*m[1][0]+m[2][0], y:x*m[0][1]+y*m[1][1]+m[2][1]}; } } }