未熟者ですので無駄な部分も多いかと思います。なんとか動くものができましたのでアップすることにしました。まずは動かしている動画を

 以下がコードです。冒頭の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();
  }
}
投稿者

manager

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


日本語が含まれない投稿は受付られません。(スパム対策)