Example #1
0
        /// <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;
                }
            }
        }
Example #2
0
        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;
        }
Example #3
0
        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);
        }
Example #4
0
        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;
        }
Example #5
0
        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;
        }
Example #6
0
        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);
                }
            }
        }