2024年12月16日 星期一

BK Week15 碰撞 + 迷宮路徑學習

Processing 程式碼

先畫出一個範圍 然後用 class Ball display() 畫出一個小圓
void setup() {
  size(640, 360);
}
Ball ball = new Ball(100, 200, 20);
void draw() {
  ball.display();
}
class Ball {
  float x, y, r;
  Ball(int x0, int y0, int r0) {
    x = x0;
    y = y0;
    r = r0;
  }
  void display() {
    ellipse(x, y, r+r, r+r);
  }
}


用兩個分頁 讓小圓碰到四周的牆壁會隨機反彈
分頁一
void setup() {
  size(640, 360);
}
Ball ball = new Ball(100, 200, 20);
void draw() {
  ball.update(); //加這行
  ball.display();
}
// 把 class Ball 移到右邊的新分頁(名字也較 Ball)
分頁二
class Ball {
  float x, y, r;
  float vx, vy;
  Ball(int x0, int y0, int r0) {
    x = x0;
    y = y0;
    r = r0;
    vx = random(-10, +10);
    vy = random(-10, +10);
  }
  void update() {
    if (x+vx > 640 || x+vx < 0) vx = -vx;
    if (y+vy < 0 || y+vy > 360) vy = -vy;
    x += vx;
    y += vy;
  }
  void display() {
    ellipse(x, y, r+r, r+r);
  }
}


