예제 #1
0
    void StickToGround(GroundInfo info)
    {
        float angle = info.angle * Mathf.Rad2Deg;

        characterAngle = angle;
        Vector3 pos = transform.position;

        switch (groundMode)
        {
        case GroundMode.Floor:
            if (angle < 315f && angle > 225f)
            {
                groundMode = GroundMode.LeftWall;
            }
            else if (angle > 45f && angle < 180f)
            {
                groundMode = GroundMode.RightWall;
            }
            pos.y = info.point.y + heightHalf;
            break;

        case GroundMode.RightWall:
            if (angle < 45f && angle > 0f)
            {
                groundMode = GroundMode.Floor;
            }
            else if (angle > 135f && angle < 270f)
            {
                groundMode = GroundMode.Ceiling;
            }
            pos.x = info.point.x - heightHalf;
            break;

        case GroundMode.Ceiling:
            if (angle < 135f && angle > 45f)
            {
                groundMode = GroundMode.RightWall;
            }
            else if (angle > 225f && angle < 360f)
            {
                groundMode = GroundMode.LeftWall;
            }
            pos.y = info.point.y - heightHalf;
            break;

        case GroundMode.LeftWall:
            if (angle < 225f && angle > 45f)
            {
                groundMode = GroundMode.Ceiling;
            }
            else if (angle > 315f)
            {
                groundMode = GroundMode.Floor;
            }
            pos.x = info.point.x + heightHalf;
            break;

        default:
            break;
        }

        transform.position = pos;
    }
