2024年12月16日 星期一

week15

 week15_01_circle_collision_Ball_new_Ball_display



1.建好簡單的物件架構

程式碼


//week15_01_circle_collision_Ball_new_Ball_display


void setup(){

  size(640,360);

}

Ball ball = new Ball(100,200,20);

void draw(){

  ball.display();

}

class Ball{

  float x,y,z,r;

  Ball(int x0,int y0,int r0) {

    x = x0;

    y = y0;

    r = r0;

  }

  void display(){

    ellipse(x,y,r+r,r+r);

  }

}


week15_02_circle_collision_class_Ball_update



1.Ball類別功能

  • update() 方法:更新球的位置,並檢查球是否碰到視窗邊界,若碰到則反彈(反轉速度)。
  • display() 方法:使用 ellipse() 函數在視窗上畫出球。

  • 程式碼

    //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

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

      }

    }


    week15_03_circle_collision_detection_two_ball



    1.做出碰撞偵測

    1. checkCollision(Ball other) 方法

      • 邏輯:使用 dist(x, y, other.x, other.y) 計算兩球中心之間的距離,並比較這個距離是否小於兩球半徑的總和 r+other.rr + other.r
      • 用途:判斷兩球是否碰撞,如果碰撞,返回 true,否則返回 false
    2. 邊界反彈邏輯

      • x 方向:如果球的下一個 x 位置超過視窗寬度(640)或小於 0,速度 vx 反向(vx = -vx)。
      • y 方向:同理,如果球的下一個 y 位置超過視窗高度(360)或小於 0,速度 vy 反向(vy = -vy)。
    3. 速度隨機生成

      • 在建構子中,vxvy 使用 random(-10, +10) 隨機生成速度,讓球的移動方向與速度有所變化。

    程式碼


    //week15_03_circle_collision_detection_two_ball


    Ball ball =  new Ball(100, 200, 60); 

    Ball ball2 =  new Ball(300, 200, 60); 


    void setup() {

      size(640, 360);

    }


    void draw() {

      background(51);

      if(ball.checkCollision(ball2)) fill(#FFAAAA);

      else fill(255);

      ball.update();

      ball.display();

      ball2.update();

      ball2.display();

    }

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

      }

    }


    week15_04_circle_collision_cos_vector_sin_N_N2_M_M2_swap


    1.做出碰撞


    程式碼


    //week15_04_circle_collision_cos_vector_sin_N_N2_M_M2_swap

    Ball ball =  new Ball(100, 200, 60); 

    Ball ball2 =  new Ball(300, 200, 60); 


    void setup() {

      size(640, 360);

    }


    void draw() {

      background(51);

      if(ball.checkCollision(ball2)) fill(#FFAAAA);

      else fill(255);

      ball.update();

      ball.display();

      ball2.update();

      ball2.display();

    }

    //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+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(-N.y,N.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);

      }

    }


    week15_05_maze_DFS_visited


    1.做出迷宮地圖


    程式碼


    //week15_05_maze_DFS_visited

    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,0,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



    1.會往下還有往右,但還不會自動跑完地圖


    程式碼

    //week15_07_maze_DFS_visited_step_mousePressed_move

    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,0,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;

      }

    }

     week15_08_maze_DFS_boolean_true_false



    1.深度優先搜尋


    程式碼


    //week15_08_maze_DFS_visited_step_mousePressed_move
    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,0,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); // 繪製一個紅色方塊,起始位置在 (startJ, startI),大小為 40x40 像素
      
      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) { // 深度優先搜尋 (DFS) 方法
      if (i == 8 && j == 8) return true; // 如果走到目標位置 (8,8),返回 true
      
      if (maze[i][j] == 1) return false; // 如果當前格子是牆 (值為1),無法通行,返回 false
      if (visited[i][j] > 0) return false; // 如果這個位置已經訪問過,返回 false
      
      visited[i][j] = s; // 標記當前格子為訪問過,s 為步數或順序

      // 探索上下左右四個方向的格子,如果找到路徑則返回 true
      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; // 返回 false,表示無法找到路徑
    }

    void mousePressed() { // 當按下滑鼠時觸發
      visited[1][1] = 0;
      DFS(1, 1, 1); // 從迷宮的起點 (1, 1) 開始搜尋,步數初始值設為 1
    }

      








    沒有留言:

    張貼留言