/// <summary> /// Handler for scaring animals that are close to a hit /// </summary> /// <param name="obj">ID of damage receiver</param> private void handleHit(object obj) { var key = obj as int?; if (!key.HasValue) { return; } var scene = Game1.Inst.Scene; if (!scene.EntityHasComponent <CTransform>(key.Value)) { return; } var hitLocation = ((CTransform)scene.GetComponentFromEntity <CTransform>(key.Value)).Position; foreach (var aiEntity in scene.GetComponents <CAI>()) { if (!scene.EntityHasComponent <CTransform>(aiEntity.Key)) { continue; } var aiLocation = ((CTransform)(scene.GetComponentFromEntity <CTransform>(aiEntity.Key))).Position; if (PositionalUtil.Distance(hitLocation, aiLocation) <= ScaryDistance) { var aiComponent = (CAI)aiEntity.Value; aiComponent.State = new SEvade(aiEntity.Key); aiComponent.StateLockTime = ScaryTime; } } }
private Vector3 Separation(Vector3 position, CFlock flock) { // Separation // Method checks for nearby boids and steers away Vector3 steer = Vector3.Zero; int count = 0; // For every boid in the system, check if it's too close foreach (var other in flock.Members) { var otherTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(other); float d = PositionalUtil.Distance(position, otherTransform.Position); // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) if ((d > 0) && (d < flock.SeparationDistance)) { // Calculate vector pointing away from neighbor Vector3 diff = Vector3.Normalize(position - otherTransform.Position); //Vector3 diff = Vector3.Subtract(position, otherTransform.Position); //diff.Normalize(); diff /= d; // Weight by distance (makes closer neighbors more important to steer away from) steer += diff; count++; // Keep track of how many } } // Average -- divide by how many if (count > 0) { steer /= count; } /* * // As long as the vector is greater than 0 * if (steer.X > 0 || steer.Y > 0 || steer.Z > 0) { * // First two lines of code below could be condensed with new PVector setMag() method * // Not using this method until Processing.js catches up * // steer.setMag(maxspeed); * * // Implement Reynolds: Steering = Desired - Velocity * steer.Normalize(); * steer *= (maxspeed); * steer.sub(velocity); * steer.limit(maxforce); * }*/ //steer.Normalize(); return(steer); }
public override void Update(float t, float dt) { foreach (var flockKeyPair in Game1.Inst.Scene.GetComponents <CFlock>()) { var flock = (CFlock)flockKeyPair.Value; // Calculate flock centroid and avg velocity (used in some states) Vector3 theCenter = Vector3.Zero; Vector3 theVelocity = Vector3.Zero; foreach (var npcKey in flock.Members) { var npcTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(npcKey); var npcBody = (CBody)Game1.Inst.Scene.GetComponentFromEntity <CBody>(npcKey); theCenter = theCenter + npcTransform.Position; theVelocity = theVelocity + npcBody.Velocity; } var flockSize = new Vector3(flock.Members.Count); flock.Centroid = theCenter / flockSize; flock.AvgVelocity = theVelocity / flockSize; foreach (var npcKey in flock.Members) { var npcComponent = (CAI)Game1.Inst.Scene.GetComponentFromEntity <CAI>(npcKey); var npcTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(npcKey); if (npcComponent.State == null) { npcComponent.State = new SIdle(npcKey); } if (npcComponent.StateLockTime <= 0) { // find closest enemy var closestEnemyDistance = float.MaxValue; var closestEnemyId = -1; foreach (var player in Game1.Inst.Scene.GetComponents <CPlayer>()) { if (!Game1.Inst.Scene.EntityHasComponent <CBody>(player.Key)) { continue; } var playerTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(player.Key); var distance = PositionalUtil.Distance(playerTransform.Position, npcTransform.Position); if (closestEnemyDistance > distance) { closestEnemyDistance = distance; closestEnemyId = player.Key; } } if (closestEnemyId == -1) { return; } var enemyBody = (CBody)Game1.Inst.Scene.GetComponentFromEntity <CBody>(closestEnemyId); // Save fuzzy values instead of recalculating on every rule var closeToEnemy = CloseToEnemy(closestEnemyDistance); var fastEnemySpeed = FastSpeed(enemyBody.Velocity); var mediumToEnemy = MediumToEnemy(closestEnemyDistance); // Test rules and set state accordingly if ((closeToEnemy & fastEnemySpeed).IsTrue()) { if (npcComponent.State.GetType() != typeof(SEvade)) { npcComponent.State = new SEvade(npcKey); npcComponent.StateLockTime = ScaryTime; } } else if ((FuzzyUtil.Very(closeToEnemy) & !fastEnemySpeed).IsTrue()) { if (npcComponent.State.GetType() != typeof(SAware)) { npcComponent.State = new SAware(npcKey); } } else if (npcComponent.State.GetType() != typeof(SIdle)) { npcComponent.State = new SIdle(npcKey); } } // Act upon state npcComponent.State.Handle(t, dt); npcComponent.StateLockTime = Math.Max(npcComponent.StateLockTime - dt, 0); } } }