コード例 #1
0
ファイル: EntityFactory.cs プロジェクト: matrix4x4/Space
        /// <summary>Creates a new, AI controlled ship.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="blueprint">The blueprint.</param>
        /// <param name="faction">The faction the ship will belong to.</param>
        /// <param name="position">The position.</param>
        /// <param name="random">The random.</param>
        /// <param name="configuration">The configuration.</param>
        /// <returns>The new ship.</returns>
        public static int CreateAIShip(
            IManager manager,
            string blueprint,
            Factions faction,
            FarPosition position,
            IUniformRandom random,
            ArtificialIntelligence.AIConfiguration configuration = null)
        {
            var entity = FactoryLibrary.SampleShip(manager, blueprint, faction, position, random);

            var input = (ShipControl)manager.GetComponent(entity, ShipControl.TypeId);

            input.Stabilizing = true;
            manager.AddComponent <ArtificialIntelligence>(entity).
            Initialize(random != null ? random.NextUInt32() : 0, configuration).Enabled = false;

            // Add to the index from which entities will automatically removed
            // on cell death and mark it (for translation checks into empty space).
            manager.AddComponent <Indexable>(entity).Initialize(CellSystem.CellDeathAutoRemoveIndexId);
            manager.AddComponent <CellDeath>(entity).Initialize(true);

            // Add to AI index, to allow putting the AI to sleep.
            manager.AddComponent <Indexable>(entity).Initialize(SleepSystem.IndexId);

            return(entity);
        }
コード例 #2
0
ファイル: SunSystemFactory.cs プロジェクト: matrix4x4/Space
            /// <summary>Samples a new orbiter of this type.</summary>
            /// <param name="manager">The manager.</param>
            /// <param name="center">The center.</param>
            /// <param name="dominantAngle">The dominant angle.</param>
            /// <param name="random">The random.</param>
            /// <returns></returns>
            internal void Sample(IManager manager, int center, float dominantAngle, IUniformRandom random)
            {
                if (random != null && ChanceToExist <= random.NextDouble())
                {
                    return;
                }

                var radius       = UnitConversion.ToSimulationUnits(SampleOrbitRadius(random));
                var eccentricity = SampleEccentricity(random);
                var angleOffset  = SampleAngleOffset(random);
                var travelSpeed  = UnitConversion.ToSimulationUnits(SampleTravelSpeed(random));
                var periodOffset = random == null ? 0f : (float)random.NextDouble();

                // Compute minor and major radius.
                float a, b;

                ComputeRadii(radius, eccentricity, out a, out b);

                // Get period. Figure out circumference using Ramanujan's approximation.
                var circumference = MathHelper.Pi * (3 * (a + b) - (float)Math.Sqrt((3 * a + b) * (a + 3 * b)));
                var period        = circumference / travelSpeed * Settings.TicksPerSecond;

                var entity = FactoryLibrary.SamplePlanet(manager, Name, random);

                // Make it move around its center.
                manager.AddComponent <EllipsePath>(entity)
                .Initialize(center, a, b, dominantAngle + angleOffset, period, MathHelper.TwoPi * periodOffset);

                // Recurse.
                if (Moons != null)
                {
                    Moons.Sample(manager, entity, random);
                }
            }
コード例 #3
0
ファイル: SunSystemFactory.cs プロジェクト: matrix4x4/Space
 /// <summary>Samples the angle of this planet's orbit.</summary>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled angle.</returns>
 private float SampleAngle(IUniformRandom random)
 {
     return
         (MathHelper.ToRadians(
              (random == null)
                 ? _angle.Low
                 : MathHelper.Lerp(_angle.Low, _angle.High, (float)random.NextDouble())));
 }
コード例 #4
0
ファイル: SunSystemFactory.cs プロジェクト: matrix4x4/Space
        /// <summary>Samples the attributes to apply to the item.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="cellCenter">The center of the cell for which the sun system is created.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <return>The entity with the attributes applied.</return>
        public void SampleSunSystem(IManager manager, FarPosition cellCenter, IUniformRandom random)
        {
            var sun = FactoryLibrary.SampleSun(manager, _sun, cellCenter, random);

            if (_planets != null)
            {
                _planets.Sample(manager, sun, random);
            }
        }
