Beispiel #1
0
 public void React(int id, int count, ICollisionActor actor, CollisionResult result)
 {
     if (actor is AttackCollisionActor)
     {
         AttackReaction(id, count, actor as AttackCollisionActor, result);
     }
 }
        public bool Detect(CollisionResult result)
        {
            var baseA = ParamA.Base();
            var baseB = ParamB.Base();
            var horizontalA = new Vector2(baseA.X, baseA.Z);
            var horizontalB = new Vector2(baseB.X, baseB.Z);

            // 水平交差判定
            var hOverlapVector = horizontalB - horizontalA;
            var hCenterLength = hOverlapVector.Length();
            var hOverlapLength = ParamA.Radius() + ParamB.Radius() - hCenterLength;
            hOverlapVector *= hOverlapLength / hCenterLength;

            var horizontal = hOverlapLength > 0.0f;

            if (!horizontal)
            {
                result.Overlap = Vector3.Zero;
                return false;
            }

            result.Overlap.X = hOverlapVector.X;
            result.Overlap.Z = hOverlapVector.Y;

            // 垂直交差判定
            var al = baseA.Y;
            var ah = al + ParamA.Height();
            var bl = baseB.Y;
            var bh = bl + ParamB.Height();
            var vertical =
                (al > bl && al < bh)
                || (ah > bl && ah < bh)
                || (bl > al && bl < ah)
                || (bh > al && bh < ah);

            if (!vertical)
            {
                result.Overlap = Vector3.Zero;
                return false;
            }

            // Aの下とBの上がめり込んでると見る場合
            var a_bottom_b_top = al - bh;
            
            // Aの上とBの下がめり込んでると見る場合
            var a_top_b_bottom = ah - bl;

            // めり込み量が少ない方を採用
            result.Overlap.Y =
                MathUtil.Abs(a_bottom_b_top) < MathUtil.Abs(a_top_b_bottom)
                ? a_bottom_b_top
                : a_top_b_bottom;

            return true;
        }
        public bool Detect(CollisionResult result)
        {
            // 中心間ベクトル
            var overlap = ParamB.Center() - ParamA.Center();
            
            // 中心間の距離
            var centerLength = overlap.Length();

            // めり込み距離
            var overlapLength = ParamA.Radius() + ParamB.Radius() - centerLength;

            // めり込みベクトル
            overlap *= overlapLength / centerLength;

            result.Overlap = overlap;
            
            return overlapLength > 0.0f;
        }
        public bool Detect(CollisionResult result)
        {
            // 垂直交差判定
            var al = Cylinder.Base().Y;
            var ah = al + Cylinder.Height();
            var bl = AABB.Corner.Y;
            var bh = bl + AABB.Width.Y;
            var vertical =
                (al > bl && al < bh)
                || (ah > bl && ah < bh)
                || (bl > al && bl < ah)
                || (bh > al && bh < ah);

            if (!vertical)
            {
                result.Overlap = Vector3.Zero;
                return false;
            }

            {
                // Aの下とBの上がめり込んでると見る場合
                var a_bottom_b_top = al - bh;

                // Aの上とBの下がめり込んでると見る場合
                var a_top_b_bottom = ah - bl;

                // めり込み量が少ない方を採用
                result.Overlap.Y =
                    MathUtil.Abs(a_bottom_b_top) < MathUtil.Abs(a_top_b_bottom)
                    ? a_bottom_b_top
                    : a_top_b_bottom;
            }

            // 水平交差判定

            if (Cylinder.Base().X + Cylinder.Radius() < AABB.Corner.X
                || Cylinder.Base().X - Cylinder.Radius() > AABB.Corner.X + AABB.Width.X)
            {
                result.Overlap = Vector3.Zero;
                return false;
            }

            if (Cylinder.Base().Z + Cylinder.Radius() < AABB.Corner.Z
                || Cylinder.Base().Z - Cylinder.Radius() > AABB.Corner.Z + AABB.Width.Z)
            {
                result.Overlap = Vector3.Zero;
                return false;
            }

            var horizontal = false;

            if (Cylinder.Base().X > AABB.Corner.X
                && Cylinder.Base().X < AABB.Corner.X + AABB.Width.X)
            {
                horizontal = true;
            }

            {
                // 円が箱の左辺から右方向にめり込んでると見る場合
                var a_right_b_left = (Cylinder.Base().X + Cylinder.Radius()) - AABB.Corner.X;

                // 円が箱の右辺から左方向にめり込んでると見る場合
                var a_left_b_right = (Cylinder.Base().X - Cylinder.Radius()) - (AABB.Corner.X + AABB.Width.X);

                // めり込み量が少ない方を採用
                result.Overlap.X =
                    MathUtil.Abs(a_right_b_left) < MathUtil.Abs(a_left_b_right)
                    ? a_right_b_left
                    : a_left_b_right;
            }

            if (Cylinder.Base().Z > AABB.Corner.Z
                && Cylinder.Base().Z < AABB.Corner.Z + AABB.Width.Z)
            {
                horizontal = true;
            }

            {
                // 円が箱の上辺から下方向にめり込んでると見る場合
                var a_bottom_b_top = (Cylinder.Base().Z + Cylinder.Radius()) - AABB.Corner.Z;

                // 円が箱の下辺から上方向にめり込んでると見る場合
                var a_top_b_bottom = (Cylinder.Base().Z - Cylinder.Radius()) - (AABB.Corner.Z + AABB.Width.Z);

                // めり込み量が少ない方を採用
                result.Overlap.Z =
                    MathUtil.Abs(a_bottom_b_top) < MathUtil.Abs(a_top_b_bottom)
                    ? a_bottom_b_top
                    : a_top_b_bottom;
            }

            if (horizontal)
            {
                return true;
            }

            // 4つの角のうち最短距離が筒の半径以内か

            var corners = new List<Vector2>();

            corners.Add(new Vector2(AABB.Corner.X, AABB.Corner.Z));
            corners.Add(new Vector2(AABB.Corner.X + AABB.Width.X, AABB.Corner.Z));
            corners.Add(new Vector2(AABB.Corner.X + AABB.Width.X, AABB.Corner.Z + AABB.Width.Z));
            corners.Add(new Vector2(AABB.Corner.X, AABB.Corner.Z + AABB.Width.Z));

            var cylinderCenter = new Vector2(Cylinder.Base().X, Cylinder.Base().Z);

            var minLength = corners.Min((corner) =>
            {
                return (corner - cylinderCenter).LengthSquared();
            });

            if (minLength >= (Cylinder.Radius() * Cylinder.Radius()))
            {
                result.Overlap = Vector3.Zero;
                return false;
            }

            // 最短距離の角
            var minCorner = corners.First((corner) =>
            {
                return minLength == (corner - cylinderCenter).LengthSquared();
            });

            {
                // 円が箱の左辺から右方向にめり込んでると見る場合
                var a_right_b_left = (cylinderCenter.X + Cylinder.Radius()) - minCorner.X;

                // 円が箱の右辺から左方向にめり込んでると見る場合
                var a_left_b_right = (cylinderCenter.X - Cylinder.Radius()) - minCorner.X;

                // めり込み量が少ない方を採用
                result.Overlap.X =
                    MathUtil.Abs(a_right_b_left) < MathUtil.Abs(a_left_b_right)
                    ? a_right_b_left
                    : a_left_b_right;
            }

            {
                // 円が箱の上辺から下方向にめり込んでると見る場合
                var a_bottom_b_top = (cylinderCenter.Y + Cylinder.Radius()) - minCorner.Y;

                // 円が箱の下辺から上方向にめり込んでると見る場合
                var a_top_b_bottom = (cylinderCenter.Y - Cylinder.Radius()) - minCorner.Y;

                // めり込み量が少ない方を採用
                result.Overlap.Z =
                    MathUtil.Abs(a_bottom_b_top) < MathUtil.Abs(a_top_b_bottom)
                    ? a_bottom_b_top
                    : a_top_b_bottom;
            }

            return true;
        }
