private GameObject GetChunkPrefab(TrackChunk.ChunkType direction, int heightDiff) { GameObject result = null; if (direction == TrackChunk.ChunkType.STRAIGHT) { if (heightDiff == 0) { result = chunkPrefabs.chunkStraight; } else if (heightDiff == -1) { result = chunkPrefabs.chunkDown; } else if (heightDiff == 1) { result = chunkPrefabs.chunkUp; } } else if (direction == TrackChunk.ChunkType.CURVE_LEFT) { result = chunkPrefabs.chunkTurnLeft; } else if (direction == TrackChunk.ChunkType.CURVE_RIGHT) { result = chunkPrefabs.chunkTurnRight; } return(result); }
private void FinalizeCloseCircuit(HashSet <TrackNode> track, SearchNode endNode) { Stack <SearchNode> path = new Stack <SearchNode>(); SearchNode current = endNode; while (current != null) { path.Push(current); current = current.parent; } while (path.Count > 0) { SearchNode node = path.Pop(); SearchNode next = null; if (path.Count > 0) { next = path.Peek(); } int heightDiff = 0; TrackChunk.ChunkType chunkType = TrackChunk.ChunkType.STRAIGHT; if (next != null) { heightDiff = next.parentHeightDiff; chunkType = next.parentType; } TrackNode trackNode = new TrackNode(node.pos, node.rotation); trackNode.heightDiff = heightDiff; trackNode.chunkType = chunkType; track.Add(trackNode); trackOrderedChunks.Add(trackNode); } }
public void GenerateTrack() { difficulty = Mathf.Clamp01(difficulty); length = Mathf.Clamp(length, MIN_LENGTH, MAX_LENGTH); HashSet <TrackNode> nodes = new HashSet <TrackNode>(); // Start one block forward IntVector3 cursor = new IntVector3(); cursor.z = 1; float heightChangeProb = HEIGHT_CHANGE_PROB * difficulty; int remainingChunks = length; int currentRotation = 0; bool done = false; int firstStretchLen = 0; int countdown = INITIAL_GENERATION_TIMEOUT * length; while (!done) { if (countdown-- < 0) { throw new InvalidTrackException("Initial track generation timed out."); } int heightDiff = 0; TrackChunk.ChunkType direction = TrackChunk.ChunkType.STRAIGHT; if (firstStretchLen > FIRST_STRETCH_LEN) { if (rand.NextDouble() < heightChangeProb) { heightDiff = (rand.NextDouble() < 0.5 ? 1 : -1); } // Decide Direction if (heightDiff == 0 && rand.NextDouble() < DIRECTION_TURN_PROB * difficulty) { if (rand.NextDouble() < 0.5) { direction = TrackChunk.ChunkType.CURVE_LEFT; } else { direction = TrackChunk.ChunkType.CURVE_RIGHT; } } } firstStretchLen++; int nextRotation = currentRotation; // Update rotation if (direction == TrackChunk.ChunkType.CURVE_RIGHT) { nextRotation += 90; } else if (direction == TrackChunk.ChunkType.CURVE_LEFT) { nextRotation -= 90; } nextRotation = ClampRotation(nextRotation); IntVector3 nextPos = GetNextPoint(cursor, nextRotation, 0); if (HasNodeAt(nodes, nextPos)) { continue; } if (heightDiff == 0) { IntVector3 nextPosUp = GetNextPoint(cursor, nextRotation, 1); IntVector3 nextPosDown = GetNextPoint(cursor, nextRotation, -1); if (HasNodeAt(nodes, nextPosUp) || HasNodeAt(nodes, nextPosDown)) { continue; } } else { IntVector3 nextPosHDiff = GetNextPoint(cursor, nextRotation, heightDiff); if (HasNodeAt(nodes, nextPosHDiff)) { continue; } } nextPos.y += heightDiff; TrackNode node = new TrackNode(cursor, currentRotation); node.chunkType = direction; node.heightDiff = heightDiff; nodes.Add(node); trackOrderedChunks.Add(node); currentRotation = nextRotation; cursor = nextPos; if (firstStretchLen > FIRST_STRETCH_LEN) { remainingChunks--; } if (remainingChunks == 0) { done = true; } } // Now, close the circuit bool ok = CloseCircuit(nodes, cursor, currentRotation); // Instance prefabs List <TrackChunk> instancedChunks = InstanceChunkClones(trackOrderedChunks); if (!ok) { throw new InvalidTrackException("A* pathfinding timed out."); } else { RacingTrack rt = trackBase.AddComponent <RacingTrack>(); rt.trackChunks = instancedChunks; rt.startChunk = instancedChunks[0]; rt.endChunk = instancedChunks[instancedChunks.Count - 1]; } }