How to implement smooth flocking

Posted by Craig on Game Development See other posts from Game Development or by Craig
Published on 2012-12-04T18:09:55Z Indexed on 2012/12/04 23:22 UTC
Read the original article Hit count: 263

Filed under:
|
|

I'm working on a simple survival game, avoid the big guy and chase the the small guys to stay alive for as long as possible.

I have taken the chase and evade example from MSDN create and drawn 20 mice on the screen.

I want the small guys to flock when they arent evading. They are doing this, but it isnt as smooth as I would like it to be. How do i make the movement smoother? Its very jittery.# Below is what I have going at the moment, flocking code is within the IF statement, when it isnt set to evading. Any help would be greatly appreciated! :)

   namespace ChaseAndEvade
      {
 class MouseSprite
{
    public enum MouseAiState
    {
        // evading the cat
        Evading,
        // the mouse can't see the "cat", and it's wandering around.
        Wander
    }


    // how fast can the mouse move?
    public float MaxMouseSpeed = 4.5f;

    // and how fast can it turn?
    public float MouseTurnSpeed = 0.20f;

    // MouseEvadeDistance controls the distance at which the mouse will flee from
    // cat. If the mouse is further than "MouseEvadeDistance" pixels away, he will
    // consider himself safe.
    public float MouseEvadeDistance = 100.0f;

    // this constant is similar to TankHysteresis. The value is larger than the
    // tank's hysteresis value because the mouse is faster than the tank: with a
    // higher velocity, small fluctuations are much more visible.
    public float MouseHysteresis = 60.0f;


    public Texture2D mouseTexture;
    public Vector2 mouseTextureCenter;
    public Vector2 mousePosition;
    public MouseAiState mouseState = MouseAiState.Wander;
    public float mouseOrientation;
    public Vector2 mouseWanderDirection;

    int separationImpact = 4;
    int cohesionImpact = 6;
    int alignmentImpact = 2;
    int sensorDistance = 50;

    public void UpdateMouse(Vector2 position, MouseSprite [] mice, int numberMice, int index)
    {

        Vector2 catPosition = position;
        int enemies = numberMice;

        // first, calculate how far away the mouse is from the cat, and use that
        // information to decide how to behave. If they are too close, the mouse
        // will switch to "active" mode - fleeing. if they are far apart, the mouse
        // will switch to "idle" mode, where it roams around the screen.
        // we use a hysteresis constant in the decision making process, as described
        // in the accompanying doc file.
        float distanceFromCat = Vector2.Distance(mousePosition, catPosition);

        // the cat is a safe distance away, so the mouse should idle:
        if (distanceFromCat > MouseEvadeDistance + MouseHysteresis)
        {
            mouseState = MouseAiState.Wander;
        }
        // the cat is too close; the mouse should run:
        else if (distanceFromCat < MouseEvadeDistance - MouseHysteresis)
        {
            mouseState = MouseAiState.Evading;
        }
        // if neither of those if blocks hit, we are in the "hysteresis" range,
        // and the mouse will continue doing whatever it is doing now.

        // the mouse will move at a different speed depending on what state it
        // is in. when idle it won't move at full speed, but when actively evading
        // it will move as fast as it can. this variable is used to track which
        // speed the mouse should be moving.
        float currentMouseSpeed;

        // the second step of the Update is to change the mouse's orientation based
        // on its current state.
        if (mouseState == MouseAiState.Evading)
        {
            // If the mouse is "active," it is trying to evade the cat. The evasion
            // behavior is accomplished by using the TurnToFace function to turn
            // towards a point on a straight line facing away from the cat. In other
            // words, if the cat is point A, and the mouse is point B, the "seek
            // point" is C.
            //     C
            //   B
            // A
            Vector2 seekPosition = 2 * mousePosition - catPosition;

            // Use the TurnToFace function, which we introduced in the AI Series 1:
            // Aiming sample, to turn the mouse towards the seekPosition. Now when
            // the mouse moves forward, it'll be trying to move in a straight line
            // away from the cat.
            mouseOrientation = ChaseAndEvadeGame.TurnToFace(mousePosition, seekPosition,
                mouseOrientation, MouseTurnSpeed);

            // set currentMouseSpeed to MaxMouseSpeed - the mouse should run as fast
            // as it can.
            currentMouseSpeed = MaxMouseSpeed;
        }
        else
        {
            // if the mouse isn't trying to evade the cat, it should just meander
            // around the screen. we'll use the Wander function, which the mouse and
            // tank share, to accomplish this. mouseWanderDirection and
            // mouseOrientation are passed by ref so that the wander function can
            // modify them. for more information on ref parameters, see
            // http://msdn2.microsoft.com/en-us/library/14akc2c7(VS.80).aspx
            ChaseAndEvadeGame.Wander(mousePosition, ref mouseWanderDirection, ref mouseOrientation,
                MouseTurnSpeed);

            // if the mouse is wandering, it should only move at 25% of its maximum
            // speed. 
            currentMouseSpeed = .25f * MaxMouseSpeed;

            Vector2 separate = Vector2.Zero;
            Vector2 moveCloser = Vector2.Zero;
            Vector2 moveAligned = Vector2.Zero;
            // What the AI does when it sees other AIs
            for (int j = 0; j < enemies; j++)
            {
                if (index != j)
                {
                    // Calculate a vector towards another AI
                    Vector2 separation = mice[index].mousePosition - mice[j].mousePosition;

                    // Only react if other AI is within a certain distance
                    if ((separation.Length() < this.sensorDistance) & (separation.Length()> 0) )
                    {
                        moveAligned += mice[j].mouseWanderDirection;

                        float distance = Math.Abs(separation.Length());
                        if (distance == 0) distance = 1;

                        moveCloser += mice[j].mousePosition;

                        separation.Normalize();
                        separate += separation / distance;

                    }
                }
            }

            if (moveAligned.LengthSquared() != 0)
            {
                moveAligned.Normalize();
            }
            if (moveCloser.LengthSquared() != 0)
            {
                moveCloser.Normalize();
            }

            moveCloser /= enemies;
            mice[index].mousePosition += (separate * separationImpact) + (moveCloser * cohesionImpact) + (moveAligned * alignmentImpact);


        }

        // The final step is to move the mouse forward based on its current
        // orientation. First, we construct a "heading" vector from the orientation
        // angle. To do this, we'll use Cosine and Sine to tell us the x and y
        // components of the heading vector. See the accompanying doc for more
        // information.
        Vector2 heading = new Vector2(
            (float)Math.Cos(mouseOrientation), (float)Math.Sin(mouseOrientation));

        // by multiplying the heading and speed, we can get a velocity vector. the
        // velocity vector is then added to the mouse's current position, moving him
        // forward.
        mousePosition += heading * currentMouseSpeed;
    }

}

}

© Game Development or respective owner

Related posts about c#

Related posts about xna-4.0