コード例 #5
0
ファイル: ReactorFactory.cs プロジェクト: matrix4x4/Space
        /// <summary>Samples a new reactor based on these constraints.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <returns>The sampled reactor.</returns>
        public override int Sample(IManager manager, IUniformRandom random)
        {
            var entity = base.Sample(manager, random);

            manager.AddComponent <Reactor>(entity)
            .Initialize(Name, Icon, Quality, RequiredSlotSize, ModelOffset, ModelBelowParent);

            return(entity);
        }
コード例 #6
0
 /// <summary>Samples the mass of this sun.</summary>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled mass.</returns>
 private float SampleMass(IUniformRandom random)
 {
     if (_mass != null)
     {
         return((random == null)
                    ? _mass.Low
                    : MathHelper.Lerp(_mass.Low, _mass.High, (float)random.NextDouble()));
     }
     return(0f);
 }
コード例 #7
0
ファイル: SunSystemFactory.cs プロジェクト: matrix4x4/Space
 /// <summary>Samples the eccentricity of this planet's orbit.</summary>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled major radius.</returns>
 private float SampleEccentricity(IUniformRandom random)
 {
     if (_eccentricity != null)
     {
         return((random == null)
                    ? _eccentricity.Low
                    : MathHelper.Lerp(_eccentricity.Low, _eccentricity.High, (float)random.NextDouble()));
     }
     return(0f);
 }
コード例 #8
0
ファイル: SunSystemFactory.cs プロジェクト: matrix4x4/Space
 /// <summary>Samples the travel speed of this planet.</summary>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled travel speed.</returns>
 private float SampleTravelSpeed(IUniformRandom random)
 {
     if (_travelSpeed != null)
     {
         return((random == null)
                    ? _travelSpeed.Low
                    : MathHelper.Lerp(_travelSpeed.Low, _travelSpeed.High, (float)random.NextDouble()));
     }
     return(0f);
 }
コード例 #9
0
ファイル: UniverseSystem.cs プロジェクト: matrix4x4/Space
        // TODO in case we need this somewhere else it might be a good idea to move this to the EntityFactory
        private void CreateAsteroid(FarPosition position, IUniformRandom random, ContentManager content)
        {
            // Randomly scale and rotate it.
            var scale = (float)random.NextDouble(0.5f, 1f);
            var angle = (float)random.NextDouble() * MathHelper.TwoPi;

            // Determine shape for physics system.
            var textureName = "Textures/Asteroids/rock_" + random.NextInt32(1, 14);
            var texture     = content.Load <Texture2D>(textureName);
            var hull        = new List <Vector2>(TextureConverter.DetectVertices(texture, 8f, textureName: textureName)[0]);

            for (var k = 0; k < hull.Count; ++k)
            {
                hull[k] -= new Vector2(texture.Width / 2f, texture.Height / 2f);
                hull[k]  = XnaUnitConversion.ToSimulationUnits(hull[k]) * scale;
            }
            var polygons = EarClipDecomposer.ConvexPartition(hull);

            // Create physical representation.
            var entity = Manager.AddEntity();
            var body   = Manager.AddBody(entity, position, angle, Body.BodyType.Dynamic);

            foreach (var polygon in polygons)
            {
                Manager.AttachPolygon(body, polygon, density: 1000f, restitution: 0.2f);
            }
            // Slow down to allow reaching sleep state again.
            body.LinearDamping  = 0.05f * Space.Util.Settings.TicksPerSecond;
            body.AngularDamping = 0.025f * Space.Util.Settings.TicksPerSecond;

            // Bounds of the asteroid for rendering culling. We use the diagonal for a loose fit that
            // contains every possible rotated state of the texture.
            var width    = UnitConversion.ToSimulationUnits(texture.Width);
            var height   = UnitConversion.ToSimulationUnits(texture.Height);
            var diagonal = (float)Math.Sqrt(width * width + height * height);
            var bounds   = new FarRectangle(-diagonal / 2, -diagonal / 2, diagonal, diagonal);

            // Rendering stuff.
            Manager.AddComponent <Indexable>(entity).Initialize(bounds, CameraSystem.IndexId);
            Manager.AddComponent <Indexable>(entity).Initialize(bounds, InterpolationSystem.IndexId);
            Manager.AddComponent <SimpleTextureDrawable>(entity).Initialize(textureName, scale);

            // Auto removal.
            Manager.AddComponent <CellDeath>(entity).Initialize(true);
            Manager.AddComponent <Indexable>(entity).Initialize(CellSystem.CellDeathAutoRemoveIndexId);

            // Make it destructible.
            var health = Manager.AddComponent <Health>(entity);

            health.Value        = health.MaxValue = 200 * scale;
            health.Regeneration = 0f;

            // As they don't move on their own, start asteroids as sleeping to save performance.
            body.IsAwake = false;
        }
