/// <summary> /// Find a valid spawn point in the world. /// </summary> /// <param name="radius">The radius of the object to be spawned.</param> /// <param name="random">A persistent Random object.</param> /// <returns>The spawn point.</returns> public static Vector2 FindSpawnPoint(GameplayObject spawnedObject, float radius) { // safety-check the singleton if (collisionManager == null) { throw new InvalidOperationException( "The collision manager has not yet been initialized."); } // safety-check the parameters if ((radius < 0f) || (radius > Dimensions.Width / 2)) { throw new ArgumentOutOfRangeException("radius"); } // keep trying to find a valid point Vector2 spawnPoint = new Vector2( radius + Dimensions.X + RandomMath.Random.Next((int)Math.Floor(Dimensions.Width - radius)), radius + Dimensions.Y + RandomMath.Random.Next((int)Math.Floor(Dimensions.Height - radius))); for (int i = 0; i < findSpawnPointAttempts; i++) { bool valid = true; // check the barriers if (Barriers != null) { CollisionMath.CircleLineCollisionResult result = new CollisionMath.CircleLineCollisionResult(); foreach (Rectangle rectangle in Barriers) { if (CollisionMath.CircleRectangleCollide(spawnPoint, radius, rectangle, ref result)) { valid = false; break; } } } // check the other objects if (valid) { foreach (GameplayObject gameplayObject in collisionManager) { if (!gameplayObject.Active || (gameplayObject == spawnedObject)) { continue; } if (CollisionMath.CircleCircleIntersect(spawnPoint, radius, gameplayObject.Position, gameplayObject.Radius)) { valid = false; break; } } } if (valid) { break; } spawnPoint = new Vector2( radius + Dimensions.X + RandomMath.Random.Next( (int)Math.Floor(Dimensions.Width - radius)), radius + Dimensions.Y + RandomMath.Random.Next( (int)Math.Floor(Dimensions.Height - radius))); } return(spawnPoint); }
/// <summary> /// Update the collision system. /// </summary> /// <param name="elapsedTime">The amount of elapsed time, in seconds.</param> public static void Update(float elapsedTime) { // safety-check the singleton if (collisionManager == null) { throw new InvalidOperationException( "The collision manager has not yet been initialized."); } // move each object for (int i = 0; i < collisionManager.Count; ++i) { if (collisionManager[i].Active) { // determine how far they are going to move Vector2 movement = collisionManager[i].Velocity * elapsedTime; // only allow collisionManager that have not collided yet // collisionManager frame to collide // -- otherwise, objects can "double-hit" and trade their momentum if (collisionManager[i].CollidedThisFrame == false) { movement = MoveAndCollide(collisionManager[i], movement); } // determine the new position collisionManager[i].Position += movement; // collide with the barriers for (int b = 0; b < collisionManager.barriers.Count; ++b) { CollisionMath.CircleLineCollisionResult result = new CollisionMath.CircleLineCollisionResult(); if (collisionManager[i] is Projectile) { CollisionMath.CircleRectangleCollide( collisionManager[i].Position - movement, collisionManager[i].Radius, collisionManager.barriers[b], ref result); if (result.Collision) { collisionManager[i].Position -= movement; collisionManager[i].Die(null, false); } } else { CollisionMath.CircleRectangleCollide( collisionManager[i].Position, collisionManager[i].Radius, collisionManager.barriers[b], ref result); if (result.Collision) { // if a non-projectile hits a barrier, bounce slightly float vn = Vector2.Dot(collisionManager[i].Velocity, result.Normal); collisionManager[i].Velocity -= (2.0f * vn) * result.Normal; collisionManager[i].Position += result.Normal * result.Distance; } } } } } CollisionManager.Collection.ApplyPendingRemovals(); }