예제 #2
0
    void FixedUpdate()
    {
        if (Input.GetKeyDown(KeyCode.Tab))
        {
            debug = !debug;
        }

        Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));

        float accelSpeedCap = underwater ? uwGroundTopSpeed : groundTopSpeed;

        if (grounded)
        {
            if (!rolling && input.y < -0.005f && Mathf.Abs(groundVelocity) >= rollingMinSpeed)
            {
                rolling             = true;
                transform.position -= new Vector3(0f, 5f);
            }

            float slope = 0f;
            if (rolling)
            {
                float sin    = Mathf.Sin(currentGroundInfo.angle);
                bool  uphill = (sin >= 0f && groundVelocity >= 0f) || (sin <= 0f && groundVelocity <= 0);
                slope = uphill ? rollUphillSlope : rollDownhillSlope;
            }
            else
            {
                slope = slopeFactor;
            }
            groundVelocity += (slope * -Mathf.Sin(currentGroundInfo.angle)) * Time.fixedDeltaTime;

            bool lostFooting = false;

            if (groundMode != GroundMode.Floor && Mathf.Abs(groundVelocity) < fallVelocityThreshold)
            {
                groundMode       = GroundMode.Floor;
                grounded         = false;
                hControlLock     = true;
                hControlLockTime = 0.5f;
                lostFooting      = true;
            }

            if (Input.GetButtonDown("Jump") && !lowCeiling)
            {
                float jumpVel = underwater ? uwJumpVelocity : jumpVelocity;
                velocity.x -= jumpVel * (Mathf.Sin(currentGroundInfo.angle));
                velocity.y += jumpVel * (Mathf.Cos(currentGroundInfo.angle));
                grounded    = false;
                jumped      = true;
            }
            else
            {
                if (hControlLock)
                {
                    hControlLockTime -= Time.fixedDeltaTime;
                    if (hControlLockTime <= 0f)
                    {
                        hControlLock = false;
                    }
                }

                if (rolling || Mathf.Abs(input.x) < 0.005f)
                {
                    // Mostly because I don't like chaining ternaries
                    float fric     = underwater ? uwFriction : friction;
                    float rollFric = underwater ? uwRollingFriction : rollingFriction;

                    float frc = rolling ? rollFric : fric;
                    if (groundVelocity > 0f)
                    {
                        groundVelocity -= frc * Time.fixedDeltaTime;
                        if (groundVelocity < 0f)
                        {
                            groundVelocity = 0f;
                        }
                    }
                    else if (groundVelocity < 0f)
                    {
                        groundVelocity += frc * Time.fixedDeltaTime;
                        if (groundVelocity > 0f)
                        {
                            groundVelocity = 0f;
                        }
                    }
                }

                if (!hControlLock && Mathf.Abs(input.x) >= 0.005f)
                {
                    float accel = underwater ? uwAcceleration : groundAcceleration;
                    float decel = underwater ? uwDeceleration : deceleration;

                    if (input.x < 0f)
                    {
                        if (groundVelocity < 0f)
                        {
                            // TODO: Set a direction variable instead
                            Vector3 scale = Vector3.one;
                            scale.x *= Mathf.Sign(groundVelocity);
                            transform.localScale = scale;
                        }
                        float acceleration = 0f;
                        if (rolling && groundVelocity > 0f)
                        {
                            acceleration = rollingDeceleration;
                        }
                        else if (!rolling && groundVelocity > 0f)
                        {
                            acceleration = decel;
                        }
                        else if (!rolling && groundVelocity <= 0f)
                        {
                            acceleration = accel;
                        }

                        if (groundVelocity > -accelSpeedCap)
                        {
                            groundVelocity = Mathf.Max(-accelSpeedCap, groundVelocity + (input.x * acceleration) * Time.deltaTime);
                        }
                    }
                    else
                    {
                        if (groundVelocity > 0f)
                        {
                            Vector3 scale = Vector3.one;
                            transform.localScale = scale;
                        }
                        float acceleration = 0f;
                        if (rolling && groundVelocity < 0f)
                        {
                            acceleration = rollingDeceleration;
                        }
                        else if (!rolling && groundVelocity < 0f)
                        {
                            acceleration = decel;
                        }
                        else if (!rolling && groundVelocity >= 0f)
                        {
                            acceleration = accel;
                        }
                        if (groundVelocity < accelSpeedCap)
                        {
                            groundVelocity = Mathf.Min(accelSpeedCap, groundVelocity + (input.x * acceleration) * Time.deltaTime);
                        }
                    }
                }

                if (groundVelocity > speedLimit)
                {
                    groundVelocity = speedLimit;
                }
                else if (groundVelocity < -speedLimit)
                {
                    groundVelocity = -speedLimit;
                }

                if (rolling && Mathf.Abs(groundVelocity) < unrollThreshold)
                {
                    rolling             = false;
                    transform.position += new Vector3(0f, 5f);
                }

                Vector2 angledSpeed = new Vector2(groundVelocity * Mathf.Cos(currentGroundInfo.angle), groundVelocity * Mathf.Sin(currentGroundInfo.angle));
                velocity = angledSpeed;
                if (lostFooting)
                {
                    groundVelocity = 0f;
                }
            }
        }
        else
        {
            float jumpRelThreshold = underwater ? uwJumpReleaseThreshold : jumpReleaseThreshold;
            if (jumped && velocity.y > jumpRelThreshold && Input.GetButtonUp("Jump"))
            {
                velocity.y = jumpRelThreshold;
            }
            else
            {
                // Air drag effect
                if (velocity.y > 0f && velocity.y < 4f && Mathf.Abs(velocity.x) > 7.5f)
                {
                    velocity.x *= airDrag;
                }

                float grv = underwater ? uwGravity : gravity;

                velocity.y = Mathf.Max(velocity.y + (grv * Time.fixedDeltaTime), -terminalVelocity);
            }

            if (!(rolling && jumped) && Mathf.Abs(input.x) >= 0.005f)
            {
                if ((input.x < 0f && velocity.x > -accelSpeedCap) || (input.x > 0f && velocity.x < accelSpeedCap))
                {
                    float airAcc = underwater ? uwAirAcceleration : airAcceleration;
                    velocity.x = Mathf.Clamp(velocity.x + (input.x * airAcc * Time.fixedDeltaTime), -accelSpeedCap, accelSpeedCap);
                }
            }
        }

        // Clamp velocity to global speed limit; going any faster could result in passing through things
        velocity.x = Mathf.Clamp(velocity.x, -speedLimit, speedLimit);
        velocity.y = Mathf.Clamp(velocity.y, -speedLimit, speedLimit);

        // Apply movement
        transform.position += new Vector3(velocity.x, velocity.y, 0f) * Time.fixedDeltaTime;

        // Now do collision testing

        RaycastHit2D leftHit;
        RaycastHit2D rightHit;

        WallCheck(sideRaycastDist, grounded ? sideRaycastOffset : 0f, out leftHit, out rightHit);

        if (leftHit.collider != null && rightHit.collider != null)
        {
            // Got squashed
            Debug.Log("GOT SQUASHED");
        }
        else if (leftHit.collider != null)
        {
            transform.position = new Vector2(leftHit.point.x + sideRaycastDist, transform.position.y);
            if (velocity.x < 0f)
            {
                velocity.x     = 0f;
                groundVelocity = 0f;
            }
        }
        else if (rightHit.collider != null)
        {
            transform.position = new Vector2(rightHit.point.x - sideRaycastDist, transform.position.y);
            if (velocity.x > 0f)
            {
                velocity.x     = 0f;
                groundVelocity = 0f;
            }
        }

        bool ceilingLeft  = false;
        bool ceilingRight = false;
        int  ceilDir      = (int)groundMode + 2;

        if (ceilDir > 3)
        {
            ceilDir -= 4;
        }
        GroundInfo ceil = GroundedCheck(groundRaycastDist, (GroundMode)ceilDir, out ceilingLeft, out ceilingRight);

        bool groundedLeft  = false;
        bool groundedRight = false;

        if (grounded)
        {
            currentGroundInfo = GroundedCheck(groundRaycastDist, groundMode, out groundedLeft, out groundedRight);
            grounded          = groundedLeft || groundedRight;
        }
        else
        {
            if (ceil.valid && velocity.y > 0f)
            {
                bool  hitCeiling = transform.position.y >= (ceil.point.y - heightHalf);
                float angleDeg   = ceil.angle * Mathf.Rad2Deg;

                // Check for attaching to ceiling
                if (hitCeiling && ((angleDeg >= 225f && angleDeg <= 270f) || (angleDeg >= 90f && angleDeg <= 135f)))
                {
                    grounded          = true;
                    jumped            = false;
                    rolling           = false;
                    currentGroundInfo = ceil;
                    groundMode        = GroundMode.Ceiling;

                    groundVelocity = velocity.y * Mathf.Sign(Mathf.Sin(currentGroundInfo.angle));
                    velocity.y     = 0f;
                }
                else if (hitCeiling)
                {
                    if (transform.position.y > ceil.point.y - heightHalf)
                    {
                        transform.position = new Vector2(transform.position.x, ceil.point.y - heightHalf);
                        velocity.y         = 0f;
                    }
                }
            }
            else
            {
                GroundInfo info = GroundedCheck(groundRaycastDist, GroundMode.Floor, out groundedLeft, out groundedRight);

                grounded = (groundedLeft || groundedRight) && velocity.y <= 0f && transform.position.y <= (info.height + heightHalf);

                // Re-calculate ground velocity based on previous air velocity
                if (grounded)
                {
                    // If in a roll jump, add 5 to position upon landing
                    if (jumped)
                    {
                        transform.position += new Vector3(0f, 5f);
                    }

                    jumped  = false;
                    rolling = false;

                    currentGroundInfo = info;
                    groundMode        = GroundMode.Floor;
                    float angleDeg = currentGroundInfo.angle * Mathf.Rad2Deg;

                    // If angle is close to level with ground, just use x velocity as ground velocity
                    if (angleDeg < 22.5f || (angleDeg > 337.5 && angleDeg <= 360f))
                    {
                        groundVelocity = velocity.x;
                    }
                    else if ((angleDeg >= 22.5f && angleDeg < 45f) || (angleDeg >= 315f && angleDeg < 337.5f))
                    {
                        if (Mathf.Abs(velocity.x) > Mathf.Abs(velocity.y))
                        {
                            groundVelocity = velocity.x;
                        }
                        else
                        {
                            groundVelocity = velocity.y * 0.5f * Mathf.Sign(Mathf.Sin(currentGroundInfo.angle));
                        }
                    }
                    else if ((angleDeg >= 45f && angleDeg < 90f) || (angleDeg >= 270f && angleDeg < 315f))
                    {
                        if (Mathf.Abs(velocity.x) > Mathf.Abs(velocity.y))
                        {
                            groundVelocity = velocity.x;
                        }
                        else
                        {
                            groundVelocity = velocity.y * Mathf.Sign(Mathf.Sin(currentGroundInfo.angle));
                        }
                    }

                    velocity.y = 0f;
                }
            }
        }

        if (grounded)
        {
            StickToGround(currentGroundInfo);
            animator.SetFloat(speedHash, Mathf.Abs(groundVelocity));

            lowCeiling = ceil.valid && transform.position.y > ceil.point.y - 25f;
        }
        else
        {
            currentGroundInfo = null;
            groundMode        = GroundMode.Floor;
            lowCeiling        = false;

            if (Mathf.Abs(input.x) > 0.005f && !(rolling && jumped))
            {
                Vector3 scale = Vector3.one;
                scale.x *= Mathf.Sign(input.x);
                transform.localScale = scale;
            }

            if (characterAngle > 0f && characterAngle <= 180f)
            {
                characterAngle -= Time.deltaTime * 180f;
                if (characterAngle < 0f)
                {
                    characterAngle = 0f;
                }
            }
            else if (characterAngle < 360f && characterAngle > 180f)
            {
                characterAngle += Time.deltaTime * 180f;
                if (characterAngle >= 360f)
                {
                    characterAngle = 0f;
                }
            }
        }
        animator.SetBool(spinHash, rolling || jumped);

        if (!underwater && transform.position.y <= waterLevel.position.y)
        {
            EnterWater();
        }
        else if (underwater && transform.position.y > waterLevel.position.y)
        {
            ExitWater();
        }

        transform.localRotation = Quaternion.Euler(0f, 0f, SnapAngle(characterAngle));
    }
