public GUIRiver(GUIManager gm) { this.gm = gm; menuWidth = gm.menuWidth; rightMenuOffset = gm.rightOffset; topOffset = gm.topOffset; buttonHeight = gm.smallButtonHeight; sideOffset = 10; scaleY = gm.scaleY; visibleArea = gm.visibleArea; rg = gm.cm.riverGenerator; rg.riverGui = this; riverFlags = new List<bool>(); //width = 15; //areaEffect = 1; //depth = 0.2f; defaultRiver = new RiverInfo(rg); defaultRiver.SetDefaultValues(); selectedRiver = defaultRiver; }
/// <summary> /// generates rivers starting from given river's starting and ending point /// operation is processed only if points are in visible terrain and not on border /// => meaning that terrain has been moved and river isn't complete /// </summary> public void GenerateConnectingRiver(RiverInfo river) { Vertex startPoint = river.riverPath[0]; if (ftm.IsInDefinedTerrain(startPoint) && !ftm.IsOnBorder(startPoint)) { Area restrictArea = fmc.CalculateRestrictedArea(startPoint); List<Direction> reachedSides = new List<Direction>(); reachedSides.Add(fmc.GetOppositeDirection(startPoint.side)); RiverInfo startRiver = frp.GetRiverFrom(startPoint, reachedSides, restrictArea, river, river.gridStep, true); if(startRiver.riverPath.Count == 0) { ShowErrorMessage("connecting river failed \n" + startRiver.errorMessage); } frd.DistortPath(startRiver.riverPath, startRiver.gridStep/3, startRiver.gridStep); river.ConnectWith(startRiver); startPoint.side = Direction.none; } Vertex endPoint = river.GetLastVertex(); if (ftm.IsInDefinedTerrain(endPoint) && !ftm.IsOnBorder(endPoint)) { Area restrictArea = fmc.CalculateRestrictedArea(endPoint); List<Direction> reachedSides = new List<Direction>(); reachedSides.Add(fmc.GetOppositeDirection(endPoint.side)); RiverInfo endRiver = frp.GetRiverFrom(endPoint, reachedSides, restrictArea, river, river.gridStep, true); if (endRiver.riverPath.Count == 0) { ShowErrorMessage("connecting river failed \n" + endRiver.errorMessage); } frd.DistortPath(endRiver.riverPath, endRiver.gridStep / 3, endRiver.gridStep); river.ConnectWith(endRiver); endPoint.side = Direction.none; } frd.DigRiver(river); }
public void AssignFunctions(RiverGenerator rg) { this.rg = rg; fd = rg.fd; ftm = rg.ftm; fmc = rg.fmc; frd = rg.frd; errorRiver = new RiverInfo(rg); errorRiver.errorMessage = "-"; terrainWidth = rg.lt.terrainWidth; terrainHeight = rg.lt.terrainHeight; }
//***********<RIVER...>************* public RiverGenerator(TerrainGenerator terrain) { this.terrain = terrain; filtermanager = terrain.filterManager; terrain.riverGenerator = this; vertices = terrain.vertices; terrainSize = terrain.terrainSize; heightMap = terrain.heightMap; frp = new FunctionRiverPlanner(this); frd = new FunctionRiverDigger(this); fmc = new FunctionMathCalculator(this); ftm = new FunctionTerrainManager(this); fd = new FunctionDebugger(this); currentRiver = new RiverInfo(terrain); AssignFunctions(); }
//connect 2 rivers into 1 public void ConnectWith(RiverInfo river2) { if (riverPath[0].EqualsCoordinates(river2.riverPath[0])) { river2.riverPath.RemoveAt(0); riverPath.Reverse(); riverPath.AddRange(river2.riverPath); //riverPath.Reverse(); } else if (GetLastVertex().EqualsCoordinates(river2.riverPath[0])) { river2.riverPath.RemoveAt(0); riverPath.AddRange(river2.riverPath); } else if (riverPath[0].EqualsCoordinates(river2.GetLastVertex())) { riverPath.RemoveAt(0); riverPath.Reverse(); river2.riverPath.Reverse(); riverPath.AddRange(river2.riverPath); riverPath.Reverse(); } else if (GetLastVertex().EqualsCoordinates(river2.GetLastVertex())) { river2.riverPath.RemoveAt(river2.riverPath.Count - 1); river2.riverPath.Reverse(); riverPath.AddRange(river2.riverPath); } else { Debug.Log("RIVERS DONT HAVE COMMON END POINT"); } //reachTop = reachTop || river2.reachTop; //reachRight = reachRight || river2.reachRight; //reachBot = reachBot || river2.reachBot; //reachLeft = reachLeft || river2.reachLeft; }
/// <summary> /// digs river path /// </summary> /// <param name="width">width of river corridor</param> /// <param name="widthFactor">also "areaEffect". defines area around river. 1 = only river, 2 = river and close area</param> /// <param name="maxDepth">depth in center of river</param> public void DigRiver(RiverInfo river, int width, float widthFactor, float maxDepth) { //optimize areaEffect if (widthFactor > 1 && widthFactor < 1.5f) widthFactor = 1; else if (widthFactor >= 1.5) widthFactor = 2; widthFactor = 2; //DigCorners(path, width, widthFactor, maxDepth); currentRiver = river; List<Vertex> path = river.riverPath; if(path.Count < 2) { Debug.Log("path too short: " + path.Count); return; } DigRiverPath(path, width, widthFactor, maxDepth, river.shape); DigCorners(path, width, widthFactor, maxDepth, river.shape); }
public void GenerateDefaultRiver() { int w = 20; List<Vertex> tempList = new List<Vertex>(); tempList.Add(new Vertex(0, -lt.terrainHeight/2 + 5)); tempList.Add(new Vertex(w, -w)); tempList.Add(new Vertex(0, 0)); tempList.Add(new Vertex(w, w)); tempList.Add(new Vertex(0, lt.terrainHeight / 2 - 5)); RiverInfo river = new RiverInfo(this); river.riverPath = tempList; frd.DistortPath(river.riverPath, river.gridStep / 3, river.gridStep); river.width = 15; river.areaEffect = 2; river.depth = 0.15f; rivers.Add(river); Debug.Log(riverGui); riverGui.riverFlags.Add(true); frd.DigRiver(rivers[rivers.Count - 1]); }
/// <summary> /// find river path from given starting point on restricted area /// </summary> /// <param name="start">starting point</param> /// <param name="reachedSides">sideas already reached - result path can't end on any of these these sides</param> /// <param name="x_min">area restriction</param> /// <param name="x_max">area restriction</param> /// <param name="z_min">area restriction</param> /// <param name="z_max">area restriction</param> /// <returns></returns> public RiverInfo GetRiverPathFrom(Vertex start, List<Direction> reachedSides, int x_min, int x_max, int z_min, int z_max) { fd.ColorPixel(start.x, start.z, 5, redColor); float step = Math.Abs(start.height); //height can be negative if (step <= 0.1f) //step can't be too small step = 0.1f; else if (step > 0.1f) //step can't be too big step = 0.1f; Vertex highestPoint = ftm.GetHighestpoint(); float maxThreshold = highestPoint.height; //highest value on map - river can't flow that heigh fd.ColorPixel(highestPoint.x, highestPoint.z, 5, blueColor); //Debug.Log(highestPoint); List<FloodNode> reachableNodes = new List<FloodNode>(); reachableNodes.Add(new FloodNode(start, 0)); float threshold = start.height + step; Debug.Log("threshold: " + threshold); Debug.Log("terrainSize: " + terrainSize); int gridStep = 20; //step between river path points int borderOffset = gridStep + 5; //bool reachedSide = false; Direction reachedSide = Direction.none; int finalIndex = 0;//index of final node (reached one of the sides) while (reachedSide == Direction.none) { for (int i = 0; i < reachableNodes.Count; i++) { //Debug.Log(i + " - threshold: " + threshold); FloodNode currentNode = reachableNodes[i]; if (!currentNode.processed) { int x = currentNode.vertex.x; int z = currentNode.vertex.z; //if (i < 100) // Debug.Log(i + ":" + currentNode); if (ftm.CheckBounds(x, z, 0, x_min, x_max, z_min, z_max)) { //if(i < 100) // Debug.Log(currentNode); //check if node is not on side that has already been reached bool reachedAvailableSide = fmc.ReachedAvailableSide(x, z, reachedSides, borderOffset, x_min, x_max, z_min, z_max); if (reachedAvailableSide) { reachedSide = fmc.GetReachedSide(x, z, borderOffset, x_min, x_max, z_min, z_max); if (reachedSide != Direction.none) { Debug.Log("!!!!!!!!!!"); finalIndex = i; break; } if (x > 150) { Debug.Log(x_min); Debug.Log(x_max); Debug.Log(z_min); Debug.Log(z_max); Debug.Log(reachedSide); Debug.Log(currentNode); } } if (reachedSide != Direction.none) { Debug.Log("????"); break; } } if (reachedSide != Direction.none) { Debug.Log("KKKKK"); break; } //dont process already processed nodes again if (!currentNode.processed) { if (i > terrainSize * terrainSize) { Debug.Log("FAIL"); finalIndex = i; reachedSide = Direction.up; break; } List<Vertex> neighbours = ftm.Get8Neighbours(currentNode.vertex, gridStep, 0, threshold, x_min, x_max, z_min, z_max); if (neighbours.Count == 8) { currentNode.processed = true; } foreach (Vertex v in neighbours) { if (v.height < threshold && !reachableNodes.Contains(new FloodNode(v, i))) { reachableNodes.Add(new FloodNode(v, i)); } } } else { //Debug.Log("skip " + i); } } if (reachedSide != Direction.none) { Debug.Log("MMM"); break; } } if (reachedSide != Direction.none) { Debug.Log("JJJJ"); break; } threshold += step; if (threshold > maxThreshold) { Debug.Log("step=" + step); Debug.Log("max=" + maxThreshold); Debug.Log("FAILz"); break; } } int pathIndex = finalIndex; List<Vertex> finalPath = new List<Vertex>(); finalPath.Add(fmc.GetVertexOnBorder(reachableNodes[finalIndex].vertex, borderOffset, reachedSide, x_min, x_max, z_min, z_max)); //add new node which lies exactly on border while (pathIndex != 0)//recursively add all vertices of found path { finalPath.Add(reachableNodes[pathIndex].vertex); pathIndex = reachableNodes[pathIndex].parentIndex; } finalPath.Reverse(); for (int i = 0; i < finalPath.Count; i++) { Debug.Log(finalPath[i]); } RiverInfo river = new RiverInfo(rg.terrain); river.riverPath = finalPath; reachedSides.Add(reachedSide); foreach(Direction side in reachedSides) { switch (reachedSide) { case Direction.up: river.reachTop = true; break; case Direction.right: river.reachRight = true; break; case Direction.down: river.reachBot = true; break; case Direction.left: river.reachLeft = true; break; } } return river; }
public void OnGui(int yPosition) { Color origColor = GUI.color; float buttonWidth = menuWidth - sideOffset - sideOffset / 2; float buttonWidth2 = menuWidth / 2 - sideOffset - sideOffset / 2; yPos = yPosition; if (GUI.Button(new Rect(Screen.width - menuWidth, yPos, menuWidth - rightMenuOffset, buttonHeight), "Generate new river")) { rg.GenerateNewRiver(selectedRiver.width, selectedRiver.areaEffect, selectedRiver.depth, selectedRiver.gridStep); gm.cm.terrainGenerator.build(); } yPos += buttonHeight + 5; GUI.Box(new Rect(Screen.width - menuWidth, yPos, menuWidth - rightMenuOffset, 6f * buttonHeight), "parameters"); yPos += buttonHeight + 2; GUI.Label(new Rect(Screen.width - menuWidth + sideOffset, yPos, buttonWidth2, buttonHeight), "width: " + (int)selectedRiver.width); selectedRiver.width = GUI.HorizontalSlider(new Rect( Screen.width - menuWidth + buttonWidth2, yPos + 5, menuWidth - sideOffset - buttonWidth2 - 5, buttonHeight), selectedRiver.width, 8f, 20f); yPos += buttonHeight + 2; GUI.Label(new Rect(Screen.width - menuWidth + sideOffset, yPos, buttonWidth2, buttonHeight), "depth: " + (int)selectedRiver.depth + "." + (int)((selectedRiver.depth - (int)selectedRiver.depth) * 100)); selectedRiver.depth = GUI.HorizontalSlider(new Rect( Screen.width - menuWidth + buttonWidth2, yPos + 5, menuWidth - sideOffset - buttonWidth2 - 5, buttonHeight), selectedRiver.depth, 0, 0.2f); yPos += buttonHeight + 2; GUI.Label(new Rect(Screen.width - menuWidth + sideOffset, yPos, buttonWidth2, buttonHeight), "step: " + selectedRiver.gridStep); selectedRiver.gridStep = (int)GUI.HorizontalSlider(new Rect( Screen.width - menuWidth + buttonWidth2, yPos + 5, menuWidth - sideOffset - buttonWidth2 - 5, buttonHeight), selectedRiver.gridStep, 10, 50); yPos += buttonHeight + 2; if (GUI.Button(new Rect(Screen.width - menuWidth + sideOffset, yPos, buttonWidth / 2 - 5, buttonHeight), "sinc()")) { selectedRiver.shape = RiverShape.sinc; RedigRiver(selectedRiver); } if (GUI.Button(new Rect(Screen.width - menuWidth + sideOffset + buttonWidth/2, yPos, buttonWidth / 2 - 5, buttonHeight), "aTan()")) { selectedRiver.shape = RiverShape.atan; RedigRiver(selectedRiver); } yPos += buttonHeight + 10; GUI.Box(new Rect(Screen.width - menuWidth, yPos, menuWidth - rightMenuOffset, 11 * buttonHeight), "rivers"); yPos += buttonHeight; for(int i = 0; i < riverFlags.Count;i++) { bool riverFlag = riverFlags[i]; riverFlag = GUI.Toggle(new Rect(Screen.width - menuWidth + sideOffset, yPos, sideOffset, buttonHeight), riverFlags[i], ""); if (riverFlag != riverFlags[i]) { riverFlags[i] = riverFlag; //Debug.Log(i + ":" + riverFlag); gm.cm.terrainGenerator.build(); } //GUI.Label(new Rect(Screen.width - menuWidth + 3 * sideOffset, yPos, buttonWidth/3, buttonHeight), "river " + i); if(selectedRiver == rg.rivers[i]) { GUI.color = Color.green; } if (GUI.Button(new Rect(Screen.width - menuWidth + 3 * sideOffset, yPos, buttonWidth / 2, buttonHeight), "river" + i)) { selectedRiver = rg.rivers[i]; } if (GUI.Button(new Rect(Screen.width - menuWidth + 7 * sideOffset + buttonWidth / 3, yPos, 3 * sideOffset, buttonHeight), "O")) { selectedRiver = rg.rivers[i]; RedigRiver(selectedRiver); //selectedRiver.DrawRiver(); } if (GUI.Button(new Rect(Screen.width - menuWidth + 10 * sideOffset + buttonWidth/3, yPos, 3*sideOffset, buttonHeight), "X")) { if(i != 0) { selectedRiver = rg.rivers[i]; } else //reset to default values { defaultRiver.SetDefaultValues(); selectedRiver = defaultRiver; } rg.DeleteRiverAt(i); gm.cm.terrainGenerator.build(); } GUI.color = origColor; yPos += buttonHeight + 5; } }
/// <summary> /// resets river dig-map /// build again with current parameters /// </summary> private void RedigRiver(RiverInfo river) { river.globalRiverC.ResetQuadrants(); rg.frd.DigRiver(river); gm.cm.terrainGenerator.build(); }
/// <summary> /// digs river with default values /// </summary> public void DigRiver(RiverInfo river) { //DigRiver(river, 15, 1, 0.6f); DigRiver(river, (int)river.width, river.areaEffect, river.depth); }
public void OptimizeRiverCorners(RiverInfo river) { List<Vertex> path = river.riverPath; int gridStep = river.gridStep; for (int i = path.Count - 1; i > 1; i--) { if (fmc.GetDistance(path[i], path[i -2]) <= (gridStep+1)) { Debug.Log("remove: " + path[i-1]); path.RemoveAt(i-1); } } }
public RiverInfo GetRiverFromTo(Vertex start, Vertex end) { Debug.Log("getting river from " + start + " to " + end); int gridStep = 20; float e = 0.2f; List<Vertex> path = GetRiverPathFromTo(start, end, gridStep, e, 0); RiverInfo river = new RiverInfo(rg); river.riverPath = path; river.gridStep = gridStep; river.threshold = Mathf.Max(start.height + e, end.height + e); //SimplifyRiver(river, 3); //SimplifyRiver(river, 1); return river; }
/// <summary> /// returns river value on given local coordiantes (0 if not defined) /// </summary> public float GetLocalValue(RiverInfo river, int x, int z) { float value = localCoordinates.GetLocalValue(x, z, river.globalRiverC); if (value != 666) return value; else return 0; }
/// <summary> /// removes all unnecessary nodes from river /// </summary> /// <param name="river"></param> public void SimplifyRiver(RiverInfo river, int maxReduction) { List<Vertex> path = river.riverPath; int gridStep = river.gridStep; int reduction; for (int i = 0; i < path.Count - 2; i++) { reduction = 0; Vertex next = path[i + 2]; while(reduction < maxReduction && i < path.Count - 3 && ftm.IsOnContour(path[i], next, river.threshold)) //if (fmc.GetDistance(path[i], path[i+2]) < 2* gridStep)//corner detected { Debug.Log(i + " remove: " + path[i+1] + ", left: " + (path.Count-1)); path.RemoveAt(i+1); next = path[i + 2]; reduction++; } } }
/// <summary> /// adds new river to the river list and riverFlag to river GUI menu /// </summary> public void AddRiver(RiverInfo river) { rivers.Add(river); riverGui.riverFlags.Add(true); }
/// <summary> /// find river path from given starting point on restricted area /// forceRiver = generates river even on not very suitable terrain /// used when generating connecting river /// </summary> public RiverInfo GetRiverFrom(Vertex start, List<Direction> reachedSides, Area restrictedArea, RiverInfo ignoreRiver, int gridStep, bool forceRiver) { float step = Math.Abs(start.height); //height can be negative int x_min = restrictedArea.botLeft.x; int z_min = restrictedArea.botLeft.z; int x_max = restrictedArea.topRight.x; int z_max = restrictedArea.topRight.z; if (step <= 0.1f) //step can't be too small step = 0.1f; else if (step > 0.1f) //step can't be too big step = 0.1f; Vertex highestPoint = ftm.GetHighestpoint(x_min, z_min, x_max, z_max); float maxThreshold = highestPoint.height; //highest value on map - river can't flow that heigh List<FloodNode> reachableNodes = new List<FloodNode>(); reachableNodes.Add(new FloodNode(start, 0)); float threshold = start.height + step; int borderOffset = gridStep + 5; Direction reachedSide = Direction.none; int finalIndex = 0;//index of final node (reached one of the sides) while (reachedSide == Direction.none) { for (int i = 0; i < reachableNodes.Count; i++) { FloodNode currentNode = reachableNodes[i]; if (!currentNode.processed) { int x = (int)currentNode.vertex.x; int z = (int)currentNode.vertex.z; if (rg.IsRiverDefined(x,z) && rg.GetRiverOn(x, z) != ignoreRiver && !ignoreRiver.riverPath.Contains(currentNode.vertex) && !reachedSides.Contains(Direction.river)) { reachedSide = Direction.river; currentNode.vertex.side = Direction.river; finalIndex = i; break; } reachedSide = fmc.GetReachedSide(x, z, borderOffset, x_min, z_min, x_max, z_max); if (reachedSide != Direction.none) { //check if node is not on side that has already been reached bool reachedAvailableSide = fmc.ReachedAvailableSide(x, z, reachedSides, borderOffset, x_min, z_min, x_max, z_max); if (reachedAvailableSide) { finalIndex = i; currentNode.vertex.side = reachedSide; break; } else { reachedSide = Direction.none; } if (reachedSide != Direction.none) { Debug.Log("????"); break; } } if (reachedSide != Direction.none) { break; } //dont process already processed nodes again if (!currentNode.processed) { if (i > terrainWidth* terrainHeight) { Debug.Log("FAIL"); errorRiver.errorMessage = "FAIL - algorithm timeout"; return errorRiver; } List<Vertex> neighbours = ftm.GetGlobal8Neighbours(currentNode.vertex, gridStep, 0, threshold, x_min, x_max, z_min, z_max); if (neighbours.Count == 8) { currentNode.processed = true; } foreach (Vertex v in neighbours) { if (v.height < threshold && !rg.IsRiverDefined(v.x, v.z) && !reachableNodes.Contains(new FloodNode(v, i)) || //normal node !reachedSides.Contains(Direction.river) && rg.IsRiverDefined(v.x, v.z) && //river node !ignoreRiver.riverPath.Contains(v)) { reachableNodes.Add(new FloodNode(v, i)); } } } } if (reachedSide != Direction.none) { break; } } if (reachedSide != Direction.none) { break; } threshold += step; if(!forceRiver && threshold > rg.riverLevel + 2 * step) { Debug.Log("threshold too high: " + threshold); errorRiver.errorMessage = "RIVER FAIL\n reached max threshold: " + threshold; return errorRiver; } if (threshold > maxThreshold) { Debug.Log("step=" + step); Debug.Log("max=" + maxThreshold); errorRiver.errorMessage = "RIVER FAIL\n reached max threshold: " + threshold; return errorRiver; } } int pathIndex = finalIndex; List<Vertex> finalPath = new List<Vertex>(); if (reachedSide == Direction.river) { Vertex lastVertex = reachableNodes[pathIndex].vertex; reachableNodes[pathIndex].vertex.side = Direction.none; finalPath.Add(rg.GetRiverOn(lastVertex.x, lastVertex.z).GetClosestVertexTo(lastVertex)); Debug.Log("added river node: " + finalPath[0]); finalPath[0].side = Direction.river; } else { finalPath.Add(fmc.GetVertexOnBorder(reachableNodes[finalIndex].vertex, borderOffset, reachedSide, x_min, x_max, z_min, z_max)); //add new node which lies exactly on border } RiverInfo river = new RiverInfo(rg); while (pathIndex != 0)//recursively add all vertices of found path { finalPath.Add(reachableNodes[pathIndex].vertex); pathIndex = reachableNodes[pathIndex].parentIndex; river.UpdateLowestPoint(reachableNodes[pathIndex].vertex); } finalPath.Add(start); //if added border node is too close to next node, delete the next one if (finalPath.Count > 1 && Vector3.Distance(finalPath[0], finalPath[1]) < gridStep / 2 && finalPath[1] != start) { finalPath.RemoveAt(1); } finalPath.Reverse(); river.riverPath = finalPath; river.gridStep = gridStep; reachedSides.Add(reachedSide); return river; }
/// <summary> /// distributes water on each node of river path /// </summary> public void FloodRiver(RiverInfo river) { float value = 0.1f; foreach(Vertex v in river.riverPath) { value = waterMap.GetValue(v.x, v.z, 0) + value; if (value < maxOutflow * 4) { waterMap.SetValue(v.x, v.z, value); erosionEffect.Add(v); } } }
public void Initialise(RiverInfo info) { for (int i = 0; i < 12; i++) { if (myAtlasBillboard[i] == null) { myAtlasBillboard[i] = new Billboard("river"); } myAtlasBillboard[i].StopRender(); myAtlasBillboard[i].SetAtlas(Globals.g_world.GetAtlas((int)AtlasType.kAtlas_GrassTiles)); myAtlasBillboard[i].myObject.GetComponent <Renderer>().sharedMaterial = Globals.g_world.GetAtlas((int)AtlasType.kAtlas_GrassTiles).myMaterialTransparent; //int tileSubtexture = ((Globals.g_world.game).lBuilder).GetTileMapTileP1P2((int) AtlasType.kAtlas_GrassTiles, bridgeX + x, bridgeY + y); myAtlasBillboard[i].SetDetailsFromAtlas(Globals.g_world.GetAtlas((int)AtlasType.kAtlas_GrassTiles), 0); // // myAtlasBillboard[i].myObject.GetComponent<MeshRenderer>().sharedMaterial = Globals.g_main.grassSpriteAtlas; // Globals.g_main.grassSpriteAtlas.SetTexture("_MainTex",); } isBeingDrawn = false; riverType = info.riverType; if (false) { yCliffStart = (float)info.yPos - 32 + 94 - 15 - 40.0f; yCliffLength = (float)(340); raiseLength = 120.0f; } else { yCliffStart = (float)info.yPos - 32 + 60 - 15 - 40.0f; yCliffLength = (float)(400); raiseLength = 80.0f; } xFlowerPosition = (float)info.xPosBridge; xWidth = (float)info.widthBridge; CGPoint stemPosition = Utilities.CGPointMake(xFlowerPosition, yCliffStart + yCliffLength - 65.0f); if (xWidth == 128.0f) { if (xFlowerPosition == 320.0f) { stemPosition.x -= 8.0f; } else if (xFlowerPosition == 64.0f) { stemPosition.x += 8.0f; } } if (info.widthBridge == 64) { noGoStem.InitialiseP1(stemPosition, 30); } else { noGoStem.InitialiseP1(stemPosition, 65); } noGoStem.SetGroundLevel(-Game.kClifffDepth); noGoStem.SetType(NoGoType.e_Bridge); }