
3Dになっている意味としては、「壁」に見えるということ以外にありません。変数の値によって迷路の規模が変わります。ボールをUP, DOWN, RIGHT, LEFTキーで動かします。
コードは以下のとおりです。
int rc = 21; // 一辺の区画の数(奇数が望ましい?)
int bs = 100; // ブロックの1辺の大きさ
color cl; // 区画の色
ArrayList<PVector> mpos; // 区画の座標とブロックの有無
PVector pos;
float centerX, centerY, centerZ; // 注視点の座標
int emn = 1; // 初期の球の区画番号
int nemn;
int ed = 2; // eyeの向きの初期値
int dis = 100; // 視線の距離
void setup(){
size(600, 600, P3D);
mpos = new ArrayList<PVector>();
// すべての区画の座標を格納、yには初期値の0
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));
}
// 周りの区画のyを1(ブロックを置く)
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;
}
}
// 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);
camera((rc * bs) / 2, -(rc * bs), (rc * bs) / 2,
(rc * bs) / 2, bs, (rc * bs) / 2 - 1, 0, 1, 0);
for(int i = 0; i < rc * rc; i++) {
pos = mpos.get(i);
if (pos.y == 1) {
cl = color(#FFDEAD);
stroke(0);
createBox(pos.x, 0, pos.z, bs,bs,bs, cl);
}
}
createBall(emn);
checkGoal();
}
void createMaze(int num) {
ArrayList<Integer> directions = new ArrayList<Integer>();
int north = num - rc;
int east = num + 1;
int south = num + rc;
int west = num -1;
// 3行目のみ東西南北の4方向を調べる
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 { // 4行目以下は北は選択肢から外す
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 createBall(int emn) {
pos = mpos.get(emn);
fill(150, 50, 200);
noStroke();
pushMatrix();
translate(pos.x, 0, pos.z);
sphere(40);
popMatrix();
}
void keyPressed() {
switch (keyCode) {
case UP:
ed = 0;
break;
case RIGHT:
ed = 1;
break;
case DOWN:
ed = 2;
break;
case LEFT:
ed = 3;
break;
}
nextPosition();
}
void nextPosition() {
nemn = emn; // デフォルトは変更なし(動かない)
switch (ed) {
case 0: // UP
if (emn > rc) { // 上端でないとき
nemn = emn - rc;
}
break;
case 1: // RIGHT
if (emn % rc < rc) { // 右端でないとき
nemn = emn + 1;
}
break;
case 2: // DOWN
if (emn < rc * rc - rc) { // 下端でないとき
nemn = emn + rc;
}
break;
case 3: // LEFT
if (emn % rc > 0) { // 左端でないとき
nemn = emn - 1;
}
break;
}
// 移動先が壁でない場合のみ更新(移動)
if (mpos.get(nemn).y == 0) {
emn = nemn;
}
}
void checkGoal() {
if (emn == rc * rc - 2) {
pushMatrix();
translate((rc * bs) /2 , -200, (rc * bs) /2);
rotateX(radians(90));
textSize(rc * 20);
textAlign(CENTER, CENTER);
fill(#32CD32);
text("GOAL!!!", 0, 0);
popMatrix();
}
}