2023年1月11日 星期三

TC*(˙Ⱉ˙ฅ)​-week16

這周來寫當白色母球撞入黑色球袋中,會被扣分的情況

我們先導入撞球桌,將事先準備好的撞球桌圖片放入processing
然後按照前幾周教的依樣畫葫蘆

PImage table_img;//讀入圖片桌子
void setup(){
  size(1200,750);//視窗大小
  table_img = loadImage("table.png");
}
void draw(){
 //background(table_img);
//可以直接將table當作背景,不過視窗大小要跟圖片大小一樣才能夠顯示出來
  image(table_img,0,0,1200,750);
//可以調整圖片大小,table圖片的x,y座標(0,0),(1200,750)是圖片寬高
}


接著畫出一顆白色母球來,打撞球通常都會要瞄準和蓄力,所以我們還需要畫出會繞著白色母球的瞄準線,當點擊力道強就會射的越大力

PImage table_img;//讀入圖片桌子
void setup(){
  size(1200,750);//視窗大小
  table_img = loadImage("table.png");//讀入桌子圖片
}
float ballX=180,ballY=200,ballVX=0,ballVY=0,angle=0;//設定球一開始出現的xy位置,以及角度初始化
boolean shooting=false;//預設布林函數是關閉狀態
void draw(){
  image(table_img,0,0,1200,750);//可以調整圖片大小,table圖片的x,y座標(0,0),(1200,750)是圖片寬高
  
  fill(#FFFFFF);//白色的球
  ellipse(ballX,ballY,20,20);//畫個20*20圓形
  angle = atan2(mouseY-ballY,mouseX-ballX);//算出角度的tan2(),這裡是公式
  
  if(shooting==false){//如果符合布林變數為關閉時
    strokeWeight(10);//粗度為10的直線
    stroke(#FFFF00);//直線顏色是黃色
    line(ballX,ballY,ballX+cos(angle)*100,ballY+sin(angle)*100);//x,y座標固定,
    
    strokeWeight(5);//粗度為5的直線
    stroke(#0000FF);//直線顏色是藍色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(3);//粗度為3的直線
    stroke(#00FF00);//直線顏色是綠色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(1);//粗度為1的直線
    stroke(0);//直線顏色是黑色
    line(ballX,ballY,mouseX,mouseY);//x,y座標固定,mouse會隨著滑鼠移動而改變線的長度
  }
}
float len0=0,len1=0;//預設向量為0
void mousePressed(){//滑鼠點擊
  len0 = dist(ballX,ballY,mouseX,mouseY);//母球和鼠標之間的x,y座標距離
}



可以從圖片看出來,黃色線會隨著球進行轉動,黑色線就是鼠標與白色母球之間的距離,藍綠色則是點擊蓄力的大小

既然都畫出球並給予瞄準線了,接下來我們要做的就是讓球可以射出去,並且不超過邊界,但球射出去會一直跑走該怎麼辦?
沒錯,還需要給球增加摩擦力!!這樣當球被推出去的時候才不會無止境的滾來滾去
以及當我們不小心瞄準錯位置,一定會希望有個重置的按紐,我們可以設置一個復原鍵r,按下復原鍵就可以讓球回到原來的位置進行瞄準

PImage table_img;//讀入圖片桌子
void setup(){
  size(1200,750);
  table_img = loadImage("table.png");
}
float ballX=180,ballY=200,ballVX=0,ballVY=0,angle=0;//設定球一開始出現的xy位置,以及角度初始化
boolean shooting=false;
void draw(){
  //background(table_img);//可以直接將table當作背景,不過視窗大小要跟圖片大小一樣才能夠顯示出來
  image(table_img,0,0,1200,750);//可以調整圖片大小,table圖片的x,y座標(0,0),(1200,750)是圖片寬高
  
  fill(#FFFFFF);//白色的球
  ellipse(ballX,ballY,20,20);//畫個20*20圓形
  angle = atan2(mouseY-ballY,mouseX-ballX);//算出角度的tan2(),這裡是公式
  
  if(shooting==false){
    strokeWeight(10);//粗度為10的直線
    stroke(#FFFF00);//直線顏色是黃色
    line(ballX,ballY,ballX+cos(angle)*100,ballY+sin(angle)*100);//x,y座標固定,
    
    strokeWeight(5);//粗度為5的直線
    stroke(#0000FF);//直線顏色是藍色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(3);//粗度為3的直線
    stroke(#00FF00);//直線顏色是綠色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(1);//粗度為1的直線
    stroke(0);//直線顏色是黑色
    line(ballX,ballY,mouseX,mouseY);//x,y座標固定,mouse會隨著滑鼠移動而改變線的長度
  }
  if(ballX+ballVX>1200-5 || ballX+ballVX<10){//ballX+vx>1200控制右邊x邊界,ballX+vx<10控制左邊x邊界
    ballVX=-ballVX;//被反彈
  }
  if(ballY+ballVY>720-5 || ballY+ballVY<25){//ballY+vy>720控制下面y邊界,ballY+vy<10控制上面y邊界
    ballVY=-ballVY;//被反彈
  }
    ballX += ballVX/10;
    ballY += ballVY/10;
    ballVX*=0.99;//替球增加摩擦力
    ballVY*=0.99;//替球增加摩擦力
}
float len0=0,len1=0;
void mousePressed(){//滑鼠點擊
  len0 = dist(ballX,ballY,mouseX,mouseY);
}
void mouseReleased(){//放開滑鼠時
  len1 = dist(ballX,ballY,mouseX,mouseY);//計算鼠標和母球的XY座標
  float v = len1-len0;
  ballVX = -v * cos(angle);
  ballVY = -v * sin(angle);
  shooting=true;
}
void keyPressed(){//按下按鍵時
  if(key=='r')reset();//按下R執行reset()函式
}
void reset(){//回復設置
  ballX=180;
  ballY=200;
  shooting=false;
  ballVX=0;
  ballVY=0;
}




就可以讓球到處彈射了!!


然後下一步我們要寫出當母球不小心掉入球袋時會扣分的情況,在那之前我們必須要先知道球袋的位置才行

所以我們可以利用,當滑鼠移動事件的函式,如果我們移動了鼠標,就印出鼠標所在的位置來寫出球袋的位置
void mouseMoved(){
  println(mouseX,mouseY);//印出滑鼠x,y的位置
}


加入程式裡面就會變成
PImage table_img;//讀入圖片桌子
void setup(){
  size(1200,750);
  table_img = loadImage("table.png");
}
float ballX=180,ballY=200,ballVX=0,ballVY=0,angle=0;//設定球一開始出現的xy位置,以及角度初始化
boolean shooting=false;
void draw(){
  //background(table_img);//可以直接將table當作背景,不過視窗大小要跟圖片大小一樣才能夠顯示出來
  image(table_img,0,0,1200,750);//可以調整圖片大小,table圖片的x,y座標(0,0),(1200,750)是圖片寬高
  fill(#2B793A);//綠色的長方形
  rect(47,47,1110,660);//測試畫長方(47,47是x,y座標/1110,660是長寬
  //rect(500,500,1000,1400);//測試畫長方
  
  fill(#FFFFFF);//白色的球
  ellipse(ballX,ballY,20,20);//畫個20*20圓形
  angle = atan2(mouseY-ballY,mouseX-ballX);//算出角度的tan2(),這裡是公式
  
  if(shooting==false){
    strokeWeight(10);//粗度為10的直線
    stroke(#FFFF00);//直線顏色是黃色
    line(ballX,ballY,ballX+cos(angle)*100,ballY+sin(angle)*100);//x,y座標固定,
    
    strokeWeight(5);//粗度為5的直線
    stroke(#0000FF);//直線顏色是藍色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(3);//粗度為3的直線
    stroke(#00FF00);//直線顏色是綠色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(1);//粗度為1的直線
    stroke(0);//直線顏色是黑色
    line(ballX,ballY,mouseX,mouseY);//x,y座標固定,mouse會隨著滑鼠移動而改變線的長度
  }

  if(ballX+ballVX>1200-5 || ballX+ballVX<10){//ballX+vx>1200控制右邊x邊界,ballX+vx<10控制左邊x邊界
    ballVX=-ballVX;//被反彈
  }
  if(ballY+ballVY>720-5 || ballY+ballVY<25){//ballY+vy>720控制下面y邊界,ballY+vy<10控制上面y邊界
    ballVY=-ballVY;//被反彈
  }
    ballX += ballVX/10;
    ballY += ballVY/10;
    ballVX*=0.99;//替球增加摩擦力
    ballVY*=0.99;//替球增加摩擦力
}

float len0=0,len1=0;
void mousePressed(){//滑鼠點擊
  len0 = dist(ballX,ballY,mouseX,mouseY);
}
void mouseReleased(){//放開滑鼠時
  len1 = dist(ballX,ballY,mouseX,mouseY);//計算鼠標和母球的XY座標
  float v = len1-len0;
  ballVX = -v * cos(angle);
  ballVY = -v * sin(angle);
  shooting=true;
}
void mouseMoved(){
  //println(mouseX,mouseY);//印出滑鼠x,y的位置
}
void keyPressed(){//按下按鍵時
  if(key=='r')reset();//按下R執行reset()函式
}
void reset(){//回復設置
  ballX=180;
  ballY=200;
  shooting=false;
  ballVX=0;
  ballVY=0;
}

可以看到圖片左下角會顯示座標,將每個洞的座標都記下來吧!!
我們以陣列的形式去記住球袋的位置
float [] holeX={50,600,1148,50,600,1151};//48,600,1150,65,600,1150
float [] holeY={52,46,57,692,703,695};//50,50,60,690,700,700


再來就是要生成球袋,並且讓母球打入球袋時會扣分了,為了美觀我們順便也畫個場地~
PImage table_img;//讀入圖片桌子
void setup(){
  size(1200,750);
  table_img = loadImage("table.png");
}
float ballX=180,ballY=200,ballVX=0,ballVY=0,angle=0;//設定球一開始出現的xy位置,以及角度初始化
boolean shooting=false;
void draw(){
  //background(table_img);//可以直接將table當作背景,不過視窗大小要跟圖片大小一樣才能夠顯示出來
  image(table_img,0,0,1200,750);//可以調整圖片大小,table圖片的x,y座標(0,0),(1200,750)是圖片寬高
  fill(#2B793A);//綠色的長方形
  rect(47,47,1110,660);//測試畫長方(47,47是x,y座標/1110,660是長寬
  //rect(500,500,1000,1400);//測試畫長方
  
  fill(#FFFFFF);//白色的球
  ellipse(ballX,ballY,20,20);//畫個20*20圓形
  angle = atan2(mouseY-ballY,mouseX-ballX);//算出角度的tan2(),這裡是公式
  
  if(shooting==false){
    strokeWeight(10);//粗度為10的直線
    stroke(#FFFF00);//直線顏色是黃色
    line(ballX,ballY,ballX+cos(angle)*100,ballY+sin(angle)*100);//x,y座標固定,
    
    strokeWeight(5);//粗度為5的直線
    stroke(#0000FF);//直線顏色是藍色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(3);//粗度為3的直線
    stroke(#00FF00);//直線顏色是綠色
    line(ballX,ballY,ballX+cos(angle)*len0,ballY+sin(angle)*len0);//x,y座標固定,
    
    strokeWeight(1);//粗度為1的直線
    stroke(0);//直線顏色是黑色
    line(ballX,ballY,mouseX,mouseY);//x,y座標固定,mouse會隨著滑鼠移動而改變線的長度
  }
  if(ballX+ballVX>1200-5 || ballX+ballVX<10){//ballX+vx>1200控制右邊x邊界,ballX+vx<10控制左邊x邊界
    ballVX=-ballVX;
  }
  if(ballY+ballVY>720-5 || ballY+ballVY<25){//ballY+vy>720控制下面y邊界,ballY+vy<10控制上面y邊界
    ballVY=-ballVY;
  }
  for(int i=0;i<6;i++){
    fill(#000000);//黑色的球袋
    ellipse(holeX[i],holeY[i],50,50);//最後面兩個數字是桌面六個圓形洞大小
    if(shooting && dist(ballX,ballY,holeX[i],holeY[i])<30){
     score--;//如果母球射入球袋就會扣分
     reset();
     println(score);
    }
    ballX += ballVX/10;
    ballY += ballVY/10;
    ballVX*=0.99;//替球增加摩擦力
    ballVY*=0.99;//替球增加摩擦力
  }
}
float [] holeX={50,600,1148,50,600,1151};//48,600,1150,65,600,1150
float [] holeY={52,46,57,692,703,695};//50,50,60,690,700,700
float score=0;
float len0=0,len1=0;
void mousePressed(){//滑鼠點擊
  len0 = dist(ballX,ballY,mouseX,mouseY);
}
void mouseReleased(){//放開滑鼠時
  len1 = dist(ballX,ballY,mouseX,mouseY);
  float v = len1-len0;
  ballVX = -v * cos(angle);
  ballVY = -v * sin(angle);
  shooting=true;
}
void mouseMoved(){
  //println(mouseX,mouseY);//印出滑鼠x,y的位置
}
void keyPressed(){
  if(key=='r')reset();
}
void reset(){
  ballX=180;
  ballY=200;
  shooting=false;
  ballVX=0;
  ballVY=0;
}

可以看見如果球不小心進到了球袋內就會被重置,並且左下角的分數會顯示被扣了一分
下周將會統合之前學過的程式,讓遊戲成形

沒有留言:

張貼留言