計算兩圓圓心相距的距離 和半徑相加的長度 判斷兩圓是否發生碰撞
分頁一
void setup() {
  size(640, 360);
}
Ball ball = new Ball(100, 200, 60);
Ball ball2 = new Ball(300, 200, 60);
void draw() {
  background(51);
  if (ball.checkCollision(ball2))fill(#FFAAAA); //如果有碰撞發生 就變粉紅色
  else fill(255);
  ball.update();
  ball.display();
  ball2.update(); //加這行
  ball2.display(); //加這行
}
// 把 class Ball 移到右邊的新分頁(名字也較 Ball)
分頁二
class Ball {
  float x, y, r;
  float vx, vy;
  Ball(int x0, int y0, int r0) {
    x = x0;
    y = y0;
    r = r0;
    vx = random(-10, +10);
    vy = random(-10, +10);
  }
  boolean checkCollision(Ball other) {
    if (dist(x, y, other.x, other.y) < r + other.r) return true;
    //先算兩圓圓心的距離 如果兩圓心距離小於兩圓半徑相加 代表兩圓碰撞在一起
    else return false;
  }
  void update() {
    if (x+vx > 640 || x+vx < 0) vx = -vx;
    if (y+vy < 0 || y+vy > 360) vy = -vy;
    x += vx;
    y += vy;
  }
  void display() {
    ellipse(x, y, r+r, r+r);
  }
}


讓兩個圓碰到會反彈 用 向量內積 (超級難)
分頁一
void setup() {
  size(640, 360);
}
Ball ball = new Ball(100, 200, 60);
Ball ball2 = new Ball(300, 200, 60);
void draw() {
  background(51);
  if (ball.checkCollision(ball2))fill(#FFAAAA); //如果有碰撞發生 就變粉紅色
  else fill(255);
  ball.update();
  ball.display();
  ball2.update(); //加這行
  ball2.display(); //加這行
}
// 把 class Ball 移到右邊的新分頁(名字也較 Ball)
分頁二
class Ball {
  float x, y, r;
  float vx, vy;
  Ball(int x0, int y0, int r0) {
    x = x0;
    y = y0;
    r = r0;
    vx = random(-5, +5);
    vy = random(-5, +5);
  }
  boolean checkCollision(Ball other) {
    if (dist(x+vx, y+vy, other.x+other.vx, other.y+other.vy) <= r + other.r) { 
    //先算兩圓圓心的距離 如果兩圓心距離小於兩圓半徑相加 代表兩圓碰撞在一起
      PVector diff = new PVector(other.x-x, other.y-y);
      float len = diff.mag(); //maganitude 量值、長度的意思
      float a = diff.heading(); //向量的方向, 對應某個角度
      // 熟悉的 cos(a), sin(a)
      PVector N = diff.copy().normalize(); // 連線方向
      N.mult(N.dot(new PVector(vx, vy)));
      PVector N2 = new PVector(-N.y, N.x).normalize(); // 另一個垂直方向
      N2.mult(N2.dot(new PVector(vx, vy)));

      PVector M = diff.copy().normalize();
      M.mult(M.dot(new PVector(other.vx, other.vy)));
      PVector M2 = new PVector(-M.y, M.x).normalize();
      M2.mult(M2.dot(new PVector(other.vx, other.vy)));

      PVector newV1 = PVector.add(M, N2);
      PVector newV2 = PVector.add(N, M2);
      vx = newV1.x;
      vy = newV1.y;
      other.vx = newV2.x;
      other.vy = newV2.y;
      return true;
    } else return false;
  }
  void update() {
    if (x+vx > 640 || x+vx < 0) vx = -vx;
    if (y+vy < 0 || y+vy > 360) vy = -vy;
    x += vx;
    y += vy;
  }
  void display() {
    ellipse(x, y, r+r, r+r);
  }
}


用陣列畫出迷宮
int [][] maze = {
   {1,1,1,1,1,1,1,1,1,1},
   {1,0,0,1,1,0,0,0,1,1},
   {1,1,0,1,1,0,1,0,1,1},
   {1,1,0,0,1,0,1,0,1,1},
   {1,1,1,0,0,0,1,0,1,1},
   {1,1,1,1,1,1,1,0,1,1},
   {1,1,1,1,1,1,1,0,1,1},
   {1,1,1,1,1,1,1,0,1,1},
   {1,1,1,1,1,1,1,0,0,1},
   {1,1,1,1,1,1,1,1,1,1}
}; 
void setup(){
   size(400, 400); 
}
void draw(){
   for(int i=0; i<maze.length; i++){
      for(int j=0; j<maze[0].length; j++){
         if(maze[i][j]==1) fill(0);
         else fill(255);
         rect(j*40, i*40, 40, 40);
      }
   }
}


用陣列畫出迷宮 並畫出紅色格子
int [][] maze = {
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
  {1, 0, 0, 0, 1, 0, 0, 0, 1, 1},
  {1, 1, 0, 1, 1, 0, 1, 0, 1, 1},
  {1, 1, 0, 0, 1, 0, 1, 0, 1, 1},
  {1, 1, 1, 0, 0, 0, 1, 0, 1, 1},
  {1, 0, 1, 1, 0, 1, 1, 0, 1, 1},
  {1, 0, 0, 0, 0, 1, 1, 0, 1, 1},
  {1, 0, 1, 1, 1, 1, 1, 0, 1, 1},
  {1, 0, 0, 0, 0, 0, 1, 0, 0, 1},
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
int [][] visited = new int[10][10];
int startI = 1, startJ = 1, I = 1, J = 1, step = 1;
void setup() {
  size(400, 400);
  visited[I][J] = step;
}
void draw() {
  for (int i=0; i<maze.length; i++) {
    for (int j=0; j<maze[0].length; j++) {
      if (maze[i][j]==1) fill(0);
      else fill(255);
      rect(j*40, i*40, 40, 40);
    }
  }
  fill(255, 0, 0);
  rect(startJ*40, startI*40, 40, 40);
}


用 mousePressed() 可以往下或往右走直到被擋住
int [][] maze = {
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
  {1, 0, 0, 0, 1, 0, 0, 0, 1, 1},
  {1, 1, 0, 1, 1, 0, 1, 0, 1, 1},
  {1, 1, 0, 0, 1, 0, 1, 0, 1, 1},
  {1, 1, 1, 0, 0, 0, 1, 0, 1, 1},
  {1, 0, 1, 1, 0, 1, 1, 0, 1, 1},
  {1, 0, 0, 0, 0, 1, 1, 0, 1, 1},
  {1, 0, 1, 1, 1, 1, 1, 0, 1, 1},
  {1, 0, 0, 0, 0, 0, 1, 0, 0, 1},
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
int [][] visited = new int[10][10];
int startI = 1, startJ = 1, I = 1, J = 1, step = 1;
void setup() {
  size(400, 400);
  visited[I][J] = step;
}
void draw() {
  for (int i=0; i<maze.length; i++) {
    for (int j=0; j<maze[0].length; j++) {
      if (maze[i][j]==1) fill(0);
      else fill(255);
      rect(j*40, i*40, 40, 40);
    }
  }
  fill(255, 0, 0);
  rect(startJ*40, startI*40, 40, 40);
  for (int i=0; i<maze[0].length; i++) {
    for (int j=0; j<maze[0].length; j++) {
      if (visited[i][j]>0) {
        fill(0, 0, 255);
        text(""+visited[i][j], j*40+20, i*40+20);
      }
    }
  }
}
void mousePressed() {
  if (maze[I+1][J]==0) {
    I = I+1;
    visited[I][J] = ++step;
  } else if (maze[I][J+1]==0) {
    J = J+1;
    visited[I][J] = ++step;
  }
}


當點一下滑鼠後 直接自己尋找最佳路徑 走到最後
int [][] maze = {
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
  {1, 0, 0, 0, 1, 0, 0, 0, 1, 1},
  {1, 1, 0, 1, 1, 0, 1, 0, 1, 1},
  {1, 1, 0, 0, 1, 0, 1, 0, 1, 1},
  {1, 1, 1, 0, 0, 0, 1, 0, 1, 1},
  {1, 0, 1, 1, 0, 1, 1, 0, 1, 1},
  {1, 0, 0, 0, 0, 1, 1, 0, 1, 1},
  {1, 0, 1, 1, 1, 1, 1, 0, 1, 1},
  {1, 0, 0, 0, 0, 0, 1, 0, 0, 1},
  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
int [][] visited = new int[10][10];
int startI = 1, startJ = 1, I = 1, J = 1, step = 1;
void setup() {
  size(400, 400);
}
void draw() {
  for (int i=0; i<maze.length; i++) {
    for (int j=0; j<maze[0].length; j++) {
      if (maze[i][j]==1) fill(0);
      else fill(255);
      rect(j*40, i*40, 40, 40);
    }
  }
  fill(255, 0, 0);
  rect(startJ*40, startI*40, 40, 40);
  for (int i=0; i<maze[0].length; i++) {
    for (int j=0; j<maze[0].length; j++) {
      if (visited[i][j]>0) {
        fill(0, 0, 255);
        text(""+visited[i][j], j*40+20, i*40+20);
      }
    }
  }
}
boolean DFS(int i, int j, int s) {
  if (i==8 && j==8) return true; //走到目的地
  if (maze[i][j]==1) return false; //擋住不能走
  if (visited[i][j] > 0) return false; //走過不要再走
  visited[i][j] = s; //先插旗子, 表示走到這裡
  if (DFS(i+1, j, s+1)) return true;
  if (DFS(i-1, j, s+1)) return true;
  if (DFS(i, j+1, s+1)) return true;
  if (DFS(i, j-1, s+1)) return true;
  visited[i][j] = 0;
  return false;
}
void mousePressed() {
  DFS(1, 1, 1);
}

沒有留言:

張貼留言