Esempio n. 1
0
        public void Behavior_Initialization_Method_Called_When_Trigger_Returns_A_Positive_Number()
        {
            const int newParticleCount = 5;

            var trigger     = MockTrigger();
            var initializer = MockInitializer();
            var allocator   = new ParticleAllocator(10);
            var config      = new EmitterConfig
            {
                Trigger         = trigger.Object,
                Initializers    = { initializer.Object },
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            trigger.Setup(x => x.DetermineNumberOfParticlesToCreate(emitter, 0.16f))
            .Returns(newParticleCount);

            emitter.Update(0.16f);

            initializer.Verify(x =>
                               x.InitializeParticles(
                                   emitter,
                                   It.IsAny <ParticleCollection>(),
                                   It.Is <IReadOnlyList <int> >(y => y.Count == newParticleCount)),
                               Times.Once);
        }
Esempio n. 2
0
        public void Tracked_Distance_Reset_After_Emission()
        {
            var trigger = new DistanceBasedTrigger(new Random())
            {
                DistanceBetweenEmissions = 1.0f,
                MinParticlesToEmit       = 5,
                MaxParticlesToEmit       = 10,
            };

            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger,
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            emitter.WorldCoordinates = Vector2.Zero;
            trigger.DetermineNumberOfParticlesToCreate(emitter, 0.16f).ShouldBe(0);

            emitter.WorldCoordinates = new Vector2(0.5f, 0.5f);
            trigger.DetermineNumberOfParticlesToCreate(emitter, 0.16f).ShouldBe(0);

            emitter.WorldCoordinates = new Vector2(1, 1);
            trigger.DetermineNumberOfParticlesToCreate(emitter, 0.16f).ShouldBeInRange(5, 10);

            emitter.WorldCoordinates = new Vector2(1, 1.5f);
            trigger.DetermineNumberOfParticlesToCreate(emitter, 0.16f).ShouldBe(0);
        }
Esempio n. 3
0
        public void Emitter_Capacity_Expanded_If_Not_Enough_Dead_Particles_Exist()
        {
            const int newParticleCount = 3;

            var trigger = MockTrigger();

            trigger.Setup(x => x.DetermineNumberOfParticlesToCreate(It.IsAny <ParticleEmitter>(), 0.16f))
            .Returns(newParticleCount);

            var initializer = MockInitializer();
            var allocator   = new ParticleAllocator(10);
            var config      = new EmitterConfig
            {
                Trigger         = trigger.Object,
                Initializers    = { initializer.Object },
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            var values = emitter.Reservation.GetPropertyValues <bool>(StandardParmeProperties.IsAlive.Name);

            for (var x = 0; x <= 10 - newParticleCount; x++)
            {
                values[x] = true;
            }

            emitter.Update(0.16f);
            emitter.Reservation.Length.ShouldBeGreaterThan(10);
        }
Esempio n. 4
0
        public void Property_Values_Remain_After_Expansion()
        {
            var allocator = new ParticleAllocator(5);

            allocator.RegisterProperty(typeof(float), "Something");

            var first = allocator.Reserve(3);

            {
                var values = first.GetPropertyValues <float>("Something");
                values[0] = 1.1f;
                values[1] = 2.2f;
                values[2] = 3.3f;
            }

            allocator.Reserve(3);

            allocator.Capacity.ShouldBeGreaterThan(5, "Expected capacity to grow");

            var newValues = first.GetPropertyValues <float>("Something");

            newValues[0].ShouldBe(1.1f);
            newValues[1].ShouldBe(2.2f);
            newValues[2].ShouldBe(3.3f);
        }
Esempio n. 5
0
        public void KeyNotFoundException_When_Property_Is_Not_Registered()
        {
            var allocator   = new ParticleAllocator(10);
            var reservation = allocator.Reserve(5);

            Assert.Throws <KeyNotFoundException>(() => reservation.GetPropertyValues <float>("Something"));
        }
Esempio n. 6
0
        public void Can_Reserve_Block_Under_Capacity()
        {
            var allocator   = new ParticleAllocator(10);
            var reservation = allocator.Reserve(7);

            reservation.Length.ShouldBe(7);
            reservation.StartIndex.ShouldBe(0);
            reservation.LastUsedIndex.ShouldBe(6);
        }
Esempio n. 7
0
        public void KeyNotFoundException_When_Property_Registered_For_Different_Type()
        {
            var allocator   = new ParticleAllocator(10);
            var reservation = allocator.Reserve(5);

            allocator.RegisterProperty(typeof(float), "Something");

            Assert.Throws <KeyNotFoundException>(() => reservation.GetPropertyValues <bool>("Something"));
        }
Esempio n. 8
0
        public void Can_Reserve_Block_Over_Capacity()
        {
            var allocator   = new ParticleAllocator(10);
            var reservation = allocator.Reserve(11);

            allocator.Capacity.ShouldBeGreaterThan(10);
            reservation.Length.ShouldBe(11);
            reservation.StartIndex.ShouldBe(0);
            reservation.LastUsedIndex.ShouldBe(10);
        }
Esempio n. 9
0
        public void Properties_Of_Different_Types_Can_Have_The_Same_Name()
        {
            var allocator   = new ParticleAllocator(10);
            var reservation = allocator.Reserve(5);

            allocator.RegisterProperty(typeof(bool), "Something");
            allocator.RegisterProperty(typeof(float), "Something");

            var boolValues  = reservation.GetPropertyValues <bool>("Something");
            var floatValues = reservation.GetPropertyValues <float>("Something");
        }
Esempio n. 10
0
        public void Can_Expand_When_Not_Enough_Free_Space_Exists()
        {
            var allocator = new ParticleAllocator(10);

            allocator.Reserve(3);
            var reservation = allocator.Reserve(5);

            reservation.Expand(10);

            reservation.Length.ShouldBe(15);
        }
Esempio n. 11
0
        public void Can_Expand_Reservation_When_Its_The_Only_Reservation()
        {
            var allocator   = new ParticleAllocator(10);
            var reservation = allocator.Reserve(5);

            reservation.Expand(3);

            reservation.Length.ShouldBe(8);
            reservation.StartIndex.ShouldBe(0);
            reservation.LastUsedIndex.ShouldBe(7);
        }
Esempio n. 12
0
        public void Can_Reserve_When_Not_Enough_Free_Space_Exists()
        {
            var allocator = new ParticleAllocator(10);

            allocator.Reserve(3);
            allocator.Reserve(2);
            allocator.Reserve(3);
            var fourth = allocator.Reserve(3);

            fourth.Length.ShouldBe(3);
            allocator.Capacity.ShouldBeGreaterThan(10);
        }
Esempio n. 13
0
        public void Can_Expand_When_Free_Space_Exists_But_No_Big_Enough_Gaps()
        {
            var allocator = new ParticleAllocator(10);
            var first     = allocator.Reserve(3);
            var second    = allocator.Reserve(2);

            allocator.Reserve(3);
            second.Dispose();

            first.Expand(3);

            first.Length.ShouldBe(6);
        }
Esempio n. 14
0
        public void Particles_For_Initialization_Are_Marked_As_Alive()
        {
            const int newParticleCount = 3;

            var trigger = MockTrigger();

            trigger.Setup(x => x.DetermineNumberOfParticlesToCreate(It.IsAny <ParticleEmitter>(), 0.16f))
            .Returns(newParticleCount);

            var initializer = MockInitializer();
            var allocator   = new ParticleAllocator(10);
            var config      = new EmitterConfig
            {
                Trigger         = trigger.Object,
                Initializers    = { initializer.Object },
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            {
                var values = emitter.Reservation.GetPropertyValues <bool>(StandardParmeProperties.IsAlive.Name);
                values[1] = true;
                values[3] = true;
                values[5] = true;
                values[7] = true;
                values[9] = true;
            }

            IReadOnlyList <int>?newParticleIndices = null;

            initializer.Setup(x =>
                              x.InitializeParticles(
                                  It.IsAny <ParticleEmitter>(),
                                  It.IsAny <ParticleCollection>(),
                                  It.IsAny <IReadOnlyList <int> >()))
            .Callback <ParticleEmitter, ParticleCollection, IReadOnlyList <int> >((_, _, indices) => newParticleIndices = indices);

            emitter.Update(0.16f);

            newParticleIndices.ShouldNotBeNull();
            newParticleIndices.Count.ShouldBe(3);

            {
                var values = emitter.Reservation.GetPropertyValues <bool>(StandardParmeProperties.IsAlive.Name);
                values[newParticleIndices[0]].ShouldBeTrue();
                values[newParticleIndices[1]].ShouldBeTrue();
                values[newParticleIndices[2]].ShouldBeTrue();
            }
        }
Esempio n. 15
0
        public void Two_Consecutive_Reservations_Are_Adjacent()
        {
            var allocator = new ParticleAllocator(10);
            var first     = allocator.Reserve(5);
            var second    = allocator.Reserve(3);

            first.Length.ShouldBe(5);
            first.StartIndex.ShouldBe(0);
            first.LastUsedIndex.ShouldBe(4);

            second.Length.ShouldBe(3);
            second.StartIndex.ShouldBe(5);
            second.LastUsedIndex.ShouldBe(7);
        }
Esempio n. 16
0
        public void Can_Expand_Reservation_Into_Disposed_Gap()
        {
            var allocator = new ParticleAllocator(10);
            var first     = allocator.Reserve(5);
            var second    = allocator.Reserve(3);

            allocator.Reserve(2);

            second.Dispose();
            first.Expand(3);

            first.Length.ShouldBe(8);
            first.StartIndex.ShouldBe(0);
            first.LastUsedIndex.ShouldBe(7);
        }
Esempio n. 17
0
        public void Can_Reserve_When_Free_Space_Exists_But_No_Wide_Enough_Gaps()
        {
            var allocator = new ParticleAllocator(10);

            allocator.Reserve(3);
            var second = allocator.Reserve(1);

            allocator.Reserve(3);

            second.Dispose();

            var fourth = allocator.Reserve(3);

            fourth.Length.ShouldBe(3);
        }
Esempio n. 18
0
        public void Disposing_Reservation_Allows_Indices_To_Be_Reused()
        {
            var allocator = new ParticleAllocator(10);

            using (var first = allocator.Reserve(5))
            {
                first.Length.ShouldBe(5);
                first.StartIndex.ShouldBe(0);
                first.LastUsedIndex.ShouldBe(4);
            }

            var second = allocator.Reserve(5);

            second.StartIndex.ShouldBe(0);
            second.LastUsedIndex.ShouldBe(4);
        }
Esempio n. 19
0
        public void Cannot_Get_Property_Not_In_Valid_Readable_Hash_Set()
        {
            var property1 = new ParticleProperty(typeof(bool), "Something");
            var property2 = new ParticleProperty(typeof(bool), "Something2");
            var allocator = new ParticleAllocator(10);

            allocator.RegisterProperty(property1.Type, property1.Name);
            allocator.RegisterProperty(property2.Type, property2.Name);

            var reservation = allocator.Reserve(5);
            var collection  = new ParticleCollection(reservation)
            {
                ValidPropertiesToSet = new HashSet <ParticleProperty>(new[] { property1 })
            };

            Assert.ThrowsAny <Exception>(() => collection.GetReadOnlyPropertyValues <bool>(property2.Name));
        }
Esempio n. 20
0
        public void Properties_Marked_As_Valid_For_Reading_Can_Be_Retrieved_As_Read_Only()
        {
            var property  = new ParticleProperty(typeof(bool), "Something");
            var allocator = new ParticleAllocator(10);

            allocator.RegisterProperty(property.Type, property.Name);

            var reservation = allocator.Reserve(5);
            var collection  = new ParticleCollection(reservation)
            {
                ValidPropertiesToRead = new HashSet <ParticleProperty>(new[] { property })
            };

            var result = collection.GetReadOnlyPropertyValues <bool>(property.Name);

            result.Length.ShouldBe(reservation.Length);
        }
Esempio n. 21
0
        public void Modifier_Method_Called()
        {
            var trigger   = MockTrigger();
            var modifier  = MockModifier();
            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger.Object,
                Modifiers       = { modifier.Object },
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            emitter.Update(0.16f);
            modifier.Verify(x => x.Update(emitter, It.IsAny <ParticleCollection>(), 0.16f), Times.Once);
        }
Esempio n. 22
0
        public void Defrag_Occurs_When_2x_Free_Space_Exists_But_No_Wide_Enough_Gaps()
        {
            var allocator = new ParticleAllocator(15);
            var first     = allocator.Reserve(3);
            var second    = allocator.Reserve(2);
            var third     = allocator.Reserve(3);
            var fourth    = allocator.Reserve(2);
            var fifth     = allocator.Reserve(3);

            second.Dispose();
            fourth.Dispose();

            var sixth = allocator.Reserve(3);

            allocator.Capacity.ShouldBe(15); // No increase in capacity in a defrag
            VerifyAllAreConsecutive(first, third, fifth, sixth);
        }
Esempio n. 23
0
        public void Multiple_Reservations_Have_Distinct_Property_Values()
        {
            var allocator = new ParticleAllocator(8);

            allocator.RegisterProperty(typeof(float), "Something");

            var first  = allocator.Reserve(3);
            var second = allocator.Reserve(2);
            var third  = allocator.Reserve(3);

            allocator.Capacity.ShouldBe(8, "Allocator capacity shouldn't have changed yet");

            {
                var values = first.GetPropertyValues <float>("Something");
                values[0] = 1.1f;
                values[1] = 2.2f;
                values[2] = 3.3f;
            }

            {
                var values = third.GetPropertyValues <float>("Something");
                values[0] = 4.4f;
                values[1] = 5.5f;
                values[2] = 6.6f;
            }

            second.Dispose();
            allocator.Reserve(3); // cause defrag or expansion, don't care which for this test

            {
                var values = first.GetPropertyValues <float>("Something");
                values[0].ShouldBe(1.1f);
                values[1].ShouldBe(2.2f);
                values[2].ShouldBe(3.3f);
            }

            {
                var values = third.GetPropertyValues <float>("Something");
                values[0].ShouldBe(4.4f);
                values[1].ShouldBe(5.5f);
                values[2].ShouldBe(6.6f);
            }
        }
Esempio n. 24
0
        public void Trigger_Not_Called_If_Emitter_Is_Not_Active()
        {
            var trigger = MockTrigger();

            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger.Object,
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config)
            {
                IsEmittingNewParticles = false,
            };

            emitter.Update(0.16f);

            trigger.Verify(x => x.DetermineNumberOfParticlesToCreate(emitter, 0.16f), Times.Never);
        }
Esempio n. 25
0
        public void Initializer_Properties_Are_Registered()
        {
            var trigger     = MockTrigger();
            var initializer = MockInitializer();

            initializer.Setup(x => x.PropertiesISet)
            .Returns(new HashSet <ParticleProperty>(new[] { new ParticleProperty(typeof(bool), "Test1") }));

            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger.Object,
                Initializers    = { initializer.Object },
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            emitter.Reservation.GetPropertyValues <bool>("Test1");
        }
Esempio n. 26
0
        public void Only_One_Set_Of_Particles_Emitted_If_Multiples_Of_Time_Elapses()
        {
            var trigger = new TimeBasedTrigger(new Random())
            {
                SecondsBetweenEmissions = 1.0f,
                MinParticlesToEmit      = 5,
                MaxParticlesToEmit      = 5,
            };

            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger,
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            trigger.DetermineNumberOfParticlesToCreate(emitter, 5.0f).ShouldBe(5);
        }
Esempio n. 27
0
        protected static (ParticleCollection collection, int[] newIndices) RunInitializer(IParticleInitializer initializer)
        {
            var config = new EmitterConfig
            {
                Initializers    = { initializer },
                Trigger         = MockTrigger().Object,
                InitialCapacity = 10,
            };

            var allocator  = new ParticleAllocator(100);
            var emitter    = new ParticleEmitter(allocator, config);
            var collection = new ParticleCollection(emitter.Reservation)
            {
                ValidPropertiesToSet = initializer.PropertiesISet,
            };

            var newIndices = new[] { 1, 3, 5, 7 };

            initializer.InitializeParticles(emitter, collection, newIndices);
            return(collection, newIndices);
        }
Esempio n. 28
0
        public void Timer_Reset_After_Particles_Emitted()
        {
            var trigger = new TimeBasedTrigger(new Random())
            {
                SecondsBetweenEmissions = 1.0f,
                MinParticlesToEmit      = 5,
                MaxParticlesToEmit      = 10,
            };

            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger,
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            trigger.DetermineNumberOfParticlesToCreate(emitter, 1.05f).ShouldBeInRange(5, 10);
            trigger.DetermineNumberOfParticlesToCreate(emitter, 0.16f).ShouldBe(0);
        }
Esempio n. 29
0
        public void Mandatory_Properties_Are_Automatically_Registered()
        {
            var trigger = MockTrigger();

            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger.Object,
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            var reservation = emitter.Reservation;

            reservation.GetPropertyValues <bool>(StandardParmeProperties.IsAlive.Name);
            reservation.GetPropertyValues <float>(StandardParmeProperties.PositionX.Name);
            reservation.GetPropertyValues <float>(StandardParmeProperties.PositionY.Name);
            reservation.GetPropertyValues <float>(StandardParmeProperties.TimeAlive.Name);
            reservation.GetPropertyValues <float>(StandardParmeProperties.CurrentWidth.Name);
            reservation.GetPropertyValues <float>(StandardParmeProperties.CurrentHeight.Name);
        }
Esempio n. 30
0
        public void Returns_Value_Between_Min_And_Max_On_Invocation()
        {
            const int seed    = 1;
            var       trigger = new OneShotTrigger(new Random(seed))
            {
                MinParticlesToEmit = 5,
                MaxParticlesToEmit = 10,
            };

            var allocator = new ParticleAllocator(10);
            var config    = new EmitterConfig
            {
                Trigger         = trigger,
                InitialCapacity = 10,
            };

            var emitter = new ParticleEmitter(allocator, config);

            var result = trigger.DetermineNumberOfParticlesToCreate(emitter, 0.16f);

            result.ShouldBe(new Random(seed).Next(trigger.MinParticlesToEmit, trigger.MaxParticlesToEmit + 1));
        }