Beispiel #1
0
 //returns true if the previous movement step is diagonal to movement step, else returns false
 private bool MovementIsDiagonal(NPCMovementStep npcMovementStep, NPCMovementStep previousNPCMovementStep)
 {
     if ((npcMovementStep.gridCoordinate.x != previousNPCMovementStep.gridCoordinate.x) && (npcMovementStep.gridCoordinate.y != previousNPCMovementStep.gridCoordinate.y))
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Beispiel #2
0
 /// <summary>
 ///  Determines if the movement step between a previous step and the current movement step is diagonal or not, so we know how long it takes to traverse between the two steps
 /// </summary>
 /// <param name="npcMovementStep"></param>
 /// <param name="previousNPCMovementStep"></param>
 /// <returns> Returns true if the step between them is diagonal, and false if they are horizontal or vertical </returns>
 private bool MovementIsDiagonal(NPCMovementStep npcMovementStep, NPCMovementStep previousNPCMovementStep)
 {
     // Return true if the npcMovementStep gridCoordinates are diagonal (x1 != x2 and y1 != y2), and false if they are horizontal/vertical
     if ((npcMovementStep.gridCoordinate.x != previousNPCMovementStep.gridCoordinate.x) && (npcMovementStep.gridCoordinate.y != previousNPCMovementStep.gridCoordinate.y))
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Beispiel #3
0
    private void UpdatePathOnNPCMovementStepStack(SceneName sceneName, Stack <NPCMovementStep> npcMovementStepStack)
    {
        Node nextNode = targetNode;

        while (nextNode != null)
        {
            NPCMovementStep npcMovementStep = new NPCMovementStep();

            npcMovementStep.sceneName      = sceneName;
            npcMovementStep.gridCoordinate = new Vector2Int(nextNode.gridPosition.x + originX, nextNode.gridPosition.y + originY);

            npcMovementStepStack.Push(npcMovementStep);

            nextNode = nextNode.parentNode;
        }
    }
Beispiel #4
0
    /// <summary>
    /// Update the path movement steps with the expected gameTimes we need to be on that step for
    /// All of the MovementSteps in the MovementStepStack for the NPC to follow, contains the sceneName/gridCoordinate to move to, and the hour/min/sec that we have to be on that step by
    /// This allows us to control the NPCs speed between steps
    /// </summary>
    public void UpdateTimesOnPath()
    {
        // Get the current game time from the timeManager
        TimeSpan currentGameTime = TimeManager.Instance.GetGameTime();

        // This is the previous step taken (so we can adjust the walking direction to go from previousStep -> currentStep)
        NPCMovementStep previousNPCMovementStep = null;

        // Loop through all of the npcMovementStep in the npcMovementStepStack and update the time we need to be at that step by, as member variables in the individual npcMovementSteps
        foreach (NPCMovementStep npcMovementStep in npcMovementStepStack)
        {
            // If we're on the first step, set the previousStep to the currentStep so the next step has it
            if (previousNPCMovementStep == null)
            {
                previousNPCMovementStep = npcMovementStep;
            }

            // set the current step as the current game time. At the end of the loop we will add the next step's worth of time to currentGameTime so the next step will be larger
            npcMovementStep.hour   = currentGameTime.Hours;
            npcMovementStep.minute = currentGameTime.Minutes;
            npcMovementStep.second = currentGameTime.Seconds;

            // This is the amount of time the current step will take to make
            TimeSpan movementTimeStep;

            // Compute the time required for the current movement step, depending on if it's a diagonal or horizontal/vertical step
            // This is computed as the distance to travel / NPCs speed, and additionally modified by 1/secondsPerGameSecond to get it in real time
            // If the current step is diagonal from the previous step, calculate the step time distance from a diagonal cell size. If not, use a normal cell size
            if (MovementIsDiagonal(npcMovementStep, previousNPCMovementStep))
            {
                movementTimeStep = new TimeSpan(0, 0, (int)(Settings.gridCellDiagonalSize / Settings.secondsPerGameSecond / npcMovement.npcNormalSpeed));
            }
            else
            {
                movementTimeStep = new TimeSpan(0, 0, (int)(Settings.gridCellSize / Settings.secondsPerGameSecond / npcMovement.npcNormalSpeed));
            }

            // Add the time for the next movement step to the currentGameTime so the next step in the loop will have this steps time added to it
            currentGameTime = currentGameTime.Add(movementTimeStep);

            // Set the previous step to the current one so we can start over on the next step
            previousNPCMovementStep = npcMovementStep;
        }
    }
Beispiel #5
0
    /// <summary>
    /// This method loops through all of the parents to the currentNode which is now the targetNode because we found a path. Following the parents
    /// backwards will eventually get to the start node. for each node we traverse, create a new npcMovementStep populated with the sceneName and
    /// Coordinate of the current node, and add it to the npcMovementStepStack that NPCs will follow
    /// </summary>
    /// <param name="sceneName"></param>
    /// <param name="npcMovementStepStack"></param>
    private void UpdatePathOnNPCMovementStepStack(SceneName sceneName, Stack <NPCMovementStep> npcMovementStepStack)
    {
        // If we found a path, the currentNode = targetNode, so we just need to follow that path of parentNodes back to the startNode (every node has a list of parentNodes working back to the start Node)
        // Start out at the targetNode (= currentNode) and work backwards towards the startNode
        Node nextNode = targetNode;

        // Loop through the currentNode=targetNode's parent nodes all the way back to the startNode when it's parent = null
        while (nextNode != null)
        {
            // For each Node we traverse backwards, create a new movement step (which stores the sceneName, the goordinates of that step, and the time of that step)
            NPCMovementStep npcMovementStep = new NPCMovementStep();

            // Populate the sceneName and gridCoordinate (offset by the origon to convert grid location to tileMap location) for the current step in the loop
            npcMovementStep.sceneName      = sceneName;
            npcMovementStep.gridCoordinate = new Vector2Int(nextNode.gridPosition.x + originX, nextNode.gridPosition.y + originY);

            // add the newly updated step to the NPC movement step stack (pushed onto the stack - so the FIRST thing we add to the stack, is the LAST thing we take off of the stack
            npcMovementStepStack.Push(npcMovementStep);

            // Set the nextNode to the currentNodes parent, and repeat, all the way to the startNode when the nextNode will = null!
            nextNode = nextNode.parentNode;
        }
    }
    private void FixedUpdate()
    {
        if (sceneLoaded)
        {
            if (npcIsMoving == false)
            {
                // set npc current and next grid position - to take into account the npc might be animating
                npcCurrentGridPosition = GetGridPosition(transform.position);
                npcNextGridPosition    = npcCurrentGridPosition;

                if (npcPath.npcMovementStepStack.Count > 0)
                {
                    NPCMovementStep npcMovementStep = npcPath.npcMovementStepStack.Peek();

                    npcCurrentScene = npcMovementStep.sceneName;

                    // If NPC is about the move to a new scene reset position to starting point in new scene and update the step times
                    if (npcCurrentScene != npcPreviousMovementStepScene)
                    {
                        npcCurrentGridPosition       = (Vector3Int)npcMovementStep.gridCoordinate;
                        npcNextGridPosition          = npcCurrentGridPosition;
                        transform.position           = GetWorldPosition(npcCurrentGridPosition);
                        npcPreviousMovementStepScene = npcCurrentScene;
                        npcPath.UpdateTimesOnPath();
                    }


                    // If NPC is in current scene then set NPC to active to make visible, pop the movement step off the stack and then call method to move NPC
                    if (npcCurrentScene.ToString() == SceneManager.GetActiveScene().name)
                    {
                        SetNPCActiveInScene();

                        npcMovementStep = npcPath.npcMovementStepStack.Pop();

                        npcNextGridPosition = (Vector3Int)npcMovementStep.gridCoordinate;

                        TimeSpan npcMovementStepTime = new TimeSpan(npcMovementStep.hour, npcMovementStep.minute, npcMovementStep.second);

                        MoveToGridPosition(npcNextGridPosition, npcMovementStepTime, TimeManager.Instance.GetGameTime());
                    }

                    // else if NPC is not in current scene then set NPC to inactive to make invisible
                    // - once the movement step time is less than game time (in the past) then pop movement step off the stack and set NPC position to movement step position
                    else
                    {
                        SetNPCInactiveInScene();

                        npcCurrentGridPosition = (Vector3Int)npcMovementStep.gridCoordinate;
                        npcNextGridPosition    = npcCurrentGridPosition;
                        transform.position     = GetWorldPosition(npcCurrentGridPosition);

                        TimeSpan npcMovementStepTime = new TimeSpan(npcMovementStep.hour, npcMovementStep.minute, npcMovementStep.second);

                        TimeSpan gameTime = TimeManager.Instance.GetGameTime();

                        if (npcMovementStepTime < gameTime)
                        {
                            npcMovementStep = npcPath.npcMovementStepStack.Pop();

                            npcCurrentGridPosition = (Vector3Int)npcMovementStep.gridCoordinate;
                            npcNextGridPosition    = npcCurrentGridPosition;
                            transform.position     = GetWorldPosition(npcCurrentGridPosition);
                        }
                    }
                }
                // else if no more NPC movement steps
                else
                {
                    ResetMoveAnimation();

                    SetNPCFacingDirection();

                    SetNPCEventAnimation();
                }
            }
        }
    }
    // FixedUpdate will move our NPC following the NPCMovementSteps in the NPCMovementStepStack. It processes each step in turn, waiting until it's done to start on the next step.
    // It will move the NPC one step at a time via a coroutine that moves the NPC from the current gridPosition to the next one. Once that's done, this
    // fixed update method will initiate the next step
    private void FixedUpdate()
    {
        // Make sure the scene is loaded before doing anything
        if (sceneLoaded)
        {
            // Make sure the NPC isn't already moving before doing anything. Every fixed update this will be checked, and if npcIsMoving=true, it is currently moving one step.
            // Eventually, when it's false again this will be enabled and we can move the next step
            if (npcIsMoving == false)
            {
                // Set the NPC current and next grid position - to take into account the NPC might be animating
                // The current position is where the NPC currently is, and initially we will set the next grid position to the current one
                npcCurrentGridPosition = GetGridPosition(transform.position);
                npcNextGridPosition    = npcCurrentGridPosition;

                // Only run if there are still NPCMovementSteps in the NPCMovementStepStack
                if (npcPath.npcMovementStepStack.Count > 0)
                {
                    // Populate the npcMovementStep with the npcMovementStep on the top of the stack (just peek at it, don't remove yet)
                    NPCMovementStep npcMovementStep = npcPath.npcMovementStepStack.Peek();

                    // Set the current NPC scene to the first movement step in this stack
                    npcCurrentScene = npcMovementStep.sceneName;

                    // If the NPC is about to move to a new scene, reset their position to the starting point in the new scene, and re-update the step times for the
                    // next path elements in the new scene
                    if (npcCurrentScene != npcPreviousMovementStepScene)
                    {
                        // If the current and next scenes are different, we are about to change scenes. Update the NPCs current grid position to the next movement steps grid coordinate
                        // (in the next scene), set the nextGridPosition to the current one, update the NPCs transform to immediately teleport them to the new scenes entrance point,
                        // update the NPCs current scene, and re-update the remaining times on the path (things probably got messed up between scenes because the grid coordinates changed substantially)
                        npcCurrentGridPosition       = (Vector3Int)npcMovementStep.gridCoordinate;
                        npcNextGridPosition          = npcCurrentGridPosition;
                        transform.position           = GetWorldPosition(npcCurrentGridPosition);
                        npcPreviousMovementStepScene = npcCurrentScene;
                        npcPath.UpdateTimesOnPath();
                    }

                    // If the NPC is in the current scene, then set the NPC to active to make it visiblie, then pop the movement step off
                    // The top of the stack, and then call the method to actually move the NPC
                    if (npcCurrentScene.ToString() == SceneManager.GetActiveScene().name)
                    {
                        // Set the NPC to active in the scene so we can see them
                        SetNPCActiveInScene();

                        // Pop the next npcMovementStep from the top of the npcMovementStepStack
                        npcMovementStep = npcPath.npcMovementStepStack.Pop();

                        // Find the next grid position the NPC needs to walk to from the next npcMovementStep, gridCoordinate member
                        npcNextGridPosition = (Vector3Int)npcMovementStep.gridCoordinate;

                        // This is the time this next npcMovementStep will take, from it's hour/minute/second member variables
                        TimeSpan npcMovementStepTime = new TimeSpan(npcMovementStep.hour, npcMovementStep.minute, npcMovementStep.second);

                        // This method will move the NPC to the next grid position npcNextGridPosition, and make sure they are there by the time npcMovementStepTime, starting off
                        // at the current game time
                        MoveToGridPosition(npcNextGridPosition, npcMovementStepTime, TimeManager.Instance.GetGameTime());
                    }

                    // Else, if the NPC is not in the current scene, then set the NPC to inactive to make it invisible (it's still moving but we can't see it until we move to their scene)
                    // Once the movement step time is less than the game time (i.e. in the past), then pop the movement step off the stack and set the NPC position to the
                    // movement step position. Because we can't see the NPC, we don't need to run the walking animations - just keep popping off the next movement Step and
                    // immediately teleporting the NPC there at the proper times. This will keep happening until the player enters the NPC's current scene - and then
                    // they will start smoothly walking again.
                    else
                    {
                        // Disables the sprite renderer and box collider, and sets the npcActiveInScene to false. The NPC is still on the persistent scene and moving, but we can't see them so it looks like they arent
                        SetNPCInactiveInScene();

                        // Set the current and nextGrid position and move the NPC to the current one
                        npcCurrentGridPosition = (Vector3Int)npcMovementStep.gridCoordinate;
                        npcNextGridPosition    = npcCurrentGridPosition;
                        transform.position     = GetWorldPosition(npcCurrentGridPosition);

                        // The step time needed for the next step to be completed by, and the current game time
                        TimeSpan npcMovementStepTime = new TimeSpan(npcMovementStep.hour, npcMovementStep.minute, npcMovementStep.second);
                        TimeSpan gameTime            = TimeManager.Instance.GetGameTime();

                        // Whenever the stepTime < gameTime (so they should be to the next position by now), immediately teleport the NPC to that step, and then wait for the next step to occur, and then
                        // teleport them again. This will keep going until the player enters the NPC's current scene - then they will start smoothly walking again.
                        if (npcMovementStepTime < gameTime)
                        {
                            // Pop off the next Movement Step from the Stack
                            npcMovementStep = npcPath.npcMovementStepStack.Pop();

                            // Update the current and next grid positions, and immediately teleport the NPC to the next step position, rather than the smooth walking animation if the player IS in the NPCs scene.
                            npcCurrentGridPosition = (Vector3Int)npcMovementStep.gridCoordinate;
                            npcNextGridPosition    = npcCurrentGridPosition;
                            transform.position     = GetWorldPosition(npcCurrentGridPosition);
                        }
                    }
                }

                // Else, if there are no more movement steps in the npcMovementStepStack (we've reached our target destination!), reset the move animation parameters so the NPC stops moving, then
                // set the proper NPCs facing direction, and then initiate the NPCs target animation
                else
                {
                    // Trigger all of the animator parameters to false for walking, so the NPC will stop the walking animation
                    ResetMoveAnimation();

                    // Using the npcFacingDirection set in the movement schedule, this will trigger the proper facing direction (i.e. idleUp, idleLeft, etc) once we're arrived at our destination
                    SetNPCFacingDirection();

                    // Set the NPCs target animation to play (i.e. smokeDirection, digDirection, etc) now that we're at the destination, as long as
                    // one has been specified in the NPCScheduleEvent
                    SetNPCEventAnimation();
                }
            }
        }
    }