Beispiel #5
0
 public void React(int id, int count, ICollisionActor actor, CollisionResult result)
 {
     Reaction(id, count, result);
 }
Beispiel #6
0
 void Damage(int collisionId, int collisionCount, AttackCollisionActor actor, CollisionResult result)
 {
     if (HitPoint > 0 && collisionCount == 1)
     {
         HitPoint -= actor.Power;
         DebugPrint.PrintLine("Enemy damage {0}, HP {1}", actor.Power, HitPoint);
         ComboCounter.Damage(actor.Shock);
     }
     if (HitPoint <= 0)
     {
         UpdateState = UpdateStateTerm;
         DecoManager.Add(new ccm.Deco.Deco_Twister(Transform, Camera, GameRand));
     }
 }
Beispiel #7
0
 void Guard(int collisionId, int collisionCount, AttackCollisionActor actor, CollisionResult result)
 {
     if (HitPoint > 0 && collisionCount == 1)
     {
         //SoundManager.PlaySoundEffect("metal03");
         //DebugPrint.PrintLine("Player guard");
         ComboCounter.Guard(actor.Shock);
         if (ComboCounter.Shocked)
         {
             GoToShocked();
         }
     }
 }
Beispiel #8
0
 void Damage(int collisionId, int collisionCount, AttackCollisionActor actor, CollisionResult result)
 {
     if (HitPoint > 0 && collisionCount == 1)
     {
         HitPoint -= actor.Power;
         DebugPrint.PrintLine("Player damage {0}, HP {1}", actor.Power, HitPoint);
         ComboCounter.Damage(actor.Shock);
         if (ComboCounter.Shocked)
         {
             GoToShocked();
         }
     }
 }
Beispiel #9
0
        bool Detect(CollisionInfo a, CollisionInfo b, CollisionResult result)
        {
            foreach (var primitiveA in a.Primitives)
            {
                foreach (var primitiveB in b.Primitives)
                {
                    if (DetectorFactory.Create(primitiveA, primitiveB).Detect(result))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
Beispiel #10
0
        void Detect(int alpha, int beta)
        {
            // 衝突判定が有効なものだけ取り出すクエリ
            var activeQuery = GetActiveQuery();

            var alphaQuery = GetActiveGroupQuery(activeQuery, alpha);

            var betaQuery = GetActiveGroupQuery(activeQuery, beta);

            foreach (var a in alphaQuery)
            {
                foreach (var b in betaQuery)
                {
                    var result = new CollisionResult();
                    if (Detect(a, b, result))
                    {
                        result.Detected = true;

                        var collisionCount = UpdateCollisionMatrix(a, b);
                        var collisionID = ++collisionIDCount;

                        // 衝突応答
                        a.Reactor.React(collisionID, collisionCount, b.Actor, result);
                        b.Reactor.React(collisionID, collisionCount, a.Actor,
                            new CollisionResult()
                            {
                                Detected = result.Detected,
                                Overlap = -result.Overlap,  // めり込みベクトルは反転させる
                                Distance = result.Distance,
                            });
                    }
                }
            }
        }