//static Color white = Color.white; // その場所が空き地かどうか調べる static public bool IsEmptyField(Vector3 pos, Liver.Entity.AreaMap areaMap, Vector3 offset) { // 画像上の位置 var tpos = pos - offset; //Debug.Log($"{pos.x}, {pos.z} -> {tpos.x}, {tpos.z}"); int x = (int)tpos.x; int y = (int)tpos.z; if (!areaMap.Contain(x, y)) { return(false); } var color = areaMap.GetPixel(x, y); return(!(color.g > 0)); //return ExtendedColor.FastEqual(ref color, ref white); }
public GameObject FenceRight; // 右側のみ public IEnumerator Process(RoadInfo roadInfo, GridArea gridArea, Liver.Entity.AreaMap areaMap) { if (FenceAll == null || FenceLeft == null || FenceRight == null) { yield break; } Debug.Log("FenceLayouter.Process"); // ピクセルを配列でゲット var num = (int)LocationDeterminer.GridSizeKilometer; var offset = new Vector3(num * -0.5f, 0, num * -0.5f); var dummy = Instantiate <GameObject>(this.FenceAll).transform; var left = dummy.Find("left"); var right = dummy.Find("right"); var vFront = new Vector3(0, 0, -2); var vBack = new Vector3(0, 0, 2); var half = Map.LocationDeterminer.GridSizeKilometer * 0.5f; float goNextFrameTime = Time.realtimeSinceStartup + 0.03f; foreach (var road in roadInfo.Roads) { // 道の長さを計算 float l = road.TotalLength; // 交差点の前後5mには置かない if (l < (3 + 6 + 3) * 2) { continue; } float d = 3 + 6 + 3; while (l > (d + 3 + 6 + 3)) { if (Random.Range(0.0f, 1.0f) < 0.5f) { var p = RoadInfo.CalcPosition(road, d); var v = RoadInfo.CalcVector(road, d); // 3kmグリッド内か判定 if (Mathf.Abs(p.x) > half || Mathf.Abs(p.z) > half) { d += 8.0f; continue; } if (RoadInfo.CheckVertex(road, d, 16, 0.99f)) { var q = Quaternion.LookRotation(v); // 向きを計算する // 計算のため、ダミーの座標と向きを設定する dummy.localPosition = p; dummy.localRotation = q; byte bit = 0; // テクスチャ画像上での色を調査 if (IsEmptyField(left.position, areaMap, offset) && IsEmptyField(left.position + q * vFront, areaMap, offset) && IsEmptyField(left.position + q * vBack, areaMap, offset)) { bit |= 1 << 0; } // 左 if (IsEmptyField(right.position, areaMap, offset) && IsEmptyField(right.position + q * vFront, areaMap, offset) && IsEmptyField(right.position + q * vBack, areaMap, offset)) { bit |= 1 << 1; } // 右 switch (bit) { // 左のみ case 1: gridArea.Component <PoolEnliven>(p).Add(this.FenceLeft, p, q); break; // 右のみ case 2: gridArea.Component <PoolEnliven>(p).Add(this.FenceRight, p, q); break; // 両方 case 3: gridArea.Component <PoolEnliven>(p).Add(this.FenceAll, p, q); break; } } } d += 8.0f; } // 一定時間ごとにyield if (Time.realtimeSinceStartup > goNextFrameTime) { yield return(null); goNextFrameTime = Time.realtimeSinceStartup + 0.03f; } } Destroy(dummy.gameObject); //texture.SetPixels32(colors); }
public int EmptyAreaSize(Liver.Entity.AreaMap areaMap, int x, int y, int step, int max) { int current = step; while (current < max) { // 四方向調べる // NOTE 建物が四角いので4端を調査 if (!areaMap.Contain(x - current, y - current)) { return(current - step); } if (!areaMap.Contain(x - current, y + current)) { return(current - step); } if (!areaMap.Contain(x + current, y - current)) { return(current - step); } if (!areaMap.Contain(x + current, y + current)) { return(current - step); } var leftup = areaMap.GetPixel(x - current, y - current); if ((leftup.r > 0)) { return(current - step); } //if (!ExtendedColor.FastEqual(ref up, ref white)) return current - step; var leftdown = areaMap.GetPixel(x - current, y + current); if ((leftdown.r > 0)) { return(current - step); } //if (!ExtendedColor.FastEqual(ref down, ref white)) return current - step; var rightup = areaMap.GetPixel(x + current, y - current); if ((rightup.r > 0)) { return(current - step); } //if (!ExtendedColor.FastEqual(ref left, ref white)) return current - step; var rightdown = areaMap.GetPixel(x + current, y + current); if ((rightdown.r > 0)) { return(current - step); } //if (!ExtendedColor.FastEqual(ref right, ref white)) return current - step; current += step; } return(max); }
// 生成 public IEnumerator Process(GridArea gridArea, Liver.Entity.AreaMap areaMap) { Debug.Log("EnlivenLayouter.Process"); if (enlivens.Length == 0) { yield break; } // テキストから生成 var enliven = Enliven.Load(); yield return(null); var num = (int)LocationDeterminer.GridSizeKilometer; var offset = new Vector3(num * -0.5f, 0, num * -0.5f); int x, y, size; float goNextFrameTime = Time.realtimeSinceStartup + 0.03f; for (int i = 0; i < enliven.Count; i++) { enliven.Unpack(i, out x, out y, out size); var color = areaMap.GetPixel(x, y); if (color.r > 0) { continue; } //if (!ExtendedColor.FastEqual(ref color, ref white)) continue; var emptySize = Mathf.Max(1, EmptyAreaSize(areaMap, x, y, 1, Mathf.Min(size, maxSize))); #if false // 空きスペース以下のプレハブをランダムで抽選する var count = System.Array.FindLastIndex(enlivens, (e) => { return(e.size <= emptySize); }); var prefab = enlivens[Random.Range(0, count + 1)].prefab; #else GameObject prefab = null; // なるべく大きいオブジェクトを配置する // MEMO : サイズ1以上のものが複数がある場合、後ろのほうが抽選されます。(現時点対応必要ないため放置します。 int count = enlivens.Length - 1; for (int j = enlivens.Length - 1; j >= 0; j--) { if (enlivens[j].size <= emptySize) { count = j; break; } } if (enlivens[count].size != 1) { prefab = enlivens[count].prefab; } else { prefab = enlivens[Random.Range(0, count + 1)].prefab; } #endif var p = new Vector3(x + offset.x, 0 + offset.y, y + offset.z); var c = gridArea.Component <PoolEnliven>(p); c.Add(prefab, p); // 一定時間ごとにyield if (Time.realtimeSinceStartup > goNextFrameTime) { yield return(null); goNextFrameTime = Time.realtimeSinceStartup + 0.03f; } } }