Ejemplo n.º 1
0
    public SplineTransformData CalculateAproxSplineTransformData(float i_splineVal)
    {
        SplineTransformData data = new SplineTransformData();

        //Convert sline val to worldspace distance
        float distTravelled = i_splineVal * Length;

        //Walk the spline this distance
        int     lastIndex = 0;
        float   distTotal = 0;
        float   distSeg   = 0;
        Vector3 prevPos   = m_splinePoints[0].transform.position;
        Vector3 fwd       = Vector3.forward;

        bool walkDone = false;

        for (int j = 0; j < m_splinePoints.Length && !walkDone; ++j)
        {
            distSeg = 0;
            Vector3 p0 = m_splinePoints[ClampIndex(j - 1)].transform.position;
            Vector3 p1 = m_splinePoints[j].transform.position;
            Vector3 p2 = m_splinePoints[ClampIndex(j + 1)].transform.position;
            Vector3 p3 = m_splinePoints[ClampIndex(j + 2)].transform.position;

            prevPos = p1;
            //Walk along the spline from p1 to p2, incrementing the time value
            for (int i = 0; i < (int)(1f / m_segmentLengthDelta) && !walkDone; ++i)
            {
                float t = (i + 1) * m_segmentLengthDelta;

                Vector3 curPos = GetIntraSegmentPos(m_segments[j], t);
                float   dist   = Vector3.Magnitude(curPos - prevPos);
                fwd        = Vector3.Normalize(curPos - prevPos);
                distTotal += dist;
                distSeg   += dist;
                if (distTotal >= distTravelled)
                {
                    walkDone = true;
                }
                prevPos = curPos;
            }

            if (!walkDone)
            {
                lastIndex = j;
            }
        }


        //We know the last index, and how far ahead we are to the next, interpolate that shid baby
        float segVal = Mathf.Min(distSeg / m_segments[lastIndex].m_length, 1);

        data.m_worldPos = prevPos;
        data.m_worldFwd = fwd;
        data.m_worldUp  = Vector3.Lerp(m_segments[lastIndex].m_startUp, m_segments[lastIndex].m_endUp, segVal);

        return(data);
    }
Ejemplo n.º 2
0
        private IEnumerator GeneratePuzzle(IPuzzleGenerator i_puzzleGeneratorIF, float i_difficulty, float i_startingSplineT, float i_startingSplineTClamped)
        {
            PuzzleData puzzleData = i_puzzleGeneratorIF.GeneratePuzzle(m_trackWidthInCells, i_difficulty, m_forwardCellsPerSideways);

            AddRandomStuff(puzzleData, i_difficulty);
            SplineTransformData puzzleStartTransformData = m_spline.CalculateAproxSplineTransformData(i_startingSplineTClamped);

            Vector2Int gridSize = new Vector2Int(puzzleData.Width, puzzleData.Height);

            SpawnedPuzzle spawnedPuzzleData = new SpawnedPuzzle();

            spawnedPuzzleData.m_spawnedObjects     = new GameObject[gridSize.x, gridSize.y];
            spawnedPuzzleData.m_startPuzzleHeight  = m_runningDistancePS;
            spawnedPuzzleData.m_endPuzzleHeight    = m_runningDistancePS + puzzleData.Height;
            spawnedPuzzleData.m_puzzleData         = puzzleData;
            spawnedPuzzleData.m_startTransformData = puzzleStartTransformData;
            m_spawnedPuzzles.Enqueue(spawnedPuzzleData);

            float GetT(int i_y)
            {
                return((i_startingSplineTClamped + i_y * m_trackTPerCell) % 1f);
            }

            // Work out if we need to offset the starting spline T
            float trackLength   = m_spline.Length;
            float puzzleTLength = (puzzleData.Height * m_cellSize) / trackLength;
            float totalAddedT   = 0f;

            while (!m_spline.DoesTRangeSupportPuzzles(i_startingSplineT, i_startingSplineT + puzzleTLength, out float nextValidT))
            {
                totalAddedT             += (nextValidT - i_startingSplineT);
                i_startingSplineT        = nextValidT;
                i_startingSplineTClamped = i_startingSplineT % 1f;
                yield return(0);
            }

            m_runningDistancePS += Mathf.CeilToInt(totalAddedT * trackLength / m_cellSize);

            // Lets figure out wtf we need to spawn this crap
            for (int y = 0; y < puzzleData.Height; ++y)
            {
                // Every time we go up one we need to find our new transform info
                float splineT = GetT(y);
                SplineTransformData splineTransformData = m_spline.CalculateAproxSplineTransformData(splineT);

                int timesAroundTrack = Mathf.FloorToInt(i_startingSplineT);
                if (timesAroundTrack % 2 == 1) // If odd, flip
                {
                    splineTransformData.m_worldUp = -splineTransformData.m_worldUp;
                }
                m_splineTransformsCalulated.Add(splineTransformData);

                Vector3    puzzleLeftPos  = splineTransformData.m_worldPos - (Vector3.Cross(splineTransformData.m_worldUp.normalized, splineTransformData.m_worldFwd.normalized) * m_cellSize * (m_trackWidthInCells - 1) / 2f);
                Quaternion objectRotation = Quaternion.LookRotation(splineTransformData.m_worldFwd.normalized, splineTransformData.m_worldUp.normalized);

                for (int x = 0; x < puzzleData.Width; ++x)
                {
                    PuzzleCell cell = puzzleData.GetCell(x, y);
                    if (cell.m_prefabToSpawn != null)
                    {
                        Vector3    positionToSpawn = puzzleLeftPos + (objectRotation * new Vector3(x * m_cellSize, 0, 0));
                        Quaternion rotationToSpawn = objectRotation;

                        // Adjust because the track isn't actually flat all the way along

                        // Lift above the track
                        Vector3 raycastFrom = positionToSpawn + splineTransformData.m_worldUp * m_upwardProjectionLengthBeforeDownwardRaycast;

                        if (Physics.Raycast(new Ray(raycastFrom, -splineTransformData.m_worldUp), out RaycastHit hit, m_downwardRaycastLength, m_trackLayer))
                        {
                            // Adjust
                            positionToSpawn = hit.point;
                            rotationToSpawn = Quaternion.LookRotation(splineTransformData.m_worldFwd.normalized, hit.normal.normalized);
                        }

                        spawnedPuzzleData.m_spawnedObjects[x, y] = Instantiate(cell.m_prefabToSpawn, positionToSpawn, cell.m_prefabRotation * rotationToSpawn, transform);
                        spawnedPuzzleData.m_spawnedObjects[x, y].transform.localScale *= m_modelScaler;
                    }
                }

                yield return(0);
            }

            // Link
            for (int x = 0; x < puzzleData.Width; ++x)
            {
                for (int y = 0; y < puzzleData.Height; ++y)
                {
                    PuzzleCell cell = puzzleData.GetCell(x, y);
                    if (cell.m_cellsToLinkTo != null)
                    {
                        foreach (Vector2Int cellCoords in cell.m_cellsToLinkTo)
                        {
                            GameObject objectToLinkFrom = spawnedPuzzleData.m_spawnedObjects[x, y];
                            GameObject objectToLinkTo   = spawnedPuzzleData.m_spawnedObjects[cellCoords.x, cellCoords.y];
                            foreach (IActivator activator in objectToLinkFrom.GetComponents <IActivator>())
                            {
                                foreach (IActivatee activatee in objectToLinkTo.GetComponents <IActivatee>())
                                {
                                    activator.AssignActivee(activatee);
                                }
                            }
                        }
                    }
                }
            }
        }