未熟者ですので無駄な部分も多いかと思います。なんとか動くものができましたのでアップすることにしました。まずは動かしている動画を
以下がコードです。冒頭のrcの値で迷路の規模を変えることができます。上の実行動画は15✕15のブロックです。
目の高さehを低くすると周りが見渡せないので、まさに迷路の中という視線になり、いまどこにいるのか、もうわかりません。
int rc = 15; // 一辺の区画の数
int bs = 100; // ブロックの1辺の大きさ
color cl; // ブロックの色
ArrayList<PVector> mpos; // 区画の座標リスト
PVector pos;
float centerX, centerY, centerZ; // 注視点の座標
int emn = 1; // eyeの区画番号の初期値
int nemn;
int ed = 2; // eyeの向きの初期値
int dis = 300; // 視線の距離
int eh = 150; // eyeの高さ
void setup(){
size(800,800,P3D);
// ブロックのx座標,ブロック作成するか否か,z座標を格納
mpos = new ArrayList<PVector>();
// 全ての区画の座標を格納
for (int i = 0; i < rc * rc; i++) {
float x = bs / 2 + (i % rc) * bs;
float z = bs / 2 + (i / rc) * bs;
mpos.add(new PVector(x, 0, z));
}
// 周囲を壁で囲む
for (int i = 0; i < rc * rc; i++) {
int row = i / rc; //行
int col = i % rc; //列
if (row == 0 ||
row == rc - 1 ||
col == 0 ||
col == rc - 1) {
mpos.get(i).y = 1;
}
}
// 棒倒し法による迷路作成
for (int i = 2; i < rc - 2; i += 2) {
for (int j = 2; j < rc - 2; j += 2) {
int num = i + j * rc;
mpos.get(num).y = 1;
createMaze(num);
}
}
mpos.get(1).y = 0; //スタート地点のブロックを取り除く
mpos.get(rc * rc -2).y = 0; // ゴール地点のブロックを取り除く
}
void draw() {
background(0);
// 環境光(全体を少し明るくする)
ambientLight(100, 100, 100);
// ライトの設定(白色のライトを少し右斜め上から照射)
directionalLight(255, 255, 255, 1, -1, -1);
pos = mpos.get(emn);
getCenter(emn, ed);
camera(pos.x, -eh, pos.z,
centerX, centerY, centerZ, 0, 1, 0);
for(int i = 0; i < rc * rc; i++) {
pos = mpos.get(i);
if (pos.y == 1) {
if (i % 4 == 0) {
cl = color(0, 100, 0);
} else {
cl = color(#f4a460);
}
stroke(0);
createBox(pos.x, 0, pos.z, bs,bs,bs, cl);
}
}
pos = mpos.get(rc * rc -3);
cl = color(255,255,0);
createBox(pos.x, -bs, pos.z, bs, bs, bs, cl);
pos = mpos.get(rc * rc -1);
cl = color(255,0,255);
createBox(pos.x, -bs, pos.z, bs, bs, bs, cl);
checkGoal();
}
// 棒倒し法によりブロックを設置して迷路作成
void createMaze(int num) {
int north = num - rc;
int east = num + 1;
int south = num + rc;
int west = num -1;
// 周囲の区画を調べてブロックが無い場所をリストに格納
ArrayList<Integer> directions = new ArrayList<Integer>();
// 3行目のみ北に壁を作ることを認める
if (num / rc == 2) {
if (north >=0 && mpos.get(north).y == 0)
directions.add(north);
if (east < rc * rc && mpos.get(east).y == 0)
directions.add(east);
if (south < rc * rc && mpos.get(south).y == 0)
directions.add(south);
if (west >= 0 && mpos.get(west).y == 0)
directions.add(west);
} else {
// それ以外の行では北に壁を作らせない
if (east < rc * rc && mpos.get(east).y == 0)
directions.add(east);
if (south < rc * rc && mpos.get(south).y == 0)
directions.add(south);
if (west >= 0 && mpos.get(west).y == 0)
directions.add(west);
}
// リストからランダムに選択して壁を作る
if (directions.size() > 0 ) {
int idx = (int)random(directions.size());
int chosen = directions.get(idx);
mpos.get(chosen).y = 1;
}
}
void createBox(float x, float y, float z,
int w, int h, int d, color cl) {
fill(cl);
pushMatrix();
translate(x, y, z);
box(w, h, d);
popMatrix();
}
// 注視点の座標を取得
void getCenter(int emn, int ed) {
pos = mpos.get(emn);
switch (ed) {
case 0: // 北を向いているとき
centerX = pos.x;
centerZ = pos.z - dis;
break;
case 1: // 東を向いているとき
centerX = pos.x + dis;
centerZ = pos.z;
break;
case 2: // 南を向いているとき
centerX = pos.x;
centerZ = pos.z + dis;
break;
case 3: // 西を向いているとき
centerX = pos.x - dis;
centerZ = pos.z;
break;
}
}
// 進行方向の次の区画番号を取得
void nextPosition() {
nemn = emn; // デフォルトは変更なし
switch (ed) {
case 0: // 前方向(北)
if (emn > rc) { // 上端でない場合
nemn = emn - rc;
}
break;
case 1: // 右方向(東)
if (emn % rc < rc) { // 右端でない場合
nemn = emn + 1;
}
break;
case 2: // 後ろ方向(南)
if (emn < rc * rc - rc) { // 下端でない場合
nemn = emn + rc;
}
break;
case 3: // 左方向(西)
if (emn % rc > 0) { // 左端でない場合
nemn = emn - 1;
}
break;
}
// 移動先が壁でない場合のみ更新
if (mpos.get(nemn).y != 1) {
emn = nemn;
}
}
void keyPressed() {
switch (keyCode) {
case UP: // 前進
nextPosition();
getCenter(emn, ed);
break;
case RIGHT: // 右に向く
ed = (ed + 1) % 4;
getCenter(emn, ed);
break;
case LEFT: // 左に向く
ed = (ed + 3) % 4;
getCenter(emn, ed);
break;
}
}
// ゴールしたときの処理
void checkGoal() {
if (emn == rc * rc - 2) {
// カメラをゴール地点から遠くに配置して、ゴールの全体を見渡せるようにする
camera(pos.x, -eh, pos.z + 400,
pos.x, -eh, pos.z, 0, 1, 0);
pushMatrix();
translate(pos.x, -eh, pos.z);
textSize(50);
textAlign(CENTER, CENTER);
fill(255, 255, 0);
text("GOAL!!!", 0, 0);
popMatrix();
}
}