コード例 #10
0
ファイル: Ziggurat.cs プロジェクト: matrix4x4/Space
        /// <summary>Construct with the provided RNG source.</summary>
        public Ziggurat(IUniformRandom rng)
        {
            _rng = rng;

            // Initialize rectangle position data.
            // _x[i] and _y[i] describe the top-right position ox Box i.

            // Allocate storage. We add one to the length of _x so that we have an entry at _x[_blockCount], this avoids having
            // to do a special case test when sampling from the top box.
            _x = new double[BlockCount + 1];
            _y = new double[BlockCount];

            // Determine top right position of the base rectangle/box (the rectangle with the Gaussian tale attached).
            // We call this Box 0 or B0 for short.
            // Note. x[0] also describes the right-hand edge of B1. (See diagram).
            _x[0] = R;
            _y[0] = GaussianPdfDenorm(R);

            // The next box (B1) has a right hand X edge the same as B0.
            // Note. B1's height is the box area divided by its width, hence B1 has a smaller height than B0 because
            // B0's total area includes the attached distribution tail.
            _x[1] = R;
            _y[1] = _y[0] + (A / _x[1]);

            // Calc positions of all remaining rectangles.
            for (var i = 2; i < BlockCount; i++)
            {
                _x[i] = GaussianPdfDenormInv(_y[i - 1]);
                _y[i] = _y[i - 1] + (A / _x[i]);
            }

            // For completeness we define the right-hand edge of a notional box 6 as being zero (a box with no area).
            _x[BlockCount] = 0.0;

            // Useful precomputed values.
            _aDivY0 = A / _y[0];
            _xComp  = new uint[BlockCount];

            // Special case for base box. _xComp[0] stores the area of B0 as a proportion of __R
            // (recalling that all segments have area __A, but that the base segment is the combination of B0 and the distribution tail).
            // Thus -xComp[0[ is the probability that a sample point is within the box part of the segment.
            _xComp[0] = (uint)(((R * _y[0]) / A) * uint.MaxValue);

            for (var i = 1; i < BlockCount - 1; i++)
            {
                _xComp[i] = (uint)((_x[i + 1] / _x[i]) * uint.MaxValue);
            }
            _xComp[BlockCount - 1] = 0; // Shown for completeness.

            // Sanity check. Test that the top edge of the topmost rectangle is at y=1.0.
            // Note. We expect there to be a tiny drift away from 1.0 due to the inexactness of floating
            // point arithmetic.
            Debug.Assert(System.Math.Abs(1.0 - _y[BlockCount - 1]) < 1e-10);
        }
コード例 #11
0
 /// <summary>Samples the rotation speed of this planet.</summary>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled rotation speed.</returns>
 private float SampleRotationSpeed(IUniformRandom random)
 {
     if (_rotationSpeed != null)
     {
         return(MathHelper.ToRadians(
                    (random == null)
                 ? _rotationSpeed.Low
                 : MathHelper.Lerp(_rotationSpeed.Low, _rotationSpeed.High, (float)random.NextDouble())));
     }
     return(0f);
 }
コード例 #12
0
ファイル: FactoryLibrary.cs プロジェクト: matrix4x4/Space
        /// <summary>Samples a new ship with the specified name.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="name">The logical name of the ship to sample.</param>
        /// <param name="faction">The faction the ship will belong to.</param>
        /// <param name="position">The initial position of the ship.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <returns>The sampled ship.</returns>
        public static int SampleShip(
            IManager manager, string name, Factions faction, FarPosition position, IUniformRandom random)
        {
            if (string.IsNullOrWhiteSpace(name) || !Factories.ContainsKey(name))
            {
                return(0);
            }
            var factory = Factories[name] as ShipFactory;

            return(factory != null?factory.Sample(manager, faction, position, random) : 0);
        }
