public static CollisionInformations CheckCollisionPadBall(Pad pad, Ball ball) { Vector3 size = Vector3.Multiply(Vector3.Add(pad.Size, ball.Size), 0.5f); Vector3[] v1 = { -Vector3.UnitX * size.X, Vector3.UnitX *size.X, -Vector3.UnitY * size.Y, Vector3.UnitY *size.Y }; Vector3[] v2 = { Vector3.UnitY *size.Y, -Vector3.UnitY *size.Y, Vector3.UnitX *size.X, -Vector3.UnitX *size.X }; Vector3[] v3 = { -Vector3.UnitZ * size.Z, Vector3.UnitZ *size.Z, -Vector3.UnitZ * size.Z, Vector3.UnitZ *size.Z }; CollisionInformations total_res = CollisionInformations.NOT_COLLIDING; for (int i = v1.Length - 1; i >= 0; i--) // reverse... we check the right and left faces first { CollisionInformations res = CalculateCollision(v1[i], v2[i], v3[i], ball, pad, yPhysics.Instance.DT, false); if (res.Colliding && res.CollisionT < total_res.CollisionT) { total_res = res; } } return(total_res); }
public static CollisionInformations CheckCollisionWalls(Level lvl, Box obj, bool ghost_wall) { // intern face of each lvl.Box* Box[] targets = { lvl.BoxDown, lvl.BoxRight, lvl.BoxUp, lvl.BoxLeft, lvl.BoxLimit, lvl.BoxLimit }; Vector3[] v1 = { -Vector3.UnitX * (lvl.BoxDown.Size.X + obj.Size.X) / 2, -Vector3.UnitY * (lvl.BoxRight.Size.Y + obj.Size.Y) / 2, Vector3.UnitX *(lvl.BoxUp.Size.X + obj.Size.X) / 2, Vector3.UnitY *(lvl.BoxLeft.Size.Y + obj.Size.Y) / 2, Vector3.UnitY *(lvl.BoxLimit.Size.Y + obj.Size.Y) / 2, Vector3.UnitY *(lvl.BoxLimit.Size.Y + obj.Size.Y) / 2 }; Vector3[] v2 = { Vector3.UnitY *(lvl.BoxDown.Size.Y + obj.Size.Y) / 2, Vector3.UnitX *(lvl.BoxRight.Size.X + obj.Size.X) / 2, -Vector3.UnitY * (lvl.BoxUp.Size.Y + obj.Size.Y) / 2, -Vector3.UnitX * (lvl.BoxLeft.Size.X + obj.Size.X) / 2, Vector3.UnitX *(lvl.BoxLimit.Size.X + obj.Size.X) / 2, -Vector3.UnitX * (lvl.BoxLimit.Size.X + obj.Size.X) / 2 }; Vector3[] v3 = { -Vector3.UnitZ * (lvl.BoxDown.Size.Z + obj.Size.Z) / 2, -Vector3.UnitZ * (lvl.BoxRight.Size.Z + obj.Size.Z) / 2, Vector3.UnitZ *(lvl.BoxUp.Size.Z + obj.Size.Z) / 2, Vector3.UnitZ *(lvl.BoxLeft.Size.Z + obj.Size.Z) / 2, Vector3.UnitZ *(lvl.BoxLimit.Size.Z + obj.Size.Z) / 2, Vector3.UnitZ *(lvl.BoxLimit.Size.Z + obj.Size.Z) / 2 }; CollisionInformations total_res = CollisionInformations.NOT_COLLIDING; for (int i = 0; i < targets.Length - (ghost_wall?0:2); i++) { CollisionInformations res = CalculateCollision(v1[i], v2[i], v3[i], obj, targets[i], yPhysics.Instance.DT, false); if (res.Colliding && res.CollisionT < total_res.CollisionT) { total_res = res; } } return(total_res); }
// global method public static CollisionInformations[] CheckCollisions(Level lvl, Pad[] pads, Ball[] balls) { LinkedList <CollisionInformations> collisions_done = new LinkedList <CollisionInformations>(); const int max_iteration = 200; const bool collision_between_balls = false; int iteration = 0; while (true) { if (++iteration > max_iteration) { break; } CollisionInformations[] collisions = new CollisionInformations[pads.Length + balls.Length + pads.Length * balls.Length + pads.Length * (pads.Length - 1) / 2 + (collision_between_balls?balls.Length * (balls.Length - 1) / 2:0)]; int collisionn = 0; for (int i = 0; i < pads.Length + balls.Length; i++) // a tricky loop, to do all the balls and all the pads at once { CollisionInformations res; if (i < pads.Length) { res = CheckCollisionWalls(lvl, (Box)pads[i], true); } else { res = CheckCollisionWalls(lvl, (Box)balls[i - pads.Length], false); } if (res.Colliding) // whenever a collision is found, the collisioninformations object is queued in the collision array { collisions[collisionn++] = res; } if (i < pads.Length) { for (int b = 0; b < balls.Length; b++) // check pad<->ball { res = CheckCollisionPadBall(pads[i], balls[b]); if (res.Colliding) { collisions[collisionn++] = res; } } for (int j = i + 1; j < pads.Length; j++) // check pad<->pad { res = CheckCollisionsBetweenPads(pads[i], pads[j]); if (res.Colliding) { collisions[collisionn++] = res; } } } } if (collision_between_balls) { for (int b = 0; b < balls.Length; b++) { for (int j = b + 1; j < balls.Length; j++) { CollisionInformations res = CheckCollisionBetweenBalls(balls[b], balls[j]); if (res.Colliding) { collisions[collisionn++] = res; } } } } if (collisionn == 0) { break; } int best_i = 0; for (int i = 1; i < collisionn; i++) { if (collisions[i].CollisionT < collisions[best_i].CollisionT) { if (collisions_done.Count > 0) { if (!collisions_done.Last.Value.hasSameObjects(collisions[i])) { best_i = i; } } else { best_i = i; } } } // check if (best_i=0) the only valid collision is the same as the last one Apply()ed if (collisions_done.Count > 0) { if (collisions_done.Last.Value.hasSameObjects(collisions[best_i])) { break; } } collisions[best_i].Apply(); collisions_done.AddLast(collisions[best_i]); } return(collisions_done.ToArray <CollisionInformations>()); }
public bool hasSameObjects(CollisionInformations c) { return(hasSameObjects(c.CollidingObj, c.TargetObj)); }