-1
\$\begingroup\$

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;
    }

}

}

\$\endgroup\$

3 Answers 3

1
\$\begingroup\$

The typical solution for jittery movement is to use linear interpolation to between movements.

Also, you don't want to set the position directly, only update it based off of velocity (and you can go further and only set the velocity based off of realistic acceleration, and even further and only change the acceleration at realistic jerk. Or just make sure you don't change the velocity too much :)).

Here where you're setting the position directly:

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

Needs to be set to a targetPosition. Then every update, move the mouse towards the targetPosition at the mouse current speed.

\$\endgroup\$
6
  • \$\begingroup\$ Well sorry jittery is the wrong word, they're moving sideways to get into the flock position, i just want it to be as smooth as the movement that they have for evading. They run away from me seperately which flows nice, then they go to flock and go sideways to their closest member. Would it still be fixed by how you detailed above? \$\endgroup\$
    – Craig
    Dec 5, 2012 at 19:03
  • \$\begingroup\$ Yes. You should be setting the seekPosition and using the TurnToFace function in the flocking. Since you're just setting the position of the mice, you're not making them move toward the desired position. So they won't necessarily be facing the position you move them to. \$\endgroup\$
    – House
    Dec 5, 2012 at 19:11
  • \$\begingroup\$ would it be along these lines then mice[index].targetPosition = mice[index].mousePosition += (separate * separationImpact) + (moveCloser * cohesionImpact) + (moveAligned * alignmentImpact); mouseOrientation = Game1.TurnToFace(mousePosition, mice[index].targetPosition, mouseOrientation, MouseTurnSpeed); \$\endgroup\$
    – Craig
    Dec 5, 2012 at 19:42
  • \$\begingroup\$ Yes, something like that. Plug it in and see how it works. \$\endgroup\$
    – House
    Dec 5, 2012 at 20:31
  • \$\begingroup\$ Hmm, they now all move to the right of the screen, always facing the same way. \$\endgroup\$
    – Craig
    Dec 5, 2012 at 20:43
1
\$\begingroup\$

Maybe you could have a look here: http://3carrotsonastick.wordpress.com/2012/11/01/boids-in-c-xna/

\$\endgroup\$
1
  • \$\begingroup\$ Hi, already been looking at that and to be honest I find it difficult to understand, going to go back and try a different way, ie set a leader and have the rest follow \$\endgroup\$
    – Craig
    Dec 6, 2012 at 19:00
0
\$\begingroup\$

Going to go back to the beginning and go about setting a leader and having the rest of the mice follow. Been told that might get me the needed results.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .