public bool IsGrounded()
    {
        if (groundInfos == null)
            groundInfos = new GroundInfo ();

        groundInfos.isGrounded = false;
        groundInfos.ground = null;

        RaycastHit2D hit = Physics2D.Raycast (CachedRigidbody.position, Vector3.down, 0.8f, groundLayers.value);

        if(hit.transform != null)
        {
            groundInfos.ground = hit.transform;
            groundInfos.isGrounded = true;
        }

        return groundInfos.isGrounded;
    }
        public void SetPos(Vector3 pos)
        {
            //清空已有资源
            for (int i = 0; i < m_rendererList.Count; i++)
            {
                GameObjectManager.DestroyGameObjectByPool(m_rendererList[i].gameObject);
            }
            m_rendererList.Clear();

            //计算出应该是哪几个资源
            //计算出对应的位置
            //加载并摆放

            m_offset = pos * scrollSpeed;
            //限制区域
            int  index   = 0;
            bool isBreak = false;
            bool isShow  = false;

            while (!isBreak)
            {
                GroundInfo info = GetGroundInfo(index);
                if (m_root.ViewBound.Overlaps(info.rect))
                {
                    isShow = true;
                    //加载对应资源并摆放
                    CreateSprite(info);
                }
                else
                {
                    //已经显示过,后面的不在显示区域中终止循环
                    if (isShow)
                    {
                        isBreak = true;
                    }
                }
                index++;
            }
        }
Esempio n. 3
0
        public GoundMaker(GroundInfo info,
                          IFactory <SceneContext> scFactory,
                          IFactory <SceneContext, UnityEngine.Object, Player> playerFactory,
                          IFactory <Canvas> uiFactory,
                          [Inject(Id = "start")]
                          IFactory <int, int, GameObject> startFactory,
                          [Inject(Id = "exit")]
                          IFactory <int, int, GameObject> exitFactory,
                          [Inject(Id = "floor")]
                          IFactory <int, int, UnityEngine.Object, IEnumerable <GameObject> > floorFactory,
                          [Inject(Id = "wall")]
                          IFactory <int, int, UnityEngine.Object, IEnumerable <GameObject> > wallFactory)
        {
            _info = info;

            _scFactory     = scFactory;
            _playerFactory = playerFactory;
            _uiFactory     = uiFactory;

            _startFactory = startFactory;
            _exitFactory  = exitFactory;
            _floorFactory = floorFactory;
            _wallFactory  = wallFactory;
        }
Esempio n. 4
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;
    }
Esempio n. 5
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);
    }
Esempio n. 6
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));
    }
Esempio n. 7
0
            /* Try and guess ground positions across an image */
            public List <GroundInfo> GuessGroundPositions(Image sphere, int acc, bool straight, StraightLineBias bias)
            {
                //Work out the classifier between ground and sky
                float skyClassifier    = TakeAverageBrightness(sphere.Height / 6, (Bitmap)sphere);
                float groundClassifier = TakeAverageBrightness(sphere.Height - (sphere.Height / 6), (Bitmap)sphere);
                float diffClassifier   = skyClassifier - groundClassifier;

                //First pass of ground position guess, check every column
                List <GroundInfo> positions = new List <GroundInfo>();
                int posOffset = 0;

                for (int i = 0; i < sphere.Width; i++)
                {
                    GroundInfo thisGround = new GroundInfo();
                    thisGround.position    = GuessGroundPositionForX(posOffset, (Bitmap)sphere, diffClassifier);
                    thisGround.block_width = 1;
                    positions.Add(thisGround);
                    posOffset += thisGround.block_width;
                }
                positions = positions.OrderBy(o => o.position.x).ToList();

                //Discredit any outliers on first pass
                List <GroundInfo> positions_new = new List <GroundInfo>();
                int prevDiscredit = 0;
                int checkRadius   = 1;

                for (int i = checkRadius; i < positions.Count - checkRadius; i++)
                {
                    if (positions_new.Count != 0)
                    {
                        float prevDif = positions[i].position.y - positions[i - checkRadius].position.y;
                        if (prevDif < 0)
                        {
                            prevDif *= -1;
                        }
                        float nextDif = positions[i].position.y - positions[i + checkRadius].position.y;
                        if (nextDif < 0)
                        {
                            nextDif *= -1;
                        }
                        if (prevDif >= 50 || nextDif >= 50) //todo dont use a set value here, do it by sphere height
                        {
                            prevDiscredit++;
                            continue;
                        }
                        positions_new[positions_new.Count - 1].block_width += prevDiscredit;
                    }
                    positions_new.Add(positions[i]);
                    prevDiscredit = 0;
                }
                positions = positions_new;

                //Second/third pass, get average of blocks from first pass, remove any outliers again, recalculate average
                positions_new = new List <GroundInfo>();
                for (int i = 1; i < positions.Count / acc; i++)
                {
                    int          startPos = acc * (i - 1);
                    int          endPos   = acc * (i);
                    List <float> yPos     = new List <float>();
                    float        avgY     = 0.0f;
                    float        avgX     = 0.0f;
                    for (int x = startPos; x < endPos; x++)
                    {
                        yPos.Add(positions[x].position.y);
                        avgY += positions[x].position.y;
                        avgX += positions[x].position.x;
                    }
                    avgY /= acc;
                    avgX /= acc;
                    float avgY2    = 0.0f;
                    int   avgCount = 0;
                    for (int x = 0; x < yPos.Count; x++)
                    {
                        if (yPos[x] >= avgY)
                        {
                            avgY2 += yPos[x];
                            avgCount++;
                        }
                    }
                    avgY2 /= avgCount;
                    GroundInfo newGndInf = new GroundInfo();
                    newGndInf.block_width = acc;
                    newGndInf.position    = new Vector2(avgX, avgY2);
                    positions_new.Add(newGndInf);
                }
                positions = positions_new;

                //If requested to trim as a straight line, take an average of all points, or pick top/bottom
                if (straight)
                {
                    float avgY = 0.0f;
                    switch (bias)
                    {
                    case StraightLineBias.TOP:
                        avgY = float.MaxValue;
                        for (int i = 0; i < positions.Count; i++)
                        {
                            if (avgY >= positions[i].position.y)
                            {
                                avgY = positions[i].position.y;
                            }
                        }
                        break;

                    case StraightLineBias.MIDDLE:
                        for (int i = 0; i < positions.Count; i++)
                        {
                            avgY += positions[i].position.y;
                        }
                        avgY /= positions.Count;
                        break;

                    case StraightLineBias.BOTTOM:
                        for (int i = 0; i < positions.Count; i++)
                        {
                            if (avgY <= positions[i].position.y)
                            {
                                avgY = positions[i].position.y;
                            }
                        }
                        break;
                    }
                    positions.Clear();
                    GroundInfo avgPos = new GroundInfo();
                    avgPos.block_width = sphere.Width / 2;
                    avgPos.position    = new Vector2(0.0f, avgY);
                    positions.Add(avgPos);
                    avgPos.position = new Vector2(sphere.Width / 2, avgY);
                    positions.Add(avgPos);
                }
                return(positions);
            }
Esempio n. 8
0
    GroundInfo groundInfo;                                                  //地面端の位置クラス

    private void Start()
    {
        groundInfo = GetComponentInParent <GroundInfo>();
    }