public override void Place(TrackSegment segment, int[,] spots) { base.Place(segment, spots); PlacerSpot spot = new PlacerSpot(); //be gentle with the stack, allocate only once //iterate on each row for (int i = 0; i < TrackSegment.LENGTH; i++) { //get curent deviation int shift = stretch.Get(); //mark and add assets along path's width for (int j = 0; j < thickness; j++) { spot.x = column + shift + j; spot.y = i; Mark(spot); AddAsset(spot); } //increment stretch and start a new one if needed if (!stretch.Advance()) { //save column for the next stretch column += shift; StartStretch(); } } }
/// <summary> /// Scans segment's occupancy matrix and fills the areas list according to placer values. /// </summary> private void MapAreas() { PlacerSpot spot = new PlacerSpot(); //be gentle with the stack, allocate only once for (int i = 0; i <= TrackSegment.WIDTH - size; i++) { for (int j = 0; j <= TrackSegment.LENGTH - size; j++) { spot.x = i; spot.y = j; float fill = PlacerArea.GetSpotRatio(PlacerSpot.Type.Empty, spots, spot, size); if (!allowIntertwined && !Mathf.Approximately(fill, 1f)) { continue; } if (fill >= targetFillRatio) { areas.Add(new PlacerArea(spots, spot, size)); } } } }
/// <summary> /// Scans the surface of a segment's occupancy matrix for a specific spot type and computes it's ratio. /// </summary> /// <param name="type">Value to search for.</param> /// <param name="spots">Ref to occupancy matrix.</param> /// <param name="pivot">Start of area.</param> /// <param name="size">Extents of area.</param> /// <returns>A value between [0f, 1f].</returns> public static float GetSpotRatio(PlacerSpot.Type type, int[,] spots, PlacerSpot pivot, int size) { int count = 0; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if (spots[pivot.x + i, pivot.y + j] == (int)type) { count++; } } } return((float)count / (size * size)); }
/// <summary> /// Instatiates a clone of the asset and positions it in segment's space, applying the offsets. /// </summary> /// <param name="spot">Matrix coordinates.</param> protected void AddAsset(PlacerSpot spot) { //determine offsets Vector3 posOffset = new Vector3( Random.Range(-positionsRange.x, positionsRange.x), Random.Range(-positionsRange.y, positionsRange.y), Random.Range(-positionsRange.z, positionsRange.z) ); Vector3 rotOffset = new Vector3( Random.Range(-rotationsRange.x, rotationsRange.x), Random.Range(-rotationsRange.y, rotationsRange.y), Random.Range(-rotationsRange.z, rotationsRange.z) ); //create and place clone Instantiate(asset, segment.GetSpotPos(spot.x, spot.y) + posOffset, Quaternion.Euler(rotOffset), segment.transform); }
/// <summary> /// Returns all the spots of a certain type from a specified area. /// </summary> /// <param name="type">Value to search for.</param> /// <param name="spots">Ref to occupancy matrix.</param> /// <param name="pivot">Start of area.</param> /// <param name="size">Extents of area.</param> /// <param name="output">List to add the spots to.</param> public static void GetSpots(PlacerSpot.Type type, int[,] spots, PlacerSpot pivot, int size, List <PlacerSpot> output) { PlacerSpot spot = new PlacerSpot(); //be gentle with the stack, allocate only once for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { spot.x = pivot.x + i; spot.y = pivot.y + j; if (spots[spot.x, spot.y] == (int)type) { output.Add(spot); } } } }
public override void Place(TrackSegment segment, int[,] spots) { base.Place(segment, spots); MapAreas(); //build list if (areas.Count == 0) //nothing to do, exit { return; } //determine actual possible pathes count - not all may fit int count = (areas.Count < targetCount)? areas.Count : targetCount; //place patches towards the target count for (int i = 0; i < count && areas.Count > 0; i++) { //choose area PlacerArea area = areas[Random.Range(0, areas.Count)]; //builds free spots list area.GetSpots(PlacerSpot.Type.Empty, free); //choose from free spots and place assets for (int j = 0; j < assetsPerPatch; j++) { int index = Random.Range(0, free.Count); PlacerSpot spot = free[index]; Mark(spot); AddAsset(spot); free.RemoveAt(index); } //prepare for next patch free.Clear(); areas.RemoveAll(item => area.Overlaps(item) && (!allowIntertwined || allowIntertwined && item.GetSpotRatio(PlacerSpot.Type.Empty) < targetFillRatio)); } //cleanup areas.Clear(); }
/// <summary> /// Set mark value in occupation matrix. /// </summary> /// <param name="spot">Matrix coordinates.</param> protected void Mark(PlacerSpot spot) { spots[spot.x, spot.y] = (int)mark; }
/// <summary> /// Constructor. /// </summary> /// <param name="spots">Ref to occupancy matrix.</param> /// <param name="pivot">Start of area.</param> /// <param name="size">Extents of area.</param> public PlacerArea(int[,] spots, PlacerSpot pivot, int size) { this.spots = spots; this.pivot = pivot; this.size = size; }