2013年5月16日 星期四

[對照]蝦爸的p5範例 7-2 「運用遞迴概念,製造迷宮材質」

[Processing Example]

本練習將透過遞迴概念的運用,製造有趣的迷宮材質貼圖。
迷宮的產生邏輯由二要素構成:
  • 不管從任何一點出發,迷宮都會佈滿所有路徑
  • 路徑會隨機增長,死路時會回到上一個還能選擇的路口,往其他方向增長。

[Processing code] ↓

int[][] Maze=new int[10][10];
int[][] Temp=new int[21][21];

int outline;
PGraphics Maze_Texture;

void setup() {
  size(600, 400, OPENGL); 
  outline=17;
  
  Maze_Texture=createGraphics(outline*10, outline*10, OPENGL);
  
  for (int i=0;i<10;i++) {
    for (int j=0;j<10;j++) {
      if ((i==0 ||i==9)||(j==0 ||j==9)) {
        Maze[i][j]=2;
      }
      else {
        Maze[i][j]=0;
      }
    }
  }//初始化,邊緣不計算

  for (int i=0;i<outline;i++) {
    for (int j=0;j<outline;j++) {
      if ((i==0 ||(i==outline-1))||(j==0 ||j==(outline-1))) {
        Temp[i][j]=2;
      }
      else {
        Temp[i][j]=0;
      }
    }
  }

  Walker(1, 1);

  for (int i=0;i<10;i++) {
    for (int j=0;j<10;j++) {
      if (Maze[i][j]==2) {
        fill(255, 0, 0);
      }
      else if (Maze[i][j]==1) {
        fill(0, 255, 0);
      }
      else {
        fill(0, 0, 255);
      }
      rect(i*10, j*10, 10, 10);
    }
  }
  
  //---將影像寫入buffer
  Maze_Texture.beginDraw(); 
  for (int i=0;i<outline;i++) {
    for (int j=0;j<outline;j++) {
      Maze_Texture.noStroke();
      if (Temp[i][j]==2) {
        Maze_Texture.fill(50, 50, 50);
      }
      else if (Temp[i][j]==1) {
        Maze_Texture.fill(200, 200, 200);
      }
      else {
        Maze_Texture.fill(100, 100, 100);
      }
     Maze_Texture. rect(i*10, j*10, 10, 10);
    }
  }
  Maze_Texture.endDraw();
  //---結束寫入
}

void draw() {
  background(0);
  camera(mouseX, mouseY, 200, 0, 0, 0, 0, 1, 0);
  beginShape();
  textureMode(NORMAL);
  texture(Maze_Texture);
  vertex(-100, -100, 0, 0, 0);
  vertex(100, -100, 0, 1, 0);
  vertex(100, 100, 0, 1, 1);
  vertex(-100, 100, 0, 0, 1);
  endShape();
}

void Walker(int x, int y) {
  Temp[x*2-1][y*2-1]=1;
  Maze[x][y]=1;
  for (;;) {
    if ((Maze[x-1][y]!=0)&&(Maze[x][y+1]!=0)&&(Maze[x+1][y]!=0)&&(Maze[x][y-1]!=0)) {
      break;
    }
    int Dircet=(int)random(4)%4;//Direct:0 left,1 down,2 right,3 up
    if ((Dircet==0) && (Maze[x-1][y] !=0 )) continue;
    if ((Dircet==1) && (Maze[x][y+1] !=0 )) continue;
    if ((Dircet==2) && (Maze[x+1][y] !=0 )) continue;
    if ((Dircet==3) && (Maze[x][y-1] !=0 )) continue;

    if ((Dircet==0) && (Maze[x-1][y] == 0)) {
      Temp[x*2-2][y*2-1]=1;
      Walker(x-1, y);
    }
    if ((Dircet==1) && (Maze[x][y+1] == 0)) {
      Temp[x*2-1][y*2]=1;
      Walker(x, y+1);
    }  
    if ((Dircet==2) && (Maze[x+1][y] == 0)) {
      Temp[x*2][y*2-1]=1;
      Walker(x+1, y);
    }
    if ((Dircet==3) && (Maze[x][y-1] == 0)) {
      Temp[x*2-1][y*2-2]=1;
      Walker(x, y-1);
    }
  }
}

[Pd Example]


P5 的迷宮貼圖是透過遞迴所產生,而Pd的範例中,則得利用讀取陣列的方式才能達成,且P5的座標是儲存在二維陣列中,當程式走到死路時,很快就能夠利用break退到上一個選擇點,在Pd則是利用一維陣列去模擬二維陣列的座標,再加上Pd並沒有continue 及break的概念,因此我是利用[spigot]來阻斷訊息,以及[delay]來阻止程式stack overflow。

在我的經驗裡,撰寫簡單的圖形及互動時,Pd會比P5好用,可是如果是像本範例中的邏輯演算,那P5實在比Pd好寫太多,用Pd寫是真的是自討哭吃(但我就是戒不掉呀..)

[Pd code] ↓

(maze.pd)

(pd setup============)

(pd class-Walker)

(pd write-Walker)

(pd back)