예제 #3
0
    GroundInfo GroundedCheck(float distance, GroundMode groundMode, out bool groundedLeft, out bool groundedRight)
    {
        Quaternion rot          = Quaternion.Euler(0f, 0f, (90f * (int)groundMode));
        Vector2    dir          = rot * Vector2.down;
        Vector2    leftCastPos  = rot * leftRaycastPos;
        Vector2    rightCastPos = rot * rightRaycastPos;

        Vector2      pos     = new Vector2(transform.position.x, transform.position.y);
        RaycastHit2D leftHit = Physics2D.Raycast(pos + leftCastPos, dir, distance);

        groundedLeft = leftHit.collider != null;

        RaycastHit2D rightHit = Physics2D.Raycast(pos + rightCastPos, dir, distance);

        groundedRight = rightHit.collider != null;

        Debug.DrawLine(pos + leftCastPos, pos + leftCastPos + (dir * distance), Color.magenta);
        Debug.DrawLine(pos + rightCastPos, pos + rightCastPos + (dir * distance), Color.red);

        GroundInfo found = null;

        if (groundedLeft && groundedRight)
        {
            float leftCompare  = 0f;
            float rightCompare = 0f;

            switch (groundMode)
            {
            case GroundMode.Floor:
                leftCompare  = leftHit.point.y;
                rightCompare = rightHit.point.y;
                break;

            case GroundMode.RightWall:
                leftCompare  = -leftHit.point.x;
                rightCompare = -rightHit.point.x;
                break;

            case GroundMode.Ceiling:
                leftCompare  = -leftHit.point.y;
                rightCompare = -rightHit.point.y;
                break;

            case GroundMode.LeftWall:
                leftCompare  = leftHit.point.x;
                rightCompare = rightHit.point.x;
                break;

            default:
                break;
            }

            if (leftCompare >= rightCompare)
            {
                found = GetGroundInfo(leftHit);
            }
            else
            {
                found = GetGroundInfo(rightHit);
            }
        }
        else if (groundedLeft)
        {
            found = GetGroundInfo(leftHit);
        }
        else if (groundedRight)
        {
            found = GetGroundInfo(rightHit);
        }
        else
        {
            found = new GroundInfo();
        }

        return(found);
    }
    // Update is called once per frame
    void Update()
    {
        switch (mode)
        {
        case GroundMode.SHOP:
            RundenAusgabe.text = "Runde: " + (roundCounter + 1);
            if (shoppingTime < 0.0f)
            {
                shop.SetActive(false);
                stats.GetComponent <StatController>().revert();
                mode         = GroundMode.WAIT;
                shoppingTime = shoppingInterval;
            }
            else
            {
                shop.SetActive(true);
                shoppingTime         -= Time.deltaTime;
                countdownAusgabe.text = "Shop Zeit: " + Mathf.Floor(shoppingTime + 1).ToString();
            }
            break;

        case GroundMode.WAIT:
            if (countdown < 0.0f)
            {
                mode      = GroundMode.SHRINK;
                countdown = intervalTime;
            }
            else
            {
                countdown            -= Time.deltaTime;
                countdownAusgabe.text = Mathf.Floor(countdown + 1).ToString();
            }
            break;

        case GroundMode.SHRINK:
            countdownAusgabe.text = "Verkleinern";
            ground.localScale     = ground.localScale - scalingVec * Time.deltaTime;
            if (Vector2.Distance(new Vector2(ground.localScale.x, ground.localScale.z), scales[stage]) < scaleOffset)
            {
                stage++;
                if (stage >= scales.Length)
                {
                    mode = GroundMode.END;
                }
                else
                {
                    mode = GroundMode.WAIT;
                }
            }
            break;

        case GroundMode.END:
            ground.gameObject.SetActive(false);
            mode = GroundMode.SHOP;
            roundCounter++;
            stage = 0;
            ground.gameObject.SetActive(true);
            ground.localScale = new Vector3(1f, 10f, 1f);
            stats.GetComponent <StatController>().forceOpenStats();
            break;
        }
    }