Exemple #1
0
        protected static bool BlockedFrom(GameActor actor, Vector3 toward, float closest)
        {
            Vector3 from = actor.WorldCollisionCenter;

            Vector3 ray = toward - from;
            float   len = ray.Length();

            if (len > closest)
            {
                ray /= len;
                ray *= closest;
            }
            toward = from + ray;

            SimWorld.Terra.Terrain.HitBlock hitBlock = new Boku.SimWorld.Terra.Terrain.HitBlock();

            Vector2 minMaxZ = new Vector2(0.0f, Single.MaxValue);

            float height = actor.Movement.Altitude - SimWorld.Terra.Terrain.GetTerrainAndPathHeight(actor.Movement.Position);

            Vector4 maxStep = new Vector4(
                height + actor.Chassis.WaistOffset, // max single step up
                Single.MinValue,                    // max step down
                -1.0f,                              // water depth at which transition land to water occurs (-1 to ignore)
                -1.0f);                             // water depth at which transition water to land occurs (-1 to ignore)

            switch (actor.Domain)
            {
            case GameActor.MovementDomain.Air:
                minMaxZ.X = -1.0f;
                break;

            case GameActor.MovementDomain.Land:
                maxStep.Z = 1.0f;
                break;

            case GameActor.MovementDomain.Water:
                maxStep.X = Single.MaxValue;
                maxStep.W = 1.0f;
                break;
            }

            if (SimWorld.Terra.Terrain.Blocked(from, toward, minMaxZ, maxStep, ref hitBlock, actor.Movement.Altitude))
            {
                if (Vector3.DistanceSquared(from, hitBlock.Position) < closest * closest)
                {
                    actor.AddLOSLine(from, hitBlock.Position, new Vector4(1.0f, 0.0f, 0.0f, 1.0f));
                    return(true);
                }
                actor.AddLOSLine(from, hitBlock.Position, new Vector4(1.0f, 1.0f, 0.0f, 1.0f));
            }
            else
            {
                actor.AddLOSLine(from, toward, new Vector4(0.0f, 1.0f, 0.0f, 1.0f));
            }

            return(false);
        } // end of BlockedFrom()
Exemple #2
0
        public override ActionSet ComposeActionSet(Reflex reflex, GameActor gameActor)
        {
            ClearActionSet(actionSet);
            UpdateCanBlend(reflex);

            if (!reflex.targetSet.AnyAction)
            {
                return(actionSet);
            }

            // Don't wander if we are immobilized. The effect is the bot randomly turning in place, which looks broken.
            ConstraintModifier constraintMod = reflex.GetModifierByType(typeof(ConstraintModifier)) as ConstraintModifier;

            if (constraintMod != null && constraintMod.ConstraintType == ConstraintModifier.Constraints.Immobile)
            {
                // We still need to add an attractor to the movement set so that the reflex will be considered acted on.
                // TODO (****) is thre a better way to indicate this?
                actionSet.AddActionTarget(Action.AllocTargetLocationAction(reflex, gameActor.Movement.Position, autoTurn: true));
                return(actionSet);
            }

            // Check if this target has timed out.
            if (Time.GameTimeTotalSeconds > this.wanderTimeout)
            {
                this.pickNewTarget = true;
            }

            // Calculate a vector toward target in 2d.
            Vector2 wanderTarget2d = new Vector2(this.wanderTarget.X, this.wanderTarget.Y);
            Vector2 value2d        = wanderTarget2d - new Vector2(gameActor.Movement.Position.X, gameActor.Movement.Position.Y);

            float distance = Vector3.Dot(wanderDir, gameActor.Movement.Position) - wanderDist + gameActor.BoundingSphere.Radius;

            if (distance > 0)
            {
                this.pickNewTarget = true;
            }

            if (this.pickNewTarget)
            {
                this.pickNewTarget = false;
                // we need to pick a random wander target
                this.wanderTarget  = RandomTargetLocation(gameActor);
                this.wanderTimeout = Time.GameTimeTotalSeconds + maxTimeOnTarget;
            }

            actionSet.AddActionTarget(Action.AllocTargetLocationAction(reflex, wanderTarget, autoTurn: true));

            /// For debugging, uncomment this line and enable Debug: Display Line of Sight
            /// on the character in question.
            gameActor.AddLOSLine(gameActor.Movement.Position,
                                 new Vector3(wanderTarget.X, wanderTarget.Y, gameActor.Movement.Position.Z),
                                 new Vector4(0.0f, 1.0f, 0.0f, 1.0f));

            return(actionSet);
        }
Exemple #3
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;
            }
        }
Exemple #4
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);
        }