コード例 #13
0
ファイル: SunSystemFactory.cs プロジェクト: matrix4x4/Space
            internal void Sample(IManager manager, int center, IUniformRandom random)
            {
                // Get the dominant angle.
                var dominantAngle = SampleAngle(random);

                // Create orbiters.
                foreach (var orbiter in _orbiters)
                {
                    orbiter.Sample(manager, center, dominantAngle, random);
                }
            }
コード例 #14
0
ファイル: ListExtensions.cs プロジェクト: matrix4x4/Space
 /// <summary>
 ///     Shuffles the specified list using the Fisher-Yates shuffle. This only shuffles a segment in a list, as opposed
 ///     to shuffling the complete list.
 /// </summary>
 /// <typeparam name="T">The type of element stored in the list.</typeparam>
 /// <param name="list">The list to shuffle.</param>
 /// <param name="offset">The offset at which to start shuffling.</param>
 /// <param name="length">The length of the interval to shuffle.</param>
 /// <param name="random">The random number generator to use for shuffling. If none is specified, a new one will be created.</param>
 public static void Shuffle <T>(this IList <T> list, int offset, int length, IUniformRandom random = null)
 {
     random = random ?? new MersenneTwister();
     for (var i = offset + length - 1; i > offset; --i)
     {
         var j = random.NextInt32(i + 1);
         var t = list[j];
         list[j] = list[i];
         list[i] = t;
     }
 }
コード例 #15
0
        /// <summary>Samples a new weapon based on these constraints.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <returns>The sampled weapon.</returns>
        public override int Sample(IManager manager, IUniformRandom random)
        {
            var entity = base.Sample(manager, random);

            // Get baked list of attributes.
            Dictionary <AttributeType, float> attributes = null;

            // Iterate over all local attribute modifiers and accumulate the
            // additive base value, store the multiplicative values in an
            // extra list to apply them at the end.
            Dictionary <AttributeType, float> multipliers = null;

            if (_guaranteedLocalAttributes != null)
            {
                foreach (var attribute in _guaranteedLocalAttributes)
                {
                    AccumulateModifier(attribute.SampleAttributeModifier(random), ref attributes, ref multipliers);
                }
            }
            if (_additionalLocalAttributes != null && _additionalLocalAttributes.Length > 0)
            {
                foreach (
                    var attributeModifier in
                    SampleAttributes(SampleLocalAttributeCount(random), random))
                {
                    AccumulateModifier(attributeModifier, ref attributes, ref multipliers);
                }
            }

            // Done checking all local attributes, apply multipliers, if any.
            if (multipliers != null)
            {
                foreach (var multiplier in multipliers)
                {
                    if (attributes != null && attributes.ContainsKey(multiplier.Key))
                    {
                        attributes[multiplier.Key] *= multiplier.Value;
                    }
                    else
                    {
                        Logger.Warn(
                            "Invalid local attribute for weapon {0}: {1} does not have an additive base value.",
                            Name,
                            multiplier.Key);
                    }
                }
            }

            manager.AddComponent <Weapon>(entity)
            .Initialize(_sound, attributes, _projectiles)
            .Initialize(Name, Icon, Quality, RequiredSlotSize, ModelOffset, ModelBelowParent);

            return(entity);
        }
コード例 #16
0
        /// <summary>Samples the attributes to apply to the item.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <return>The entity with the attributes applied.</return>
        public int Sample(IManager manager, IUniformRandom random)
        {
            var entity = manager.AddEntity();

            // Sample all values in advance, to allow reshuffling component creation
            // order in case we need to, without influencing the 'random' results.
            var radius        = UnitConversion.ToSimulationUnits(SampleRadius(random));
            var rotationSpeed = SampleRotationSpeed(random);
            var mass          = SampleMass(random);

            var surfaceRotation = random != null
                                      ? (Math.Sign(random.NextDouble() - 0.5) * rotationSpeed)
                                      : rotationSpeed;

            // Give it a position.
            manager.AddComponent <Transform>(entity);

            // Add it to some indexes.
            var bounds = new FarRectangle(-radius, -radius, radius * 2, radius * 2);

            // Can be detected.
            manager.AddComponent <Indexable>(entity).Initialize(bounds, Detectable.IndexId);
            // Can make some noise.
            manager.AddComponent <Indexable>(entity).Initialize(SoundSystem.IndexId);
            // Must be detectable by the camera.
            manager.AddComponent <Indexable>(entity).Initialize(bounds, CameraSystem.IndexId);

            // Remove when out of bounds or large containing cell dies.
            manager.AddComponent <Indexable>(entity).Initialize(CellSystem.CellDeathAutoRemoveIndexId);
            manager.AddComponent <CellDeath>(entity).Initialize(false);

            // Make it rotate.
            manager.AddComponent <Velocity>(entity).Initialize(
                Vector2.Zero,
                MathHelper.ToRadians(rotationSpeed) / Settings.TicksPerSecond);

            // Make it attract stuff if it has mass.
            if (mass > 0)
            {
                manager.AddComponent <Gravitation>(entity).Initialize(Gravitation.GravitationTypes.Attractor, mass);
            }

            // Make it detectable.
            manager.AddComponent <Detectable>(entity).Initialize("Textures/Radar/Icons/radar_planet");

            // Make it visible.
            manager.AddComponent <PlanetRenderer>(entity).Initialize(this, UnitConversion.ToScreenUnits(radius), surfaceRotation);

            // Let it rap.
            manager.AddComponent <Sound>(entity).Initialize("Planet");

            return(entity);
        }
