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; }
public void React(int id, int count, ICollisionActor actor, CollisionResult result) { Reaction(id, count, result); }
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)); } }
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(); } } }
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(); } } }
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; }
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, }); } } } }