/// <summary>
        /// Tries to move towards the target position using the attached NavigationComponent asynchronously
        /// </summary>
        /// <param name="targetPosition"></param>
        /// <returns></returns>
        protected IEnumerator <Vector3> Move(Vector3 targetPosition)
        {
            NavigationComponent navigationComponent = Entity.Get <NavigationComponent>();

            List <Vector3> pathPoints = new List <Vector3>();

            if (navigationComponent == null || navigationComponent.NavigationMesh == null)
            {
                pathPoints = new List <Vector3> {
                    Entity.Transform.WorldMatrix.TranslationVector, targetPosition
                };
            }
            else
            {
                if (!navigationComponent.TryFindPath(targetPosition, pathPoints))
                {
                    yield break;
                }
            }

            Path     navigationPath = new Path(pathPoints.ToArray());
            Waypoint nextWaypoint   = navigationPath.Waypoints[0];

            while (nextWaypoint != null)
            {
                Vector3 targetSpeed = Vector3.Zero;
                if (!Drone.Stunned)
                {
                    // Move towards target when having a waypoint
                    Vector3 dir = nextWaypoint.Position - Entity.Transform.WorldMatrix.TranslationVector;
                    dir.Y = 0;
                    var dist = dir.Length();

                    if (dist < MoveThreshold)
                    {
                        nextWaypoint = nextWaypoint.Next;
                        continue;
                    }

                    dir.Normalize();
                    Drone.UpdateBodyRotation(dir);

                    targetSpeed = dir * Drone.MaximumSpeed;
                    float dt            = (float)Game.UpdateTime.Elapsed.TotalSeconds;
                    var   estimatedDist = targetSpeed.Length() * dt;
                    if (estimatedDist > dist)
                    {
                        targetSpeed = dir * (dist / dt);
                    }
                }
                Drone.SetMovement(targetSpeed);
                yield return(nextWaypoint.Position);
            }

            // Stop when done moving
            Drone.SetMovement(Vector3.Zero);
        }
Beispiel #2
0
        public override void Update()
        {
            base.Update();

            Vector2 logicalMovement = Vector2.Zero;

            if (Input.IsKeyDown(Keys.A))
            {
                logicalMovement.X = -1.0f;
            }
            if (Input.IsKeyDown(Keys.D))
            {
                logicalMovement.X = 1.0f;
            }
            if (Input.IsKeyDown(Keys.W))
            {
                logicalMovement.Y = 1.0f;
            }
            if (Input.IsKeyDown(Keys.S))
            {
                logicalMovement.Y = -1.0f;
            }

            Vector3 worldMovement = Vector3.UnitX * logicalMovement.X + Vector3.UnitZ * -logicalMovement.Y;

            worldMovement.Normalize();

            Drone.SetMovement(worldMovement);

            if (worldMovement != Vector3.Zero)
            {
                Drone.UpdateBodyRotation(worldMovement);
            }

            if (Input.IsMousePositionLocked)
            {
                Size3   backbufferSize      = Game.GraphicsDevice.Presenter.BackBuffer.Size;
                Vector2 screenSize          = new Vector2(backbufferSize.Width, backbufferSize.Height);
                Vector2 logicalHeadMovement = Input.MouseDelta * screenSize;
                logicalHeadMovement.Y = -logicalHeadMovement.Y;

                float headRotationDelta = -logicalHeadMovement.X * MathUtil.Pi / 500.0f;
                Drone.UpdateHeadRotation(Drone.HeadRotation + headRotationDelta);

                if (Input.IsKeyPressed(Keys.Space) || Input.IsMouseButtonPressed(MouseButton.Left))
                {
                    Drone.Weapon?.TryShoot(null);
                }

                if (Input.IsKeyPressed(Keys.Escape))
                {
                    Input.UnlockMousePosition();
                }
            }
            else
            {
                if (Input.IsMouseButtonPressed(MouseButton.Left))
                {
                    Input.LockMousePosition(true);
                }
            }
        }
        private void PatrolUpdate()
        {
            PatrolState patrolState = stateMachine.GetCurrentState <PatrolState>();

            if (patrolState == null)
            {
                throw new InvalidOperationException("PatrolUpdate can only be used with PatrolState");
            }

            // Move the drone on the current path, until the end of the move target is reached
            if (patrolState.MoveOperation != null)
            {
                if (!patrolState.MoveOperation.MoveNext())
                {
                    // Continue on path (if assigned)
                    if (PathToFollow != null)
                    {
                        // Done moving
                        patrolState.NextWaypoint = patrolState.NextWaypoint.Next;
                        if (patrolState.NextWaypoint == null)
                        {
                            patrolState.NextWaypoint = PathToFollow.Path.Waypoints[0]; // Loop back to first waypoint
                        }
                        patrolState.MoveOperation = Move(patrolState.NextWaypoint.Position);
                    }
                    else
                    {
                        // No move moving, this was a single target move
                        patrolState.MoveOperation = null;
                    }
                }
            }
            else
            {
                // Not moving and no path to follow, reset to spawn rotation
                Drone.UpdateBodyRotation(Drone.RotationToWorldDirection(spawnOrientation.Item1));
                Drone.UpdateHeadRotation(spawnOrientation.Item2);
            }

            // Look in moving direction
            Vector3 dir = Drone.CurrentVelocity;

            dir.Normalize();
            if (dir != Vector3.Zero)
            {
                Drone.UpdateHeadRotation(dir);
            }
            Drone.Alerted = false;

            // Check for enemies
            foreach (var collision in alertZoneTrigger.Collisions)
            {
                var targetCollider = collision.ColliderA.Entity != alertZoneTrigger.Entity
                    ? collision.ColliderA
                    : collision.ColliderB;

                if (Drone.Stunned)
                {
                    if (targetCollider.CollisionGroup != CollisionFilterGroups.CustomFilter3)
                    {
                        continue;
                    }
                }
                else
                {
                    if (targetCollider.CollisionGroup != CollisionFilterGroups.CharacterFilter &&
                        targetCollider.CollisionGroup != CollisionFilterGroups.CustomFilter1)
                    {
                        continue;
                    }
                }

                var enemy = Utils.GetDestructible(targetCollider.Entity);
                if (targetCollider.Entity == Entity || enemy == null || enemy.IsDead)
                {
                    continue;
                }

                // Visibility check
                bool hasLineOfSight = CheckLineOfSight(Entity, targetCollider);
                if (hasLineOfSight)
                {
                    // Start chasing state
                    patrolState.ChaseTarget         = targetCollider.Entity;
                    patrolState.ChaseColliderTarget = targetCollider;
                    stateMachine.SwitchTo(ChaseState.Name);
                }

                break;
            }
        }