/// <summary> /// Positions a minion (e.g. a ship) using any of the spawn areas in the arena. /// </summary> public static void PositionNewMinion(Gob minion, Arena arena) { Func<IGeomPrimitive, int, IEnumerable<Vector2>> getRandomPoses = (area, count) => Enumerable.Range(0, count) .Select(x => arena.GetFreePosition(LARGE_GOB_PHYSICAL_RADIUS, area)); var spawnPoses = arena.Gobs.All<SpawnPlayer>() .SelectMany(spawn => getRandomPoses(spawn._spawnArea, 5)); var poses = spawnPoses.Any() ? spawnPoses : getRandomPoses(new Rectangle(Vector2.Zero, arena.Dimensions), 20); var posesWithThreats = poses .Select(pos => new { pos, mood = GetMood(minion, pos) }) .ToList() .OrderByDescending(x => x.mood) .ToList(); var bestMood = posesWithThreats[0].mood; var bestSpawns = posesWithThreats.TakeWhile(x => x.mood == bestMood).ToList(); var bestPos = bestSpawns[RandomHelper.GetRandomInt(bestSpawns.Count)].pos; minion.ResetPos(bestPos, Vector2.Zero, Gob.DEFAULT_ROTATION); }
private void GobCreation(Gob gob, int createCount, int i, int emitType, ref List<Particle> particles) { // Find out emission parameters. // We have to loop because some choices of parameters may not be wanted. int maxAttempts = 20; bool attemptOk = false; for (int attempt = 0; !attemptOk && attempt < maxAttempts; ++attempt) { bool lastAttempt = attempt == maxAttempts - 1; attemptOk = true; int random = RandomHelper.GetRandomInt(); float directionAngle, rotation; Vector2 directionUnit, pos, move; switch (Peng.ParticleCoordinates) { case Peng.CoordinateSystem.Peng: RandomHelper.GetRandomCirclePoint(_radius, -_sprayAngle, _sprayAngle, out pos, out directionUnit, out directionAngle); move = _initialVelocity.GetValue(0, random) * directionUnit; switch (_facingType) { case FacingType.Directed: rotation = 0; break; case FacingType.Forward: rotation = directionAngle; break; case FacingType.Random: rotation = RandomHelper.GetRandomFloat(0, MathHelper.TwoPi); break; default: throw new Exception("SprayEmitter: Unhandled particle facing type " + _facingType); } break; case Peng.CoordinateSystem.Game: { float posWeight = (i + 1) / (float)createCount; var startPos = Peng.OldDrawPos; var endPos = Peng.Pos + Peng.DrawPosOffset; var iPos = Vector2.Lerp(startPos, endPos, posWeight); var drawRotation = Peng.Rotation + Peng.DrawRotationOffset; RandomHelper.GetRandomCirclePoint(_radius, drawRotation - _sprayAngle, drawRotation + _sprayAngle, out pos, out directionUnit, out directionAngle); pos += iPos; move = Peng.Move + _initialVelocity.GetValue(0, random) * directionUnit; // HACK: 'move' will be added to 'pos' in PhysicalUpdater during this same frame pos -= move * (float)Peng.Game.GameTime.ElapsedGameTime.TotalSeconds; switch (_facingType) { case FacingType.Directed: rotation = Peng.Rotation; break; case FacingType.Forward: rotation = directionAngle; break; case FacingType.Random: rotation = RandomHelper.GetRandomFloat(0, MathHelper.TwoPi); break; default: throw new Exception("SprayEmitter: Unhandled particle facing type " + _facingType); } } break; case Peng.CoordinateSystem.FixedToPeng: pos = Vector2.Zero; move = Vector2.Zero; rotation = 0; directionAngle = 0; break; default: throw new ApplicationException("SprayEmitter: Unhandled peng coordinate system " + Peng.ParticleCoordinates); } // Set the thing's parameters. if (emitType < TextureNames.Length) { var particle = new Particle { Alpha = 1, Move = move, PengInput = Peng.Input, Pos = pos, Random = random, Direction = directionAngle, DirectionVector = Vector2.UnitX.Rotate(directionAngle), Rotation = rotation, Scale = 1, Texture = Peng.Game.Content.Load<Texture2D>(TextureNames[emitType]), }; particles.Add(particle); } else { // Bail out if the position is not free for the gob. if (!lastAttempt && !Peng.Arena.IsFreePosition(new Circle(pos, Gob.SMALL_GOB_PHYSICAL_RADIUS))) { attemptOk = false; continue; } gob.Owner = Peng.Owner; gob.ResetPos(pos, move, rotation); Peng.Arena.Gobs.Add(gob); } } }