public void OnDraw(Draw message) { if (!Enabled) { return; } var camera = (CameraSystem)Manager.GetSystem(CameraSystem.TypeId); // Get camera transform. var cameraTransform = camera.Transform; var cameraTranslation = camera.Translation; var interpolation = (InterpolationSystem)Manager.GetSystem(InterpolationSystem.TypeId); // Iterate over all visible entities. _spriteBatch.Begin( SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, cameraTransform); foreach (var entity in camera.VisibleEntities) { var transform = (ITransform)Manager.GetComponent(entity, TransformTypeId); if (transform != null) { int x, y, subX, subY; BitwiseMagic.Unpack(CellSystem.GetCellIdFromCoordinates(transform.Position), out x, out y); BitwiseMagic.Unpack(CellSystem.GetSubCellIdFromCoordinates(transform.Position), out subX, out subY); var text = string.Format( "ID: {0} @ {1} / {2}\nCell: {3}:{4}, SubCell: {5}:{6}", transform.Entity, transform.Position, transform.Angle, x, y, subX, subY); FarPosition position; float angle; interpolation.GetInterpolatedTransform(transform.Entity, out position, out angle); position = FarUnitConversion.ToScreenUnits(position + cameraTranslation); _spriteBatch.DrawString( _font, text, (Vector2)position, Color.White, 0, Vector2.Zero, 1f / camera.CameraZoom, SpriteEffects.None, 1); } } _spriteBatch.End(); }
public override void OnUpdate(Update message) { // See if we have some pending spawns. if (_cellSpawns.Count > 0) { // Prefer cells with players in them. var avatars = (AvatarSystem)Manager.GetSystem(AvatarSystem.TypeId); var index = -1; foreach (var avatar in avatars.Avatars) { var avatarPosition = ((ITransform)Manager.GetComponent(avatar, TransformTypeId)).Position; var avatarCell = CellSystem.GetCellIdFromCoordinates(avatarPosition); index = _cellSpawns.FindIndex(x => x.Item1 == avatarCell); if (index >= 0) { break; } } // Fall back to using the first cell, if there's no player in any. if (index < 0) { index = _cellSpawns.Count - 1; } // Pop the entry (tuples are immutable). var spawn = _cellSpawns[index]; _cellSpawns.RemoveAt(index); // Should be removed in message handling if cell dies. System.Diagnostics.Debug.Assert( ((CellSystem)Manager.GetSystem(CellSystem.TypeId)).IsSubCellActive(spawn.Item1)); // Spawn some ships. ProcessSpawn(spawn.Item1); // If there's stuff left to do push it back again. if (spawn.Item2 > 1) { _cellSpawns.Add(Tuple.Create(spawn.Item1, spawn.Item2 - 1)); } } base.OnUpdate(message); }
/// <summary>Processes a single spawn from the top of the spawn queue.</summary> private void ProcessSpawn(ulong id) { // Get the cell position. var position = CellSystem.GetSubCellCoordinatesFromId(id); // Get the cell info to know what faction we're spawning for. Use the large cell id for that, // because we only store info for that. var cellInfo = ((UniverseSystem)Manager.GetSystem(UniverseSystem.TypeId)) .GetCellInfo(CellSystem.GetCellIdFromCoordinates(position)); // The area covered by the cell. FarRectangle cellArea; cellArea.X = position.X; cellArea.Y = position.Y; cellArea.Width = CellSystem.SubCellSize; cellArea.Height = CellSystem.SubCellSize; // Get center point for spawn group. FarPosition spawnPoint; spawnPoint.X = _random.NextInt32((int)cellArea.Left, (int)cellArea.Right); spawnPoint.Y = _random.NextInt32((int)cellArea.Top, (int)cellArea.Bottom); // Configuration for spawned ships. string[] ships; ArtificialIntelligence.AIConfiguration[] configurations = null; var formation = SquadSystem.Formations.None; // TODO different groups, based on cell info? definable via editor maybe? if (_random.NextDouble() < 0.5f) { ships = new[] { "L1_AI_Ship", "L1_AI_Ship", "L1_AI_Ship", "L1_AI_Ship", "L1_AI_Ship", "L1_AI_Ship" }; configurations = new[] { new ArtificialIntelligence.AIConfiguration { AggroRange = UnitConversion.ToSimulationUnits(600) } }; formation = SquadSystem.Formations.Block; } else { ships = new[] { "L1_AI_Ship", "L1_AI_Ship", "L1_AI_Ship", "L1_AI_Ship", "L1_AI_Ship" }; configurations = new[] { new ArtificialIntelligence.AIConfiguration { AggroRange = UnitConversion.ToSimulationUnits(800) } }; formation = SquadSystem.Formations.Vee; } // Spawn all ships. Squad leaderSquad = null; for (var i = 0; i < ships.Length; i++) { // Get the configuration for this particular ship. If we don't have enough configurations // we just re-use the last existing one. var configuration = configurations != null && configurations.Length > 0 ? configurations[Math.Min(i, configurations.Length - 1)] : null; // Get a position nearby the spawn (avoids spawning all ships in one point). var spawnPosition = spawnPoint; spawnPosition.X += UnitConversion.ToSimulationUnits(_random.NextInt32(-100, 100)); spawnPosition.Y += UnitConversion.ToSimulationUnits(_random.NextInt32(-100, 100)); // Create the ship and get the AI component. var ship = EntityFactory.CreateAIShip( Manager, ships[i], cellInfo.Faction, spawnPosition, _random, configuration); var ai = (ArtificialIntelligence)Manager.GetComponent(ship, ArtificialIntelligence.TypeId); // Push fallback roam behavior, if an area has been specified. ai.Roam(ref cellArea); // If we have a squad push the squad component. if (ships.Length <= 1) { // No squad, skip squad component. continue; } var squad = Manager.AddComponent <Squad>(ship); // If we're not the leader we guard him, otherwise mark us as // the squad leader (ergo: first loop iteration). if (leaderSquad != null) { leaderSquad.AddMember(ship); ai.Guard(leaderSquad.Entity); } else { leaderSquad = squad; squad.Formation = formation; } } }