
- 作者: 吉谷幹人,布留川英一,一條貴彰,西森丈俊,藤岡裕吾,室星亮太,車谷勇人,湊新平,土屋つかさ,黒河優介,中村優一,牙竜,コポコポ,かせ,hataken,monmoko,佐藤英一
- 出版社/メーカー: ボーンデジタル
- 発売日: 2018/05/01
- メディア: 大型本
- この商品を含むブログを見る
序文
『UNITYゲーム プログラミング・バイブル』12日目。
進捗
(学習時間:???)
コード実装部分
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MazeMake : MonoBehaviour { [SerializeField]int mapSize = 5; // マップサイズ(必ず奇数値) int[,] maze; // マップ生成用(0=壁 1=通路) int cnt = 0; // 迷路の壁を生成した回数 [SerializeField] GameObject wallObject; // 壁オブジェクトを設定 [SerializeField] GameObject groundObject;// 地面オブジェクトを設定 [SerializeField] GameObject GoalObject; // ゴールオブジェクトを設定 void Start () { // マップ生成終了条件を算出(マップ内で通路が置ける場所-1) // 3×3の場合、2×2-1=3 // 5×5の場合、3×3-1=8 // 7×7の場合、4×4-1=15 int endNum = ((mapSize + 1) / 2) * ((mapSize + 1) / 2) - 1; // 迷路マップ // +2は外周の壁分 maze = new int[mapSize+2, mapSize+2]; while(endNum > cnt) { //Debug.Log(cnt); // ランダムで迷路を掘る場所を決める(必ず偶数になるようにする) // 3×3の場合、0,2 // 5×5の場合、0,2,4 // 7×7の場合、0,2,4,6 int x = Random.Range (0, (mapSize + 1) / 2) * 2; int y = Random.Range (0, (mapSize + 1) / 2) * 2; if (cnt == 0) { // 外周分を考慮して+1 maze[x + 1, y + 1] = 1; // 初回だけ予め穴を開けておく } // 外周分を考慮して+1 // 開始地点が通路ならその地点を起点として穴を堀り始める if (maze [x+1, y+1] == 1) WallDig (x, y, 0); } // パズル画面の表示 Output (); // ゴールを描画 Instantiate (GoalObject, new Vector3 (mapSize, 0, mapSize), Quaternion.identity); } // 迷路生成(穴掘り法) // 引数のx,yは外周を考慮していない void WallDig(int x, int y, int oldVec){ // [0]:上 // [1]:右 // [2]:下 // [3]:左 int[] vx = { 0, 2, 0, -2 }; int[] vy = { -2, 0, 2, 0 }; bool retFlg = false; // 四方向をランダムで選んで2マス先が掘れるかどうかをチェック // r = 0:上 // r = 1:右 // r = 2:下 // r = 3:左 int r = Random.Range (0, 4); // マップの端は掘ることが出来ない // y = 0は一番上だから上に掘ることはできない if (r == 0 && y <= 0) retFlg = true; // 右に掘ったらマップ外に出る時、右に掘ることはできない if (r == 1 && (x+2) >= mapSize) retFlg = true; // 下に掘ったらマップ外に出る時、下に掘ることはできない if (r == 2 && (y+2) >= mapSize) retFlg = true; // x == 0は一番左だから左に掘ることはできない if (r == 3 && x <= 0) retFlg = true; // 問題があるときはもう一度やり直す // 失敗したら違う方向 if (retFlg) { WallDig (x, y, oldVec); return; } // 壁を掘れそうなら掘る // (+1は外周分を考慮) if (maze [x+1 + vx [r], y+1 + vy [r]] == 0) { // 右辺の1は通路を示す // 次の地点に穴を掘る maze[x+1 + vx [r], y+1 + vy [r]] = 1; // 経由地点にも穴を掘る maze[x+1 + vx [r] / 2, y+1 + vy [r] / 2] = 1; // 穴の数を増やす cnt++; // 再帰ループ // 次の地点から穴を掘る WallDig (x + vx[r], y + vy[r], r); } // 堀った先がすでに通路だったときはreturn } // パズルをモデルを使って出力 void Output () { GameObject obj = new GameObject(); // 親オブジェクトの中に格納する obj.name = "Mize"; for (int x = 0; x < mapSize+2; x++) { for (int y = 0; y < mapSize+2; y++) { if (maze [x, y] == 0) { Instantiate (wallObject, new Vector3 (x, 0, y), Quaternion.identity).transform.parent = obj.transform; } else { Instantiate (groundObject, new Vector3 (x, 0, y), Quaternion.identity).transform.parent = obj.transform; } } } } }
実行結果
なし
感想
ノベルゲームのソースコードを読み解くことを諦めて、3D編に戻る。
「穴掘り法」と呼ばれるアルゴリズムで迷路を生成していくらしい。
ソースコードの中で外周の壁を考慮する部分と考慮しない部分が混在していて少し混乱したが、一応理解することができたと思う。
でもなんかアナログなアルゴリズムだねぇ。
カロリーメイトください。