コード例 #17
0
        public static RectangleF NextRectangle(this IUniformRandom random, float area, float minSize, float maxSize)
        {
            var rect = new RectangleF
            {
                Width  = (float)random.NextDouble(minSize, maxSize),
                Height = (float)random.NextDouble(minSize, maxSize)
            };

            rect.X = (float)random.NextDouble(-area / 2, area / 2 - rect.Width);
            rect.Y = (float)random.NextDouble(-area / 2, area / 2 - rect.Height);
            return(rect);
        }
コード例 #18
0
        /// <summary>Samples an attribute modifier from this constraint.</summary>
        /// <param name="random">The randomizer to use.</param>
        /// <returns>The sampled attribute modifier.</returns>
        public AttributeModifier <TAttribute> SampleAttributeModifier(IUniformRandom random)
        {
            // Only randomize if necessary.
            var value = (random == null)
                            ? _value.Low
                            : MathHelper.Lerp(_value.Low, _value.High, (float)random.NextDouble());

            if (_round)
            {
                value = (float)System.Math.Round(value);
            }
            return(new AttributeModifier <TAttribute>(_type, value, _computationType));
        }
コード例 #19
0
 /// <summary>Samples the offset of this sun.</summary>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled offset.</returns>
 private Vector2 SampleOffset(IUniformRandom random)
 {
     if (_offsetRadius != null && random != null)
     {
         Vector2 offset;
         offset.X = (float)(random.NextDouble() - 0.5);
         offset.Y = (float)(random.NextDouble() - 0.5);
         offset.Normalize();
         offset *= MathHelper.Lerp(_offsetRadius.Low, _offsetRadius.High, (float)random.NextDouble());
         return(offset);
     }
     return(Vector2.Zero);
 }
コード例 #20
0
ファイル: FactoryLibrary.cs プロジェクト: matrix4x4/Space
        /// <summary>Samples a new item with the specified name.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="name">The logical name of the item to sample.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <returns>The sampled item.</returns>
        public static int SampleItem(IManager manager, string name, IUniformRandom random)
        {
            if (string.IsNullOrWhiteSpace(name) || !Factories.ContainsKey(name))
            {
                return(0);
            }
            var factory = Factories[name] as ItemFactory;

            if (factory != null)
            {
                return(factory.Sample(manager, random));
            }
            return(0);
        }
