2024年12月16日 星期一

weeeeeeeeeeeeeeeeeeeeeeeeek15 物理碰撞

 1.week15_01_circle_collision_class_Ball_new_Ball_display

// week15_01_circle_collision_class_Ball_new_Ball_display
// google: processing collision detection library
// https://processing.org/examples/circlecollis
void setup(){
  size(640, 360);
}
Ball ball = new Ball(100, 400, 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);
  }
}

2.week15_02_circle_collision_class_Ball_update
////page1
// week15_02_circle_collision_class_Ball_update
void setup(){
  size(640, 360);
}
Ball ball = new Ball(100, 200, 20);
void draw(){
  ball.update(); //加這行
  ball.display();
}
//把 class Ball 移到右邊的新分頁(名字也叫Ball)
////page2
2.
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);
  }
}

3.week15_03_circle_collision_detection_two_ball
////page1
// week15_03_circle_collision_detection_two_ball
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)
////page2
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);
  }
}

4.week15_04_circle
////page1
// week15_04_circle
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)
///page2
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) {
    // 計算兩個小球的距離
    float d = dist(x, y, other.x, other.y);
    
    // 如果小球之間的距離小於半徑總和,表示發生碰撞
    if (d < r + other.r) {
      // 計算碰撞的法向量
      PVector diff = new PVector(other.x - x, other.y - y);
      float len = diff.mag(); // 法向量的長度
      diff.normalize(); // 將法向量單位化

      // 計算兩個小球的相對速度
      PVector v1 = new PVector(vx, vy);
      PVector v2 = new PVector(other.vx, other.vy);

      // 計算相對速度在法向量上的分量(即兩個小球接近的速度)
      float velocityAlongNormal = v1.dot(diff) - v2.dot(diff);

      // 如果兩個小球的相對速度在法向量方向上是接近的,就處理碰撞反彈
      if (velocityAlongNormal > 0) {
        // 彈性碰撞的反彈處理
        float e = 1.0; // 彈性係數(1為完全彈性碰撞)
        
        // 計算碰撞的動量
        float j = (-(1 + e) * velocityAlongNormal) / 2.0;

        // 計算並應用碰撞後的速度變化(動量變化)
        PVector impulse1 = diff.copy().mult(j); // 第一顆球的動量變化
        PVector impulse2 = diff.copy().mult(-j); // 第二顆球的動量變化

        // 更新速度
        vx += impulse1.x;
        vy += impulse1.y;
        other.vx += impulse2.x;
        other.vy += impulse2.y;
      }
      return true; // 發生了碰撞
    }
    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 * 2, r * 2);
  }
}

5.week15_05
///week15_05
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,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,1,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, step = 1;

void setup(){
  size(400, 400);
  visited[startI][startJ] = step;  // 用 startI 和 startJ 作為起點
  textSize(12);  // 設定顯示文字的字體大小,讓步數顯示清楚
}

void draw(){
  background(255);  // 清除背景

  // 繪製迷宮
  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.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 + 15, i * 40 + 25);  // 顯示步數
      }
    }
  }
}

// 深度優先搜尋 (DFS) 函數
boolean DFS(int i, int j, int s) {
  // 假如找到出口(7,7),則返回 true
  if(i == 7 && j == 7) return true;

  // 如果當前位置是牆壁或已經訪問過,則返回 false
  if(maze[i][j] == 1 || 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;  // 向左

  // 回溯,將當前位置重設為 0
  visited[i][j] = 0;
  return false;
}

// 當點擊鼠標時,重新開始 DFS
void mousePressed(){
  // 重設訪問狀態並重新執行 DFS
  for (int i = 0; i < visited.length; i++) {
    for (int j = 0; j < visited[0].length; j++) {
      visited[i][j] = 0;
    }
  }
  DFS(startI, startJ, 1);
}















































































































































沒有留言:

張貼留言