Beispiel #1
0
        /// <summary>
        /// Gets the position in world space the character should be based on how far up the rope section they are.
        /// </summary>
        /// <returns>The center for position.</returns>
        /// <param name="characterPosition">Characters grab position.</param>
        /// <param name="characterPosition">Offset from characters center and their grab (usually hand) position.</param>
        virtual public Vector2 GetCharacterPositionForPosition(float position, float handOffset)
        {
            float newPosition = position + (handOffset / Length);

            // On current section
            if (Mathf.Abs(newPosition) <= 1.0f)
            {
                return(GetCharacterPositionForPosition(newPosition));
            }
            // Above current section
            else if (newPosition >= 1.0f)
            {
                RopeSection altSection = this;
                while (newPosition > 1.0f)
                {
                    if (altSection.SectionAbove == null)
                    {
                        return(altSection.GetCharacterPositionForPosition(1.0f));
                    }
                    else
                    {
                        altSection = altSection.SectionAbove;
                    }
                    newPosition -= 1.0f;
                }
                return(altSection.GetCharacterPositionForPosition(newPosition));
            }
            // Below current section
            else
            {
                RopeSection altSection = this;
                while (newPosition < -1.0f)
                {
                    if (altSection.SectionBelow == null)
                    {
                        return(altSection.GetCharacterPositionForPosition(-1.0f));
                    }
                    else
                    {
                        altSection = altSection.SectionBelow;
                    }
                    newPosition += 1.0f;
                }
                return(altSection.GetCharacterPositionForPosition(newPosition));
            }
        }
        /// <summary>
        /// Moves the character.
        /// </summary>
        override public void DoMove()
        {
            if (swingTimer <= 0.0f)
            {
                showSwingAnimation = false;
            }
            // On a ladder/vine
            if (currentRopeSection == null)
            {
                float offsetFromCentre = transform.position.x - character.CurrentLadder.transform.position.x;
                character.Translate(-offsetFromCentre, 0, true);

                // Determine if we are at bottom of ladder (ie. the bottom of the feet colliders are below or at the ladders end)
                // Climbing
                if (character.Input.VerticalAxisDigital != 0)
                {
                    if (character.Input.VerticalAxisDigital == 1)
                    {
                        character.Translate(0, TimeManager.FrameTime * climbSpeed, true);
                        // Make sure we don't go above ladder
                        float ladderTop = (character.CurrentLadder.transform.position.y +
                                           ((BoxCollider2D)character.CurrentLadder).Offset().y) +
                                          (character.CurrentLadder.transform.lossyScale.y * (((BoxCollider2D)character.CurrentLadder).size.y / 2));
                        if (ladderTop <= character.BottomOfFeet)
                        {
                            character.Translate(0, ladderTop - character.BottomOfFeet, true);
                            // Dismount - climbed to bottom/top of ladder
                            if (((int)LadderDismountType.TOP_BOTTOM & availableDismounts) == (int)LadderDismountType.TOP_BOTTOM)
                            {
                                dismount = true;
                                character.ApplyBaseCollisionsForRaycastType(RaycastType.FOOT);
                            }
                        }
                    }
                    else if (character.Input.VerticalAxisDigital == -1)
                    {
                        character.Translate(0, TimeManager.FrameTime * -climbSpeed, true);
                        // Make sure we don't go below ladder
                        float ladderBottom = (character.CurrentLadder.transform.position.y +
                                              ((BoxCollider2D)character.CurrentLadder).Offset().y) -
                                             (character.CurrentLadder.transform.lossyScale.y * (((BoxCollider2D)character.CurrentLadder).size.y / 2));
                        if (ladderBottom >= character.BottomOfFeet)
                        {
                            character.Translate(0, ladderBottom - character.BottomOfFeet, true);
                            // Dismount - climbed to bottom/top of ladder
                            if (((int)LadderDismountType.TOP_BOTTOM & availableDismounts) == (int)LadderDismountType.TOP_BOTTOM)
                            {
                                dismount = true;
                            }
                        }
                    }
                }
            }
            // On a rope
            else
            {
                // Handle non-climbable rope
                if (currentRopeSection.usedFixedPosition)
                {
                    // Dismount on down
                    if (character.Input.VerticalAxisDigital == -1)
                    {
                        if (((int)LadderDismountType.TOP_BOTTOM & availableDismounts) == (int)LadderDismountType.TOP_BOTTOM)
                        {
                            dismount      = true;
                            dismountTimer = DismountTime;
                            character.ApplyBaseCollisionsForRaycastType(RaycastType.FOOT);
                        }
                    }
                }
                else
                {
                    // Climbing
                    if (character.Input.VerticalAxisDigital != 0)
                    {
                        if (character.Input.VerticalAxisDigital == 1)
                        {
                            // Make sure we can climb to the next rope piece if it exists
                            // Move along length
                            float newPosition = positionOnSection + (TimeManager.FrameTime * (climbSpeed / currentRopeSectionLength));
                            if (newPosition >= 2.0f)
                            {
                                Debug.LogWarning("Rope climbing speed is too large for rope section size");
                                newPosition = 1.9999f;
                            }
                            if (newPosition > 1.0f)
                            {
                                // If position is bigger than one move up to next rope section
                                RopeSection nextSection = currentRopeSection.SectionAbove;
                                // Don't allow climbing to the RopeAnchor
                                if (nextSection is RopeAnchor)
                                {
                                    nextSection = null;
                                }
                                // Or if no rope section left cap position at 1.
                                if (nextSection == null)
                                {
                                    positionOnSection = 1.0f;
                                }
                                else
                                {
                                    positionOnSection  = newPosition - 1.0f;
                                    currentRopeSection = nextSection;
                                }
                            }
                            else
                            {
                                positionOnSection = newPosition;
                            }
                        }
                        else if (character.Input.VerticalAxisDigital == -1)
                        {
                            // Make sure we can climb to the next rope piece if it exists
                            // Move along length
                            float newPosition = positionOnSection - (TimeManager.FrameTime * (climbSpeed / currentRopeSectionLength));
                            if (newPosition <= -1.0f)
                            {
                                Debug.LogWarning("Rope climbing speed is too large for rope section size");
                                newPosition = -0.9999f;
                            }
                            if (newPosition < 0)
                            {
                                // If position is smaller than zero move down to next rope section
                                RopeSection nextSection = currentRopeSection.SectionBelow;
                                // Or if no rope section left cap position at 0
                                if (nextSection == null)
                                {
                                    positionOnSection = 0;
                                    if (((int)LadderDismountType.TOP_BOTTOM & availableDismounts) == (int)LadderDismountType.TOP_BOTTOM && character.Input.VerticalAxisDigital == -1)
                                    {
                                        dismount      = true;
                                        dismountTimer = DismountTime;
                                        character.ApplyBaseCollisionsForRaycastType(RaycastType.FOOT);
                                    }
                                }
                                else
                                {
                                    positionOnSection  = newPosition + 1.0f;
                                    currentRopeSection = nextSection;
                                }
                            }
                            else
                            {
                                positionOnSection = newPosition;
                            }
                        }
                    }
                }

                // Rotate
                if (calculateAngles)
                {
                    // TODO This rotation interacts directly with the chracter transform (and other variables) - it would be nicer to do this through the character interface
                    float deg  = currentRopeSection.GetCharacterRotationForPosition(positionOnSection, handOffset);
                    float deg2 = currentRopeSection.GetCharacterRotationForPosition(positionOnSection, 0);
                    deg = (deg + deg2) / 2.0f;
                    float difference = deg - character.transform.eulerAngles.z;

                    // Shouldn't really happen but just in case
                    if (difference > 180)
                    {
                        difference = difference - 360;
                    }
                    if (difference < -180)
                    {
                        difference = difference + 360;
                    }
                    // character.transform.Rotate =  Quaternion.Euler(0,0,deg);
                    //character.transform.RotateAround(transform.position + new Vector3(0, handOffset, 0), new Vector3(0,0,1), difference);
                    if (difference > character.rotationSpeed * TimeManager.FrameTime)
                    {
                        difference = character.rotationSpeed * TimeManager.FrameTime;
                    }
                    if (difference < -character.rotationSpeed * TimeManager.FrameTime)
                    {
                        difference = -character.rotationSpeed * TimeManager.FrameTime;
                    }
                    character.transform.RotateAround(character.transform.position, new Vector3(0, 0, 1), difference);
                }


                // Snap to centre
                Vector2 diff = (Vector2)character.transform.position + (Vector2)(character.transform.localRotation * new Vector2(0, handOffset)) - currentRopeSection.GetCharacterPositionForPosition(positionOnSection, handOffset);
                character.Translate(-diff.x, -diff.y, true);

                // Apply down force
                if (downforce > 0)
                {
                    currentRopeSection.GetComponent <Rigidbody2D>().AddForceAtPosition(new Vector2(0, -downforce), character.Transform.position, ForceMode2D.Force);
                }

                // Swing (but only if not climbing)
                if (swingForce > 0 && swingTimer <= 0.0f && character.Input.HorizontalAxisDigital != 0 && character.Input.VerticalAxisDigital == 0)
                {
                    currentRopeSection.GetComponent <Rigidbody2D>().AddForceAtPosition(currentRopeSection.transform.rotation * new Vector2(swingForce * character.Input.HorizontalAxisDigital, 0), character.Transform.position, ForceMode2D.Impulse);
                    swingTimer         = swingTime;
                    showSwingAnimation = true;
                }
            }

            // We have no residual velocity if on a rope
            if (!jumpDismount)
            {
                character.SetVelocityX(0);
                character.SetVelocityY(0);
            }
        }