2024年12月16日 星期一

周家契約15號

今天要做碰撞偵測

1.用class來做球球設定

x, y, r代表座標和半徑

 //week15_01_circle_collision_class_Ball_new_Ball_display

void setup(){
  size(640,360);
  ball = new Ball(100,200,20);
}
//Ball ball = new Ball(100,400,20);
Ball ball;
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.接下來做update()

為了做碰到牆壁反彈

先在主要的打一個update()

再新增分頁把class Ball{}移過去

update()寫在裡面

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);
  }
}

















3.加上checkCollision函式

判斷是否有兩顆球碰在一起

在原本的程式加上判斷

呼叫checkCollision判斷true或false

true就變粉

false就維持白色

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.加入碰撞
用向量的內積(mult())
記得先normalize()
if (dist(x+vx, y+vy, other.x+other.vx, other.y+other.vy)<=r+other.r)
這行是防止兩顆球黏在一起
標準化數字才會變小
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+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();
      float a = diff.heading();
      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);
  }
}
































跟之前一樣做迷宮
先用矩陣畫出迷宮(0是能走的,1是不能走的)
想要用深度優先搜尋法來做

//week15_07_maze_DFS_visited
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);
}


























紅色是起始點
每按滑鼠一下就會開始移動並顯示步數

//week15_07_maze_DFS_visited_step_mousePressed_move
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.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;
  }
}




要做結尾
讓他碰壁能重新搜尋
在boolean DFS()裡搜尋所又有可能的走法
true就繼續走
false就重新走
DFS(x,y,s)
s用來當旗標
來表示曾經走到哪裡

//week15_07_maze_DFS_visited_step_mousePressed_move
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.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) {
  print(i,i,s);
  if (i==8 && j==8)  return true;
  if (visited[i][j]>0)  return false;
  if (maze[i][j]==1)  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, s+1))  return true;
  visited[i][j]=0;
  return false;
}
void mousePressed() {
  DFS(1, 1, 1);
}












































沒有留言:

張貼留言