private FuzzyNumber SlowSpeed(Vector3 velocity) { double speed = Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Z, 2)); return(FuzzyUtil.SigMF(speed, 1.5, 2)); }
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); } } }
private FuzzyNumber FarToFlock(float distance) { return(FuzzyUtil.SigMF(distance, 20, -0.3)); }
private FuzzyNumber MediumSpeed(Vector3 velocity) { double speed = Math.Sqrt(Math.Pow(velocity.X, 2) + Math.Pow(velocity.Z, 2)); return(FuzzyUtil.GaussMF(speed, 3, 1)); }
private FuzzyNumber MediumToFlock(float distance) { return(FuzzyUtil.GaussMF(distance, 15, 10)); }
// Distance to flock private FuzzyNumber CloseToFlock(float distance) { return(FuzzyUtil.SigMF(distance, 10, 0.3)); }
private FuzzyNumber FarToEnemy(float distance) { return(FuzzyUtil.SigMF(distance, 100, -0.3)); }
private FuzzyNumber MediumToEnemy(float distance) { return(FuzzyUtil.GaussMF(distance, 50, 15)); }
// Distance to enemy private FuzzyNumber CloseToEnemy(float distance) { return(FuzzyUtil.SigMF(distance, 20, 0.3)); }