/// <summary> /// コリジョン形状の変更 /// </summary> /// <remarks> /// コリジョン形状を変更します。 /// コリジョン形状に <c>null</c> に設定すると例外が発生します。 /// </remarks> /// <param name="shape">コリジョン形状</param> public void SetShape(Collision shape) { if (shape == null) { throw new ArgumentNullException ("Shape is null"); } var p2d = Physics2D.GetInstance (); this.shape = shape; this.body.CreateFixture (shape.CreateShapeBody (p2d.PPM), this); // コリジョン イベントは Body ではなく Fixture にセットされるので、 // 形状を定義した後にセットする必要がある。 this.body.OnCollision += new OnCollisionEventHandler (CollisionEnterEventHandler); this.body.OnSeparation += new OnSeparationEventHandler (CollisionExitEventHandler); }
/* * /// <summary> /// 2物体の衝突の検出 /// </summary> /// <remarks> /// 2物体の衝突を検出します。 /// 現在のところ衝突地点とその法線について、それっぽい値を返していますが明確な取り決めはありません。 /// </remarks> /// <param name="shapeA">コリジョン形状A</param> /// <param name="matA">変換行列A</param> /// <param name="shapeB">コリジョン形状B</param> /// <param name="matB">変換行列B</param> /// <param name="col">結果を受け取るコリジョン構造体</param> /// <returns>衝突があれば<c>true</c>, そうでなければ <c>false</c>.</returns> public static bool Collide (Collision shapeA, Matrix4x4? matA, Collision shapeB, Matrix4x4? matB, out Collision col) { if (shapeA == null || shapeB == null) { throw new ArgumentNullException ("Shapes are null"); } var mani = new Manifold (); Vector3 T; Matrix3x3 R; Vector3 S; (matA ?? Matrix4x4.Identity).Decompress (out T, out R, out S); var shpA = shapeA.CreateShapeBody (1.0f); var posA = new XnaVector2 (T.X, T.Y); var rotA = new Mat22 (R[0], R[1], R[3], R[4]); var traA = new Transform (ref posA, ref rotA); (matB ?? Matrix4x4.Identity).Decompress (out T, out R, out S); var shpB = shapeB.CreateShapeBody (1.0f); var posB = new XnaVector2 (T.X, T.Y); var rotB = new Mat22 (R[0], R[1], R[3], R[4]); var traB = new Transform (ref posB, ref rotB); if (shapeA.IsPolygon && shapeB.IsPolygon) { FarseerPhysics.Collision.Collision.CollidePolygons (ref mani, (PolygonShape)shpA, ref traA, (PolygonShape)shpB, ref traB); } if (shapeA.IsPolygon && shapeB.IsCircle) { FarseerPhysics.Collision.Collision.CollidePolygonAndCircle (ref mani, (PolygonShape)shpA, ref traA, (CircleShape)shpB, ref traB); } if (shapeA.IsCircle && shapeB.IsPolygon) { MyMath.Swap (ref shpA, ref shpB); MyMath.Swap (ref traA, ref traB); FarseerPhysics.Collision.Collision.CollidePolygonAndCircle (ref mani, (PolygonShape)shpA, ref traA, (CircleShape)shpB, ref traB); } if (shapeA.IsCircle && shapeB.IsCircle) { FarseerPhysics.Collision.Collision.CollideCircles (ref mani, (CircleShape)shpA, ref traA, (CircleShape)shpB, ref traB); } XnaVector2 normal; FixedArray2<XnaVector2> points; switch (mani.PointCount) { case 0: { col = new Collision (null, Vector3.Zero, Vector3.Zero); return false; } case 1: { FarseerPhysics.Collision.Collision.GetWorldManifold (ref mani, ref traA, shpA.Radius, ref traB, shpB.Radius, out normal, out points); var p = new Vector3 (points[0].X, points[0].Y, 0); var n = new Vector3 (normal.X, normal.Y, 0); col = new Collision (null, p, n); return true; } case 2: { FarseerPhysics.Collision.Collision.GetWorldManifold (ref mani, ref traA, shpA.Radius, ref traB, shpB.Radius, out normal, out points); var p = new Vector3 ((points[0].X + points[1].X) / 2.0f, (points[0].Y + points[1].Y) / 2.0f, 0); var n = new Vector3 (normal.X, normal.Y, 0); col = new Collision (null, p, n); return true; } default: throw new InvalidOperationException ("This never happen"); } } /// <summary> /// 2物体の衝突の検出 /// </summary> /// <remarks> /// 2物体の衝突を検出します。衝突地点の情報を受け取らない事を除き同名の関数と等価です。 /// </remarks> /// <param name="shapeA">コリジョン形状A</param> /// <param name="matA">変換行列A</param> /// <param name="shapeB">コリジョン形状B</param> /// <param name="matB">変換行列B</param> /// <returns>衝突があれば<c>true</c>, そうでなければ <c>false</c>.</returns> public static bool Collide (Collision shapeA, Matrix4x4? matA, Collision shapeB, Matrix4x4? matB) { Collision col; return Collide (shapeA, matA, shapeB, matB, out col); } /// <summary> /// 2物体の衝突の検出 /// </summary> /// <remarks> /// 2物体の衝突を検出します。変換行列は自動的に <see cref="Node.GlobalTransform"/> を取得して使用します。 /// </remarks> /// <param name="shapeA">コリジョン形状A</param> /// <param name="shapeB">コリジョン形状B</param> /// <param name="col">結果を受け取るコリジョン構造体</param> /// <returns>衝突があれば<c>true</c>, そうでなければ <c>false</c>.</returns> public static bool Collide (Collision shapeA, Collision shapeB, out Collision col) { if(shapeA == null || shapeB == null){ throw new ArgumentNullException("Shapes are null"); } var matA = (shapeA.Node == null) ? Matrix4x4.Identity : shapeA.Node.GlobalTransform; var matB = (shapeB.Node == null) ? Matrix4x4.Identity : shapeB.Node.GlobalTransform; return Collide (shapeA, matA, shapeB, matB, out col); } /// <summary> /// 2物体の衝突の検出 /// </summary> /// <remarks> /// 2物体の衝突を検出します。衝突地点の情報を受け取らない事を除き同名の関数と等価です。 /// </remarks> /// <param name="shapeA">コリジョン形状A</param> /// <param name="shapeB">コリジョン形状B</param> /// <returns>衝突があれば<c>true</c>, そうでなければ <c>false</c>.</returns> public static bool Collide (Collision shapeA, Collision shapeB) { Collision col; return Collide (shapeA, shapeB, out col); } /// <summary> /// 2物体の最短距離の測定 /// </summary> /// <remarks> /// 2つのコリジョン形状の最短距離を求めます。 /// 2つの物体がオーバーラップしていた場合は一律 0 が帰り、負の値が変える事はありません。 /// <note> /// 必要性が感じられないので削除予定。使用禁止。 /// </note> /// </remarks> /// <param name="shapeA">コリジョン形状A</param> /// <param name="matA">変換行列A</param> /// <param name="shapeB">コリジョン形状B</param> /// <param name="matB">変換行列B</param> /// <returns></returns> public static float Distance (Collision shapeA, Matrix4x4? matA, Collision shapeB, Matrix4x4? matB) { if (shapeA == null) { Console.WriteLine ("Distance shapeA is null"); } if (shapeB == null) { Console.WriteLine ("Distance shapeB is null"); } ClosestPoints cp; return Distance (shapeA, matA, shapeB, matB, out cp); } /// <summary> /// 2物体の最短距離の測定 /// </summary> /// <remarks> /// 2つのコリジョン形状の最短距離を求めます。 /// 2つの物体がオーバーラップしていた場合は一律 0 が帰り、負の値が変える事はありません。 /// <note> /// 必要性が感じられないので削除予定。使用禁止。 /// </note> /// </remarks> /// <param name="shapeA">コリジョン形状A</param> /// <param name="matA">変換行列A</param> /// <param name="shapeB">コリジョン形状B</param> /// <param name="matB">変換行列B</param> /// <param name="cp">結果の再近接地点情報を受け取る</param> /// <returns>距離</returns> public static float Distance (Collision shapeA, Matrix4x4? matA, Collision shapeB, Matrix4x4? matB, out ClosestPoints cp) { DistanceOutput output; SimplexCache cache; DistanceInput input = new DistanceInput (); DistanceProxy proxyA = new DistanceProxy (); DistanceProxy proxyB = new DistanceProxy (); proxyA.Set (shapeA.CreateShapeBody (1), 0); proxyB.Set (shapeB.CreateShapeBody (1), 0); input.ProxyA = proxyA; input.ProxyB = proxyB; input.UseRadii = true; Vector3 T; Matrix3x3 M; Vector3 S; (matA ?? Matrix4x4.Identity).Decompress (out T, out M, out S); var posA = new XnaVector2 (T.X, T.Y); var rotA = new Mat22 (M[0], M[1], M[3], M[4]); input.TransformA = new Transform (ref posA, ref rotA); (matB ?? Matrix4x4.Identity).Decompress (out T, out M, out S); var posB = new XnaVector2 (T.X, T.Y); var rotB = new Mat22 (M[0], M[1], M[3], M[4]); input.TransformB = new Transform (ref posB, ref rotB); FarseerPhysics.Collision.Distance.ComputeDistance (out output, out cache, input); var pointA = new Vector3(output.PointA.X, output.PointA.Y, 0); var pointB = new Vector3 (output.PointB.X, output.PointB.Y, 0); cp = new ClosestPoints (pointA, pointB); return output.Distance; } /// <summary> /// コリジョン形状と1点の検出 /// </summary> /// <remarks> /// 日本語変・・・ /// </remarks> /// <param name="shapeA">コリジョン形状</param> /// <param name="matA">変換行列</param> /// <param name="point">判定したい1点</param> /// <returns>コリジョン形状の中にあれば<c>true</c>, そうでなければ <c>false</c>. </returns> public static bool Contain (Collision shapeA, Matrix4x4? matA, Vector2 point) { Vector3 T; Matrix3x3 R; Vector3 S; (matA ?? Matrix4x4.Identity).Decompress (out T, out R, out S); var shpA = shapeA.CreateShapeBody (1.0f); var posA = new XnaVector2 (T.X, T.Y); var rotA = new Mat22 (R[0], R[1], R[3], R[4]); var traA = new Transform (ref posA, ref rotA); var posB = new XnaVector2 (point.X, point.Y); return shpA.TestPoint (ref traA, ref posB); } /// <summary> /// レイキャストによる交差判定 /// </summary> /// <remarks> /// レイと物体の交差判定を行い、衝突結果を受け取ります。 /// </remarks> /// <param name="shapeA">形状A</param> /// <param name="matA">変換行列A</param> /// <param name="ray">レイ</param> /// <param name="rayOut">結果を受け取る <see cref="RayIntersection"/> オブジェクト</param> /// <returns>レイと物体が交差したら<c>true</c>, そうでなければ <c>false</c>.</returns> public static bool RayCast (Collision shapeA, Matrix4x4? matA, Ray ray, out RayIntersection rayOut) { FarseerPhysics.Collision.RayCastInput input; FarseerPhysics.Collision.RayCastOutput output; input.Point1 = Convert (ray.PointA); input.Point2 = Convert (ray.PointB); input.MaxFraction = ray.Fraction; var shpA = Convert (shapeA); var traA = Convert (matA ?? Matrix4x4.Identity); var hit = shpA.RayCast (out output, ref input, ref traA, 0); if (hit) { var normal = Convert (output.Normal); var frac = output.Fraction; rayOut = new RayIntersection (true, shapeA.Node, normal, frac, ray); } else { rayOut = new RayIntersection (); } return hit; } /// <summary> /// レイキャストによる交差判定 /// </summary> /// <remarks> /// レイと物体の交差判定を行います。衝突情報を受け取ります。 /// </remarks> /// <param name="shapeA">形状A</param> /// <param name="matA">変換行列A</param> /// <param name="ray">レイ</param> /// <returns></returns> public static bool RayCast (Collision shapeA, Matrix4x4? matA, Ray ray) { RayIntersection output; return RayCast (shapeA, matA, ray, out output); } /// <summary> /// レイキャストによる交差判定 /// </summary> /// <remarks> /// レイと物体の交差判定を行います。衝突情報を受け取ります。 /// 変換行列はアタッチされたノードの物を暗黙的に使用します。 /// </remarks> /// <param name="shapeA">形状A</param> /// <param name="ray">レイ</param> /// <param name="output">結果を受け取る <see cref="RayIntersection"/> 構造体</param> /// <returns></returns> public static bool RayCast (Collision shapeA, Ray ray, out RayIntersection output) { if (shapeA.Node == null) { throw new ArgumentException ("ShapeA is not attached"); } var matA = shapeA.Node.Transform; return RayCast (shapeA, matA, ray, out output); } /// <summary> /// レイキャストによる交差判定 /// </summary> /// <remarks> /// レイと物体の交差判定を行います。衝突情報を受け取りません。 /// 変換行列はアタッチされたノードの物を暗黙的に使用します。 /// </remarks> /// <param name="shapeA">形状A</param> /// <param name="ray">レイ</param> /// <returns></returns> public static bool RayCast (Collision shapeA, Ray ray) { RayIntersection output; var matA = shapeA.Node.Transform; return RayCast (shapeA, matA, ray, out output); } */ private static Shape Convert(Collision shape) { return shape.CreateShapeBody (1.0f); }