internal static EntityOnMap <K> ConvertInnerEntities(EntityOnMap <T> mapItem, K entityToInject) { var mapitemNew = new EntityOnMap <K>(mapItem.location, entityToInject); mapitemNew.ID = mapItem.ID; return(mapitemNew); }
public override PipelineReturnData pushThrough(List <EntityOnMap <SickEntity> > currentSick, List <EntityOnMap <HealthyEntity> > currentHealthy, ulong timeDeltaMs) { // Instantiating here (instead as a class variable), otherwise there // are cases where `random.Next()` returns EQUAL values for multiple // threads Random random = new Random(); // Find the closest person via Y coordinates and change diraction to match it var newSick = currentSick.Select(x => { if (currentHealthy.Count() > 0 && random.Next(1000) == 0) { var firstElement = currentHealthy.First(); // Go through all the entities and find the closest healthy entity var closestEntity = currentHealthy .Aggregate( new Tuple <EntityOnMap <HealthyEntity>, double>(firstElement, (double)World.MaxCoords.X), (aggregate, item) => { var newDistance = EntityOnMap <HealthyEntity> .calculateDistance(x.location, item.location); return(newDistance < aggregate.Item2 ? new Tuple <EntityOnMap <HealthyEntity>, double>(item, newDistance) : aggregate); }); var closestX = Math.Sign(closestEntity.Item1.location.X - x.location.X); var closestY = Math.Sign(closestEntity.Item1.location.Y - x.location.Y); x.entity.direction = new Vector3(closestX, closestY, 0); } return(x); }).ToList(); return(new PipelineReturnData { newHealthy = currentHealthy, newSick = newSick, }); }
public override PipelineReturnData pushThrough(List <EntityOnMap <SickEntity> > currentSick, List <EntityOnMap <HealthyEntity> > currentHealthy, ulong timeDeltaMs) { // Make entities sick if they need to /* * NOTE: Because the timeScale parameter removes "frames" * and possible intersections (no interpolation is being * done as it's quite intensive to do at real time), * the code tries to compensate by increasing the radius. * Because we don't want everyone to become sick immediately, * then linear scaling is not possible. Using this * (https://www.desmos.com/calculator/7agyg8rqqz) for * trying out some things. */ var toBeSick = currentHealthy .Where(h => { // Only keep entries that are intersecting with sick people return(currentSick .Any(s => EntityOnMap <SickEntity> .IsIntersecting( s.location, radius, h.location, radius) )); }) .Select((x, idx) => { // Covert to sick entities var sickEntity = SickEntity.ConvertToSick(x.entity); var sickMapItem = EntityConverterUtility <HealthyEntity, SickEntity> .ConvertInnerEntities(x, sickEntity); return(sickMapItem); }) .Aggregate((new List <ulong>(), new List <EntityOnMap <SickEntity> >()), (aggregate, item) => { aggregate.Item1.Add(item.ID); aggregate.Item2.Add(item); return(aggregate); }) .ToTuple(); return(new PipelineReturnData { newHealthy = currentHealthy.Where(x => !toBeSick.Item1.Contains(x.ID)).ToList(), newSick = currentSick.Concat(toBeSick.Item2).ToList(), }); }
internal static void iterateOver( List <EntityOnMap <T> > entities, Random random, Dictionary <ulong, int> nextAttractor, List <Point> attractors, int attractorRadius ) { // Perform attractor assignment entities.ForEach(x => { // Check if is registered if (nextAttractor.ContainsKey(x.ID)) { var attractorIndex = nextAttractor[x.ID]; // Check if located at desired attractor if (EntityOnMap <SickEntity> .IsIntersecting(x.location, 1, attractors[attractorIndex], (ushort)attractorRadius)) { // Generte a new attractor to head towards nextAttractor[x.ID] = random.Next(0, attractors.Count() - 1); } // Add some randomness if (random.Next(100) == 0) { var attractorDirectionX = Math.Sign(attractors[attractorIndex].X - x.location.X); var attractorDirectionY = Math.Sign(attractors[attractorIndex].Y - x.location.Y); x.entity.direction = new Vector3(attractorDirectionX, attractorDirectionY, 0); } } else { // Generte a new attractor to head towards nextAttractor[x.ID] = random.Next(0, attractors.Count() - 1); } }); }