コード例 #1
0
        /// <summary>
        /// Look to see if we are blocked from where we are trying to go. If
        /// we are, we'll expand out our circle radius until we are no longer
        /// blocked, and then slowly shrink it back again.
        /// </summary>
        /// <param name="gameActor"></param>
        private void CheckEscape(Reflex reflex, GameActor gameActor, Vector3 targetPos, GameThing target, Vector3 finalDir)
        {
            Vector3 from = gameActor.WorldCollisionCenter;

            bool  escaping    = false;
            float escapeSpeed = 10.0f;

            GameActor.BlockedInfo blockInfo = new GameActor.BlockedInfo();
            if (gameActor.Blocked(
                    from + finalDir * gameActor.Chassis.SafeStoppingDistance(),
                    ref blockInfo))
            {
                gameActor.AddLOSLine(from, blockInfo.Contact, new Vector4(1.0f, 0, 0, 1.0f));
                if (!reflex.ModifierParams.HasTurn)
                {
                    CCW = !CCW;
                }
                else
                {
                    float kMinEscape = -0.25f;

                    targetPos.Z = from.Z;

                    if ((escapeRadius > kMinEscape) && !gameActor.Blocked(target, targetPos, ref blockInfo))
                    {
                        escapeRadius -= escapeSpeed * Time.GameTimeFrameSeconds;
                        escaping      = true;
                    }
                    else
                    {
                        escapeRadius += escapeSpeed * Time.GameTimeFrameSeconds;
                        escaping      = true;
                    }
                }
            }
            if (!escaping)
            {
                if (escapeRadius > 0)
                {
                    escapeRadius = Math.Max(0.0f, escapeRadius - escapeSpeed * 0.5f * Time.GameTimeFrameSeconds);
                }
                else
                {
                    escapeRadius = Math.Min(0.0f, escapeRadius + escapeSpeed * 0.5f * Time.GameTimeFrameSeconds);
                }
            }
            float kMaxEscape = 25.0f;

            if (escapeRadius > kMaxEscape)
            {
                escapeRadius = kMaxEscape;
            }
        }
コード例 #2
0
        private Vector3 RandomTargetLocation(GameActor gameActor)
        {
            Debug.Assert(gameActor != null);

            Vector3 location3d;

            // Find a random spot for the wander target.  Take into account whether or not we've
            // stalled and the movement domain of this actor.
            Vector3 collisionNormal = Vector3.Zero;
            int     count           = 13; // Prevent this from looping forever.  On the off chance that we get n in a row
                                          // bad locations we shouldn't worry since the timeout will prevent the actor
                                          // from getting stuck.
            bool validLocation = false;

            do
            {
                float newRotation;
                // If we timed out or if we're taking too many attempts to get a valid target, assume we're bouncing
                // against a barrier and use a wider angle to pick the next target location.
                float angleWidthModifier = 1.0f;
                if (count < 8 || Time.GameTimeTotalSeconds > this.wanderTimeout)
                {
                    angleWidthModifier = 2.0f;
                }
                newRotation = angleWidthModifier * (float)BokuGame.bokuGame.rnd.NextDouble() * wanderArcRange + wanderArcMin;

                float rangeMin   = wanderRangeMin;
                float rangeDelta = wanderRangeRange;

                float wanderDistance = (float)BokuGame.bokuGame.rnd.NextDouble() * rangeDelta + rangeMin;

                if (gameActor.Chassis.HasFacingDirection)
                {
                    newRotation += gameActor.Movement.RotationZ;
                }
                else
                {
                    Vector3 dir = gameActor.Movement.Velocity;
                    dir.Z = 0.0f;
                    dir.Normalize();
                    if (!float.IsNaN(dir.X))
                    {
                        float rotation = (float)Math.Acos(dir.X);
                        if (dir.Y < 0.0f)
                        {
                            rotation = MathHelper.TwoPi - rotation;
                        }
                        newRotation += rotation;
                    }
                }

                // cap it within 0-pi*2;
                newRotation = (newRotation + MathHelper.TwoPi) % (MathHelper.TwoPi);
                Vector3 newHeading = new Vector3((float)Math.Cos(newRotation), (float)Math.Sin(newRotation), 0.0f);

                location3d = newHeading * wanderDistance + gameActor.Movement.Position;

                GameActor.BlockedInfo blockInfo = new GameActor.BlockedInfo();

                bool blocked = gameActor.Blocked(location3d, ref blockInfo);

                if (blocked)
                {
                    gameActor.AddLOSLine(gameActor.Movement.Position, blockInfo.Contact, new Vector4(1.0f, 0, 0, 1.0f));

                    float avert   = gameActor.Chassis.SafeAversionDistance();
                    float closest = gameActor.BoundingSphere.Radius + avert;
                    if (Vector3.DistanceSquared(gameActor.WorldCollisionCenter, blockInfo.Contact) > closest * closest)
                    {
                        // We have room to move in that direction
                        Vector3 dir    = blockInfo.Contact - gameActor.WorldCollisionCenter;
                        float   length = dir.Length();
                        Debug.Assert(length > 0);
                        dir    /= length;
                        length -= closest;
                        Debug.Assert(length > 0);
                        dir       *= length;
                        location3d = gameActor.Movement.Position + dir;

                        blocked = false;
                    }
                }
                if (!blocked)
                {
                    // Actors can have different domains within which they move.  Try and ensure that
                    // the point picked for wandering is valid for this actor's domain.
                    switch (gameActor.Domain)
                    {
                    case GameActor.MovementDomain.Air:
                        validLocation = CheckAirBounds(location3d);
                        break;

                    case GameActor.MovementDomain.Land:
                    {
                        // Test for ground with no water.
                        float terrainAltitude = Terrain.GetTerrainAndPathHeight(location3d);
                        if (terrainAltitude > 0.0f && Terrain.GetWaterBase(location3d) == 0.0f)
                        {
                            validLocation = true;
                            location3d.Z  = terrainAltitude;
                        }
                    }
                    break;

                    case GameActor.MovementDomain.Water:
                    {
                        // Test for water and set location somewhere between surface and ground.
                        float waterAltitude = Terrain.GetWaterBase(location3d);
                        if (Terrain.GetWaterBase(location3d) > 0.0f)
                        {
                            validLocation = true;
                            float terrainAltitude = Terrain.GetTerrainAndPathHeight(location3d);
                            location3d.Z = terrainAltitude + (waterAltitude - terrainAltitude) * (float)BokuGame.bokuGame.rnd.NextDouble();
                        }
                    }
                    break;
                    }
                }

                --count;
            } while (count > 0 && !validLocation);

            if (!validLocation)
            {
                location3d.Z = Terrain.GetTerrainAndPathHeight(location3d);
            }
            wanderDir   = location3d - gameActor.Movement.Position;
            wanderDir.Z = 0;
            if (wanderDir.LengthSquared() > 0)
            {
                wanderDir.Normalize();
            }
            wanderDist = Vector3.Dot(location3d, wanderDir);

            return(location3d);
        }