コード例 #21
0
        /// <summary>Samples the attributes to apply to the item.</summary>
        /// <param name="manager"> </param>
        /// <param name="faction">The faction the ship belongs to.</param>
        /// <param name="position">The position at which to spawn the ship.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <return>The entity with the attributes applied.</return>
        public int Sample(IManager manager, Factions faction, FarPosition position, IUniformRandom random)
        {
            var entity = CreateShip(manager, faction, position);

            // Create initial equipment.
            var equipment = (ItemSlot)manager.GetComponent(entity, ItemSlot.TypeId);

            equipment.Item = FactoryLibrary.SampleItem(manager, _items.Name, position, random);
            if (equipment.Item > 0)
            {
                foreach (var item in _items.Slots)
                {
                    SampleItems(manager, position, random, equipment.Item, item);
                }
            }

            // Add our attributes.
            var attributes = (Attributes <AttributeType>)manager.GetComponent(entity, Attributes <AttributeType> .TypeId);

            foreach (var attribute in _attributes)
            {
                var modifier = attribute.SampleAttributeModifier(random);
                if (modifier.ComputationType == AttributeComputationType.Multiplicative)
                {
                    throw new InvalidOperationException("Base attributes must be additive.");
                }
                attributes.SetBaseValue(modifier.Type, modifier.Value);
            }

            // Fill up our values.
            var health = ((Health)manager.GetComponent(entity, Health.TypeId));
            var energy = ((Energy)manager.GetComponent(entity, Energy.TypeId));

            health.Value = health.MaxValue;
            energy.Value = energy.MaxValue;

            // Add experience points if we're worth any.
            if (_xp > 0)
            {
                manager.AddComponent <ExperiencePoints>(entity).Initialize(_xp);
            }

            return(entity);
        }
コード例 #22
0
ファイル: ProjectileFactory.cs プロジェクト: matrix4x4/Space
 /// <summary>Samples the initial directed velocity.</summary>
 /// <param name="baseRotation">The base rotation.</param>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled velocity.</returns>
 public Vector2 SampleInitialDirectedVelocity(float baseRotation, IUniformRandom random)
 {
     if (_initialDirection != null && _initialVelocity != null)
     {
         var velocity = Vector2.UnitX;
         var rotation =
             Matrix.CreateRotationZ(
                 baseRotation +
                 MathHelper.ToRadians(
                     MathHelper.Lerp(
                         _initialDirection.Low,
                         _initialDirection.High,
                         (random == null) ? 0 : (float)random.NextDouble())));
         Vector2.Transform(ref velocity, ref rotation, out velocity);
         velocity.Normalize();
         return(velocity *
                ((random == null)
                     ? _initialVelocity.Low
                     : MathHelper.Lerp(_initialVelocity.Low, _initialVelocity.High, (float)random.NextDouble())));
     }
     return(Vector2.Zero);
 }
コード例 #23
0
ファイル: ProjectileFactory.cs プロジェクト: matrix4x4/Space
 /// <summary>Samples the acceleration force.</summary>
 /// <param name="baseRotation">The base rotation.</param>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled acceleration force.</returns>
 public Vector2 SampleAccelerationForce(float baseRotation, IUniformRandom random)
 {
     if (_accelerationDirection != null && _accelerationForce != null)
     {
         var acceleration = Vector2.UnitX;
         var rotation     =
             Matrix.CreateRotationZ(
                 baseRotation +
                 MathHelper.ToRadians(
                     MathHelper.Lerp(
                         _accelerationDirection.Low,
                         _accelerationDirection.High,
                         (random == null) ? 0 : (float)random.NextDouble())));
         Vector2.Transform(ref acceleration, ref rotation, out acceleration);
         acceleration.Normalize();
         return(acceleration *
                ((random == null)
                     ? _accelerationForce.Low
                     : MathHelper.Lerp(
                     _accelerationForce.Low, _accelerationForce.High, (float)random.NextDouble())));
     }
     return(Vector2.Zero);
 }
コード例 #24
0
        /// <summary>Samples the items for the specified item info and children (recursively).</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="position">The position.</param>
        /// <param name="random">The random.</param>
        /// <param name="parent">The parent.</param>
        /// <param name="itemInfo">The item info.</param>
        private static void SampleItems(
            IManager manager, FarPosition position, IUniformRandom random, int parent, ItemInfo itemInfo)
        {
            // Create the actual item.
            var itemId = FactoryLibrary.SampleItem(manager, itemInfo.Name, position, random);

            if (itemId < 1)
            {
                // No such item.
                return;
            }
            var item = (Item)manager.GetComponent(itemId, Item.TypeId);

            // Then equip it in the parent.
            foreach (ItemSlot slot in manager.GetComponents(parent, ItemSlot.TypeId))
            {
                if (slot.Item == 0 && slot.Validate(item))
                {
                    // Found a suitable empty slot, equip here.
                    slot.Item = itemId;

                    // Recurse to generate children.
                    foreach (var childInfo in itemInfo.Slots)
                    {
                        SampleItems(manager, position, random, itemId, childInfo);
                    }

                    // Done.
                    return;
                }
            }

            // If we get here we couldn't find a slot to equip the item in.
            manager.RemoveEntity(itemId);

            Logger.Warn("Parent item did not have a slot for the requested child item.");
        }
コード例 #25
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="Behavior"/> class.
 /// </summary>
 /// <param name="ai">The AI component.</param>
 /// <param name="random">The randomizer to use for decision making.</param>
 /// <param name="pollRate">The poll rate in seconds.</param>
 protected Behavior(ArtificialIntelligence ai, IUniformRandom random, float pollRate)
 {
     AI        = ai;
     Random    = random;
     _pollRate = (int)(pollRate * Settings.TicksPerSecond);
 }
コード例 #26
0
ファイル: ListExtensions.cs プロジェクト: matrix4x4/Space
 /// <summary>Shuffles the specified list using the Fisher-Yates shuffle.</summary>
 /// <typeparam name="T">The type of element stored in the list.</typeparam>
 /// <param name="list">The list to shuffle.</param>
 /// <param name="random">The random number generator to use for shuffling. If none is specified, a new one will be created.</param>
 public static void Shuffle <T>(this IList <T> list, IUniformRandom random = null)
 {
     list.Shuffle(0, list.Count, random);
 }
コード例 #27
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="RoamBehavior"/> class.
 /// </summary>
 /// <param name="ai">The ai component this behavior belongs to.</param>
 /// <param name="random">The randomizer to use for decision making.</param>
 public RoamBehavior(ArtificialIntelligence ai, IUniformRandom random)
     : base(ai, random, 0)
 {
 }
コード例 #28
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="MoveBehavior"/> class.
 /// </summary>
 /// <param name="ai">The ai component this behavior belongs to.</param>
 /// <param name="random">The randomizer to use for decision making.</param>
 public MoveBehavior(ArtificialIntelligence ai, IUniformRandom random)
     : base(ai, random, 1)
 {
 }
