/// <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; } } }
public override void Handle(float t, float dt) { var npcTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(entityId); var npcBody = (CBody)Game1.Inst.Scene.GetComponentFromEntity <CBody>(entityId); var aiComponent = (CAI)Game1.Inst.Scene.GetComponentFromEntity <CAI>(entityId); var flock = (CFlock)Game1.Inst.Scene.GetComponentFromEntity <CFlock>(aiComponent.Flock); var rotationSpeed = Math.Min(1.8f * dt, 1); var movementSpeed = dt * flock.PreferredMovementSpeed * 5; var closestEnemyDistance = float.MaxValue; var closestEnemyId = -1; CTransform closestEnemyTransform = null; foreach (var player in Game1.Inst.Scene.GetComponents <CInput>()) { if (!Game1.Inst.Scene.EntityHasComponent <CBody>(player.Key)) { continue; } var playerTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(player.Key); var positionDiff = playerTransform.Position - npcTransform.Position; float distance = (float)Math.Sqrt(Math.Pow(positionDiff.X, 2) + 0 + Math.Pow(positionDiff.Z, 2)); if (closestEnemyDistance > distance) { closestEnemyDistance = distance; closestEnemyId = player.Key; closestEnemyTransform = playerTransform; } } if (closestEnemyId == -1) { return; } Vector3 dest = Vector3.Normalize(closestEnemyTransform.Position - npcTransform.Position); var source = Vector3.Backward; var goalQuat = PositionalUtil.GetRotation(source, dest, Vector3.Up); var startQuat = npcTransform.Rotation.Rotation; var dQuat = Quaternion.Lerp(startQuat, goalQuat, rotationSpeed); dQuat.X = 0; dQuat.Z = 0; npcTransform.Rotation = Matrix.CreateFromQuaternion(dQuat); // move forward in set direction npcBody.Velocity.X = (movementSpeed * npcTransform.Rotation.Forward).X; npcBody.Velocity.Z = (movementSpeed * npcTransform.Rotation.Forward).Z; }
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 Handle(float t, float dt) { var aiComponent = (CAI)Game1.Inst.Scene.GetComponentFromEntity <CAI>(entityId); var npcTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(entityId); var npcBody = (CBody)Game1.Inst.Scene.GetComponentFromEntity <CBody>(entityId); var flock = (CFlock)Game1.Inst.Scene.GetComponentFromEntity <CFlock>(aiComponent.Flock); var flockTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(aiComponent.Flock); var rotationSpeed = 1.0f * dt; var movementSpeed = dt * flock.PreferredMovementSpeed; var separation = Separation(npcTransform.Position, flock); var alignment = flock.AvgVelocity / flock.Members.Count; var cohesion = flock.Centroid - npcTransform.Position; // try to make flock stay at the same position cohesion = flockTransform.Position - npcTransform.Position; cohesion.Y = 0; // factors to enchance certain aspects of flocking behavior separation *= flock.SeparationFactor; alignment *= flock.AlignmentFactor; cohesion *= flock.CohesionFactor; // add all directions and then normalize to get a goal direction var rot = separation + cohesion + alignment; rot.Normalize(); var source = Vector3.Forward; var goalQuat = PositionalUtil.GetRotation(source, rot, Vector3.Up); // add a little randomness to goal direction var randomDirection = (float)rnd.NextDouble() * 0.25f; goalQuat.Y += randomDirection; var startQuat = npcTransform.Rotation.Rotation; var dQuat = Quaternion.Lerp(startQuat, goalQuat, rotationSpeed); dQuat.Normalize(); dQuat.X = 0; dQuat.Z = 0; // set rotation to interpolated direction npcTransform.Rotation = Matrix.CreateFromQuaternion(dQuat); // move forward in set direction npcBody.Velocity.X = (movementSpeed * npcTransform.Rotation.Forward).X; npcBody.Velocity.Z = (movementSpeed * npcTransform.Rotation.Forward).Z; }
public override void Handle(float t, float dt) { var rotationSpeed = Math.Min(0.65f * dt, 1); var stopSpeed = 1 - dt; var npcTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(entityId); var npcBody = (CBody)Game1.Inst.Scene.GetComponentFromEntity <CBody>(entityId); var closestEnemyDistance = float.MaxValue; var closestEnemyId = -1; foreach (var player in Game1.Inst.Scene.GetComponents <CInput>()) { if (!Game1.Inst.Scene.EntityHasComponent <CBody>(player.Key)) { continue; } var playerTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(player.Key); var positionDiff = playerTransform.Position - npcTransform.Position; float distance = (float)Math.Sqrt(Math.Pow(positionDiff.X, 2) + 0 + Math.Pow(positionDiff.Z, 2)); if (closestEnemyDistance > distance) { closestEnemyDistance = distance; closestEnemyId = player.Key; } } var enemyTransform = (CTransform)Game1.Inst.Scene.GetComponentFromEntity <CTransform>(closestEnemyId); Vector3 dest = Vector3.Normalize(enemyTransform.Position - npcTransform.Position); var source = Vector3.Forward; var goalQuat = PositionalUtil.GetRotation(source, dest, Vector3.Up); var startQuat = npcTransform.Rotation.Rotation; var dQuat = Quaternion.Lerp(startQuat, goalQuat, rotationSpeed); dQuat.X = 0; dQuat.Z = 0; npcTransform.Rotation = Matrix.CreateFromQuaternion(dQuat); npcBody.Velocity *= stopSpeed; }
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); } } }