/// <summary> /// Move all of the actors in the world. /// </summary> /// <param name="elapsedTime">The amount of elapsed time, in seconds.</param> private void MoveWorld(float elapsedTime) { Vector2 point = Vector2.Zero; // move each actor for (int i = 0; i < actors.Count; ++i) { if (actors[i].Dead) { continue; } // determine how far they are going to move Vector2 movement = actors[i].Velocity * elapsedTime; // only allow actors that have not collided yet this frame to collide // -- otherwise, objects can "double-hit" and trade their momentum fast if (actors[i].CollidedThisFrame == false) { movement = MoveAndCollide(actors[i], movement); } // determine the new position actors[i].Position += movement; // determine if their new position taks them through a wall for (int w = 0; w < walls.Length / 2; ++w) { if (actors[i] is Projectile) { if (Collision.LineLineIntersect(actors[i].Position, actors[i].Position - movement, walls[w * 2], walls[w * 2 + 1], out point)) { actors[i].Touch(actors[0]); } } else { Collision.CircleLineCollisionResult result = new Collision.CircleLineCollisionResult(); if (Collision.CircleLineCollide(actors[i].Position, actors[i].Radius, walls[w * 2], walls[w * 2 + 1], ref result)) { // if a non-projectile hits a wall, bounce slightly float vn = Vector2.Dot(actors[i].Velocity, result.Normal); actors[i].Velocity -= (2.0f * vn) * result.Normal; actors[i].Position += result.Normal * result.Distance; } } } } }
/// <summary> /// Move all of the actors in the world. /// </summary> /// <param name="elapsedTime">The amount of elapsed time, in seconds.</param> private void MoveWorld(float elapsedTime) { Vector2 point = Vector2.Zero; // move each actor for (int i = 0; i < actors.Count; ++i) { if (actors[i].Dead) { continue; } // determine how far they are going to move Vector2 movement = actors[i].Velocity * elapsedTime; // only allow actors that have not collided yet this frame to collide // -- otherwise, objects can "double-hit" and trade their momentum fast if (actors[i].CollidedThisFrame == false) { movement = MoveAndCollide(actors[i], movement); } // determine the new position actors[i].Position += movement; // determine if their new position taks them through a wall for (int w = 0; w < walls.Length / 2; ++w) { if (actors[i] is Projectile) { if (Collision.LineLineIntersect(actors[i].Position, actors[i].Position - movement, walls[w * 2], walls[w * 2 + 1], out point)) { actors[i].Touch(actors[0]); } } else { Collision.CircleLineCollisionResult result = new Collision.CircleLineCollisionResult(); if (Collision.CircleLineCollide(actors[i].Position, actors[i].Radius, walls[w * 2], walls[w * 2 + 1], ref result)) { // if a non-projectile hits a wall, bounce slightly float vn = Vector2.Dot(actors[i].Velocity, result.Normal); actors[i].Velocity -= (2.0f * vn) * result.Normal; actors[i].Position += result.Normal * result.Distance; } } } } }
/// <summary> /// Find a valid point for the actor to spawn. /// </summary> /// <param name="actor">The actor to find a location for.</param> /// <remarks>This query is not bounded, which would be needed in a more complex /// game with a likelihood of no valid spawn locations.</remarks> /// <returns>A valid location for the user to spawn.</returns> public Vector2 FindSpawnPoint(Actor actor) { if (actor == null) { throw new ArgumentNullException("actor"); } Vector2 spawnPoint; float radius = actor.Radius; // fudge the radius slightly so we're not right on top of another actor if (actor is Ship) { radius *= 2f; } else { radius *= 1.1f; } radius = (float)Math.Ceiling(radius); Vector2 spawnMinimum = new Vector2( safeDimensions.X + radius, safeDimensions.Y + radius); Vector2 spawnDimensions = new Vector2( (float)Math.Floor(safeDimensions.Width - 2f * radius), (float)Math.Floor(safeDimensions.Height - 2f * radius)); Vector2 spawnMaximum = spawnMinimum + spawnDimensions; Collision.CircleLineCollisionResult result = new Collision.CircleLineCollisionResult(); bool valid = true; while (true) { valid = true; // generate a new spawn point spawnPoint = new Vector2( spawnMinimum.X + spawnDimensions.X * (float)random.NextDouble(), spawnMinimum.Y + spawnDimensions.Y * (float)random.NextDouble()); if ((spawnPoint.X < spawnMinimum.X) || (spawnPoint.Y < spawnMinimum.Y) || (spawnPoint.X > spawnMaximum.X) || (spawnPoint.Y > spawnMaximum.Y)) { continue; } // if we don't collide, then one is good enough if (actor.Collidable == false) { break; } // check against the walls if (valid == true) { for (int wall = 0; wall < walls.Length / 2; wall++) { if (Collision.CircleLineCollide(spawnPoint, radius, walls[wall * 2], walls[wall * 2 + 1], ref result)) { valid = false; break; } } } // check against all other actors if (valid == true) { foreach (Actor checkActor in actors) { if ((actor == checkActor) || checkActor.Dead) { continue; } if (Collision.CircleCircleIntersect(checkActor.Position, checkActor.Radius, spawnPoint, radius)) { valid = false; break; } } } // if we have gotten this far, then the spawn point is good if (valid == true) { break; } } return spawnPoint; }
/// <summary> /// Find a valid point for the actor to spawn. /// </summary> /// <param name="actor">The actor to find a location for.</param> /// <remarks>This query is not bounded, which would be needed in a more complex /// game with a likelihood of no valid spawn locations.</remarks> /// <returns>A valid location for the user to spawn.</returns> public Vector2 FindSpawnPoint(Actor actor) { if (actor == null) { throw new ArgumentNullException("actor"); } Vector2 spawnPoint; float radius = actor.Radius; // fudge the radius slightly so we're not right on top of another actor if (actor is Ship) { radius *= 2f; } else { radius *= 1.1f; } radius = (float)Math.Ceiling(radius); Vector2 spawnMinimum = new Vector2( safeDimensions.X + radius, safeDimensions.Y + radius); Vector2 spawnDimensions = new Vector2( (float)Math.Floor(safeDimensions.Width - 2f * radius), (float)Math.Floor(safeDimensions.Height - 2f * radius)); Vector2 spawnMaximum = spawnMinimum + spawnDimensions; Collision.CircleLineCollisionResult result = new Collision.CircleLineCollisionResult(); bool valid = true; while (true) { valid = true; // generate a new spawn point spawnPoint = new Vector2( spawnMinimum.X + spawnDimensions.X * (float)random.NextDouble(), spawnMinimum.Y + spawnDimensions.Y * (float)random.NextDouble()); if ((spawnPoint.X < spawnMinimum.X) || (spawnPoint.Y < spawnMinimum.Y) || (spawnPoint.X > spawnMaximum.X) || (spawnPoint.Y > spawnMaximum.Y)) { continue; } // if we don't collide, then one is good enough if (actor.Collidable == false) { break; } // check against the walls if (valid == true) { for (int wall = 0; wall < walls.Length / 2; wall++) { if (Collision.CircleLineCollide(spawnPoint, radius, walls[wall * 2], walls[wall * 2 + 1], ref result)) { valid = false; break; } } } // check against all other actors if (valid == true) { foreach (Actor checkActor in actors) { if ((actor == checkActor) || checkActor.Dead) { continue; } if (Collision.CircleCircleIntersect(checkActor.Position, checkActor.Radius, spawnPoint, radius)) { valid = false; break; } } } // if we have gotten this far, then the spawn point is good if (valid == true) { break; } } return(spawnPoint); }