コード例 #29
0
ファイル: ProjectileFactory.cs プロジェクト: matrix4x4/Space
        /// <summary>Samples a new projectile.</summary>
        /// <param name="manager">The manager.</param>
        /// <param name="emitter">The emitter that the projectile comes from.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="angle">The angle.</param>
        /// <param name="weapon">The weapon.</param>
        /// <param name="faction">The faction the projectile belongs to.</param>
        /// <param name="random">The randomizer to use.</param>
        /// <returns>A new projectile.</returns>
        public int SampleProjectile(
            IManager manager,
            int emitter,
            Vector2 offset,
            float angle,
            Weapon weapon,
            Factions faction,
            IUniformRandom random)
        {
            var entity = manager.AddEntity();

            // Get position and velocity of the emitter, to set initial position
            // and additional velocity.
            var emitterTransform = (ITransform)manager.GetComponent(emitter, TransformTypeId);
            var emitterVelocity  = (IVelocity)manager.GetComponent(emitter, VelocityTypeId);

            // Rotate the offset.
            var emitterAngle = emitterTransform.Angle;
            var cosRadians   = (float)Math.Cos(emitterAngle);
            var sinRadians   = (float)Math.Sin(emitterAngle);

            FarPosition rotatedOffset;

            rotatedOffset.X = -offset.X * cosRadians - offset.Y * sinRadians;
            rotatedOffset.Y = -offset.X * sinRadians + offset.Y * cosRadians;

            // Set initial velocity.
            var velocity          = SampleInitialDirectedVelocity(emitterAngle + angle, random);
            var accelerationForce = SampleAccelerationForce(emitterAngle + angle, random);

            // Adjust rotation for projectile based on its own acceleration or speed.
            var emitAngle = emitterAngle;

            if (accelerationForce != Vector2.Zero)
            {
                emitAngle = (float)Math.Atan2(accelerationForce.Y, accelerationForce.X);
            }
            else if (velocity != Vector2.Zero)
            {
                emitAngle = (float)Math.Atan2(velocity.Y, velocity.X);
            }

            // See what we must not bump into.
            var collisionMask = ~faction.ToCollisionGroup();

            // Normally projectiles won't test against each other, but some may be
            // shot down, such as missiles. If that's the case, don't add us to the
            // common projectile group.
            if (!_canBeShot)
            {
                collisionMask &= ~Factions.Projectiles.ToCollisionGroup();
            }

            // Create physical body.
            var body = manager.AddBody(
                entity,
                emitterTransform.Position + rotatedOffset + velocity / Settings.TicksPerSecond,
                emitAngle,
                Body.BodyType.Dynamic,
                isBullet: true,
                allowSleep: false);

            manager.AttachCircle(
                body,
                UnitConversion.ToSimulationUnits(_collisionRadius),
                0,
                restitution: 0.1f,
                collisionCategory: faction.ToCollisionGroup() | Factions.Projectiles.ToCollisionGroup(),
                collisionMask: collisionMask);

            // Add to render system indexes. The padding these perform should be enough for any projectile.
            manager.AddComponent <Indexable>(entity).Initialize(CameraSystem.IndexId);
            manager.AddComponent <Indexable>(entity).Initialize(InterpolationSystem.IndexId);

            // If our emitter was moving, apply its velocity.
            if (emitterVelocity != null)
            {
                velocity += emitterVelocity.LinearVelocity;
            }

            // Then set the initial velocity of our bullet.
            body.LinearVelocity = velocity;

            // Sample an acceleration for this projectile. If there is any, create the
            // component for it, otherwise disregard.
            if (accelerationForce != Vector2.Zero)
            {
                // TODO add motor joint? else teach acceleration system to use ApplyForce
//                manager.AddComponent<Acceleration>(entity).Initialize(accelerationForce);
            }

            // Apply friction to this projectile if so desired.
            if (_friction > 0)
            {
                body.LinearDamping = 1f - _friction;
            }

            // If this projectile should vanish after some time, make it expire.
            if (_timeToLive > 0)
            {
                manager.AddComponent <Expiration>(entity).Initialize((int)(_timeToLive * Settings.TicksPerSecond));
            }

            // Mark as applying damage on collision.
            manager.AddComponent <CollisionDamage>(entity).Initialize(true);

            // Apply attributes of the weapon, modified with emitter attribute values,
            // and emitter attributes to the projectile to allow damage calculation if
            // it hits something.
            var emitterAttributes =
                (Attributes <AttributeType>)manager.GetComponent(emitter, Attributes <AttributeType> .TypeId);
            Attributes <AttributeType> projectileAttributes = null; // Only create if necessary.

            foreach (AttributeType attributeType in Enum.GetValues(typeof(AttributeType)))
            {
                if (attributeType == AttributeType.None)
                {
                    continue;
                }
                // Try to get weapon local attribute as base values.
                var value = 0f;
                if (weapon.Attributes.ContainsKey(attributeType))
                {
                    value = weapon.Attributes[attributeType];
                }
                // Try to modify it with emitter attributes.
                if (emitterAttributes != null)
                {
                    value = emitterAttributes.GetValue(attributeType, value);
                }
                // If we have something, copy it to the projectile.
// ReSharper disable CompareOfFloatsByEqualityOperator
                if (value != 0f)
// ReSharper restore CompareOfFloatsByEqualityOperator
                {
                    if (projectileAttributes == null)
                    {
                        projectileAttributes = manager.AddComponent <Attributes <AttributeType> >(entity);
                    }
                    projectileAttributes.SetBaseValue(attributeType, value);
                }
            }

            // Make us visible!
            if (!string.IsNullOrWhiteSpace(_model))
            {
                manager.AddComponent <SimpleTextureDrawable>(entity).Initialize(_model);
            }

            // And add some particle effects, if so desired.
            if (!string.IsNullOrWhiteSpace(_effect))
            {
                manager.AddComponent <ParticleEffects>(entity)
                .TryAdd(0, _effect, 1f, 0, _effectOffset, ParticleEffects.EffectGroup.None, true);
            }

            // Assign owner, to track original cause when they do something (e.g. kill something).
            manager.AddComponent <Owner>(entity).Initialize(emitter);

            return(entity);
        }
コード例 #30
0
ファイル: SunSystemFactory.cs プロジェクト: matrix4x4/Space
 /// <summary>Samples the angle of this planet's orbit.</summary>
 /// <param name="random">The randomizer to use.</param>
 /// <returns>The sampled angle.</returns>
 private float SampleOrbitRadius(IUniformRandom random)
 {
     return((random == null)
                ? _orbitRadius.Low
                : MathHelper.Lerp(_orbitRadius.Low, _orbitRadius.High, (float)random.NextDouble()));
 }