private SteeringOut Alignment(List <MovingAgent> neighbors)
        {
            SteeringOut steeringOut = new SteeringOut();

            float newTargetAngle = 0;

            //Getting common direction
            foreach (MovingAgent agent in neighbors)
            {
                if (agent == null)
                {
                    continue;
                }

                newTargetAngle += agent.DegreeHeading();
            }
            newTargetAngle /= neighbors.Count;

            float deltaAngle = Utils.AbsDeltaAngle(newTargetAngle, _owner.DegreeHeading());

            steeringOut.LimitSpeed  = DeltaAngle2LimitSpeed(deltaAngle);
            steeringOut.TargetAngle = newTargetAngle;

            return(steeringOut);
        }
        private SteeringOut Wander()
        {
            SteeringOut steeringOut = new SteeringOut();

            float newTargetAngle = _owner.TargetAngle();

            float jitterValue = UnityEngine.Random.Range(-1f, 1f) * _fWanderJitter;

            newTargetAngle += jitterValue;

            if (newTargetAngle > 360)
            {
                newTargetAngle -= 360;
            }
            if (newTargetAngle < 0)
            {
                newTargetAngle += 360;
            }

            float deltaAngle = Utils.AbsDeltaAngle(newTargetAngle, _owner.DegreeHeading());

            steeringOut.LimitSpeed  = DeltaAngle2LimitSpeed(deltaAngle);
            steeringOut.TargetAngle = newTargetAngle;

            return(steeringOut);
        }
        public SteeringOut Calculate()
        {
            SteeringOut steeringOut = new SteeringOut();

            //TODO: Update on calculate method

            UnityEngine.Random.Range(0f, 1f);

            if (IsOn(BehaviorType.obstacle_avoidance) && Utils.Rand01f() > 0.4f)
            {
                steeringOut = ObstacleAvoidance(_owner.obstDef);
            }

            if (_targetAgent != null && steeringOut.IsOriginal())
            {
                if (IsOn(BehaviorType.pursuit))
                {
                    steeringOut = Pursuit(_targetAgent);
                    return(steeringOut);
                }

                if (IsOn(BehaviorType.seek))
                {
                    steeringOut = Seek(_targetAgent.Position);
                }

                if (IsOn(BehaviorType.arrive))
                {
                    steeringOut = Seek(_targetAgent.Position);
                }

                if (IsOn(BehaviorType.flee))
                {
                    steeringOut = Flee(_targetAgent.Position);
                }

                if (IsOn(BehaviorType.evade))
                {
                    steeringOut = Evade(_targetAgent);
                }

                if (IsOn(BehaviorType.wander))
                {
                    steeringOut = Wander();
                }
            }

            return(steeringOut);
        }
        public SteeringOut CalculateDithered()
        {
            SteeringOut steeringOut = new SteeringOut();

            double prAlignment = 0.3f;
            double prSeek      = 0.8f;
            double prPursuit   = 0.8f;

            //TODO: change prValue to get data from file

            //Directly affecting function

            if (IsOn(BehaviorType.cohesion))
            {
                Cohesion(_owner.neighbors);
            }

            if (IsOn(BehaviorType.separation))
            {
                Seperation(_owner.neighbors);
            }

            //Indirectly affecting function
            System.Random rand = new System.Random();

            if (IsOn(BehaviorType.alignment) && rand.NextDouble() < prAlignment)
            {
                steeringOut = Alignment(_owner.neighbors);
            }

            if (IsOn(BehaviorType.seek) && rand.NextDouble() < prSeek)
            {
                steeringOut = Seek(_targetAgent.Position);
            }

            if (IsOn(BehaviorType.pursuit) && rand.NextDouble() < prPursuit)
            {
                steeringOut = Pursuit(_targetAgent);
            }

            return(steeringOut);
        }
        //Directly affect body2d
        private void Cohesion(List <MovingAgent> neighbors)
        {
            SteeringOut steeringOut = new SteeringOut();

            const float cohesionForceWeight = 2;

            Vector2 centerMass = new Vector2(0, 0);

            foreach (MovingAgent agent in neighbors)
            {
                centerMass += agent.Position;
            }
            centerMass /= neighbors.Count;

            foreach (MovingAgent agent in neighbors)
            {
                Vector2 cohesionForce = (centerMass - agent.Position) * cohesionForceWeight;
                agent.AddForce(cohesionForce);
            }
        }
        //Directly affect body2d
        private void Seperation(List <MovingAgent> neighbors)
        {
            SteeringOut steeringOut           = new SteeringOut();
            const float seperationForceWeight = 30;

            foreach (MovingAgent agent in neighbors)
            {
                if (agent == null)
                {
                    continue;
                }

                Vector2 seperationForce = agent.Position - _owner.Position;
                if (seperationForce != Vector2.zero)
                {
                    seperationForce = seperationForce.normalized / seperationForce.magnitude * seperationForceWeight;
                }
                agent.AddForce(seperationForce);
            }
        }
        private SteeringOut ObstacleAvoidance(LayerMask obstDef)
        {
            SteeringOut steeringOut = new SteeringOut();

            RaycastHit2D rcHit = Physics2D.Raycast(_owner.Position, _owner.VectorHeading(),
                                                   _owner.obsFeelerLen, obstDef);

            /* Draw feeler
             * Debug.DrawRay (_owner.Position, new Vector3 (_owner.VectorHeading().x,
             *  _owner.VectorHeading ().y, 0) * _owner.obsFeelerLen, Color.green);
             */

            if (rcHit.collider == null)
            {
                return(steeringOut);
            }

            Vector2 toObst           = (Vector2)rcHit.transform.position - _owner.Position;
            float   toObstDeltaAngle = Utils.DeltaAngle(_owner.DegreeHeading(), Utils.Vector2Angle(toObst));

            float newTargetAngle = _owner.DegreeHeading();

            if (toObstDeltaAngle < 0)
            {
                newTargetAngle = newTargetAngle + 90 + toObstDeltaAngle;
            }
            else
            {
                newTargetAngle = newTargetAngle - 90 + toObstDeltaAngle;
            }

            float deltaAngle = Utils.AbsDeltaAngle(newTargetAngle, _owner.DegreeHeading());

            steeringOut.LimitSpeed  = DeltaAngle2LimitSpeed(deltaAngle);
            steeringOut.TargetAngle = newTargetAngle;

            return(steeringOut);
        }