上周做出了白色母球如果被射進六邊的黑色球袋中,就會被扣分
這周我想把剩餘的撞球寫完,並且改良了一下玩法
如果將規則改為,在規定的時間內看看可以射出多少顆母球呢?
當然事情並不會這麼簡單,若場地上還有其他障礙物,且被碰到後會倒扣一分呢?
當然我們要先結合之前學過的知識來繼續寫遊戲,目前用到了音樂播放、布林變數、滑鼠事件、碰撞偵測等等
像是如果撞到了其他顏色的球就會死亡隨機重生在場地上,所以還要設置一個回復按鍵,我們只需要改寫上周最後一段的reset()函式
void reset(){
ballX=random(1100);//隨機生成的x座標範圍
ballY=random(750);//隨機生成的y座標範圍
shooting=false;
ballVX=0;
ballVY=0;
}
只要是隨機就會運用到random這個函式,但範圍不要設置超出場地,因此取(1100,750)的值內
接下來還需要使用場景切換,宣告初始場景並在draw()函式執行該場景會需要做到的指令(已經先將程式碼分成兩頁,當有需要使用到分頁程式碼時在進行呼叫)
程式碼主頁
import processing.sound.*;//聲音的函式庫
SoundFile sound1;//音檔1
PImage home_img,start_img,go_img;//讀入封面,開始遊戲,點go
PImage table_img,sayrule_img,stage4_img;//讀入遊戲畫面桌子,規則說明
int w=1200,h=750,stage=1;//畫面寬度,畫面高度,當前場景編號
void setup(){//基本設定
size(1200,900);//視窗長寬
sound1=new SoundFile(this,"music01.mp3");//載入音樂
sound1.play();//播放音樂
home_img = loadImage("home.png");//載入封面圖home.png
start_img = loadImage("start.png");//載入開始遊戲鍵start.png
go_img = loadImage("go.png");//載入go.png
table_img = loadImage("table.png");//載入遊戲畫面table.png
sayrule_img = loadImage("sayrule.png");//載入規則說明sayrule.png
stage4_img = loadImage("stage4.png");//載入stage4.png
}
void draw(){//畫圖
if(stage==1){//初始頁面舞台1,首頁場景設定
image(home_img,0,0,1200,900);//home圖片的x,y座標(0,0),(1200,900)是圖片寬高
image(start_img,1000,750,150,75);//start圖片的x,y座標(1000,600),(150,75)是圖片寬高
if(pressed_start == true)rect(1000,600,150,75);//按下開始遊戲的按鈕後
}
if(stage==2){//當被切換到舞台2進入遊戲畫面的設定
image(sayrule_img,0,0,1200,900);//可以調整圖片大小,規則說明的x,y座標(0,0),(1200,900)是圖片寬高
image(go_img,860,750,150,75);//rule圖片的x,y座標(800,600),(150,75)是圖片寬高
if(pressed_go == true)rect(860,750,150,75);//按下go的按鈕後
}
if(stage==3){//當被切到舞台3時
draw2();//執行分頁stage3的程式
}
if(stage==4){//當被切換到舞台4時
image(stage4_img,0,0,1200,900);//可以調整圖片大小,規則說明的x,y座標(0,0),(1200,900)是圖片寬高
}
}
boolean pressed_start=false;//預設按壓開始遊戲鍵為關閉狀態
boolean pressed_go=false;//預設按壓規則介紹鍵為關閉狀態
void mousePressed(){//按下滑鼠時
if(stage==1){//當被切換到舞台1
if(1000<mouseX && mouseX < 1000+200 && 750<mouseY && mouseY<750+100){
//判定圖片範圍,xy座標(1000,600),1000+200就是判定範圍有多寬,600+100就是判定範圍有多高
pressed_start=true;//如果按壓開始遊戲鍵成立
stage=2;//切換到場景2,介紹遊戲
pressed_start=false;//關閉按下開始鍵
}
}
if(stage==2){//當被切換到舞台2
if(860<mouseX && mouseX < 860+150 && 750<mouseY && mouseY<750+80){
//判定圖片範圍,xy座標(1000,600),1000+200就是判定範圍有多寬,750+100就是判定範圍有多高
pressed_go=true;//如果按壓開始遊戲鍵成立
stage=3;//切換到場景3,開始遊戲
pressed_go=false;//關閉按下go鍵
}
}
if(stage==3){//當被切換到舞台3
len0 = dist(ballX,ballY,mouseX,mouseY);//計算白色母球和鼠標(X,Y)座標的距離向量
}
}
void mouseReleased(){//放開滑鼠時
if(stage==3){//當切換到舞台3時
len1 = dist(ballX,ballY,mouseX,mouseY);//計算白色母球和鼠標(X,Y)座標的距離向量
float v = len1-len0;//計算兩者向量相減後的力矩
ballVX = -v * cos(angle);//COS角度
ballVY = -v * sin(angle);//SIN角度
shooting=true;//打開布林變數,球可以被射出
}
}
程式碼分頁(stage3)
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 ballX=180,ballY=200,ballVX=0,ballVY=0,angle=0;//設定球一開始出現的xy位置,以及角度初始化
float score=0;//將成績初始化歸0
float len0=0,len1=0;//距離向量歸0
boolean shooting=false;//射擊的布林變數預設關閉
void draw2(){
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是長寬
fill(#A76565);//棕色的長方形
rect(0,750,1200,300);//測試畫長方(47,47是x,y座標/1110,660是長寬
fill(#FFFFFF);//白色的球
ellipse(ballX,ballY,30,30);//畫個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){//計算白色母球和球袋的XY座標距離是否小於30
score++;//如果母球射入球袋就會扣分
reset();//隨機復活
println(score);//顯示成績
}
ballX += ballVX/10;
ballY += ballVY/10;
ballVX*=0.99;//替球增加摩擦力
ballVY*=0.99;//替球增加摩擦力
}
}
void reset(){//隨機生成在場地上
ballX=random(1100);//隨機X座標
ballY=random(750);//隨機Y座標
shooting=false;//關閉布林函數,預設非射擊狀態
ballVX=0;//X方向的速度歸0
ballVY=0;//Y方向的速度歸0
}
然後就可以得到這幾個頁面(會播放音樂
1.遊戲進行中,還會用到計時器的寫法
先宣告時間變數(宣告在哪頁都沒有關係)
int startTime;//遊戲開始時間
int Time;//計時
然後寫進分頁的void draw2()函式裡
int m = (150-((millis()/1000)-(startTime/1000)))/60%60;//計時器,毫秒是千分之一秒,150秒約2:30,因為要倒數就要%60,設定分鐘
int s = (150-((millis()/1000)-(startTime/1000)))%60;//計時器,毫秒是千分之一秒,150秒約2:30,因為要倒數就要%60,設定秒鐘
String mm = nf(m, 2);//00,ex:01分鐘
String ss = nf(s, 2);//00,ex:01秒鐘
String time = "剩下"+":"+mm+":"+ss;//顯示剩餘的時間
2.若想控制字體(ex:剩餘時間的剩餘),就使用PFont font=createFont("字體名稱",字體大小);來固定
PFont font=createFont("標楷體",20);//設定創建字體,全部的字體都會被設置為標楷體 textFont(font);//文字字體
將1、2點結合起來,如程式所示
程式主頁
import processing.sound.*;//聲音的函式庫
SoundFile sound1;//音檔1
PImage home_img,start_img,go_img;//讀入封面,開始遊戲,點go
PImage table_img,sayrule_img,stage4_img;//讀入遊戲畫面桌子,規則說明
int w=1200,h=750,stage=1;//畫面寬度,畫面高度,當前場景編號
void setup(){//基本設定
size(1200,900);//視窗長寬
PFont font=createFont("標楷體",20);//設定創建字體,全部的字體都會被設置為標楷體
textFont(font);//文字字體
sound1=new SoundFile(this,"music01.mp3");//載入音樂
sound1.play();//播放音樂
home_img = loadImage("home.png");//載入封面圖home.png
start_img = loadImage("start.png");//載入開始遊戲鍵start.png
go_img = loadImage("go.png");//載入go.png
table_img = loadImage("table.png");//載入遊戲畫面table.png
sayrule_img = loadImage("sayrule.png");//載入規則說明sayrule.png
stage4_img = loadImage("stage4.png");//載入stage4.png
}
void draw(){//畫圖
if(stage==1){//初始頁面舞台1,首頁場景設定
image(home_img,0,0,1200,900);//home圖片的x,y座標(0,0),(1200,900)是圖片寬高
image(start_img,1000,750,150,75);//start圖片的x,y座標(1000,600),(150,75)是圖片寬高
if(pressed_start == true)rect(1000,600,150,75);//按下開始遊戲的按鈕後
}
if(stage==2){//當被切換到舞台2進入遊戲畫面的設定
image(sayrule_img,0,0,1200,900);//可以調整圖片大小,規則說明的x,y座標(0,0),(1200,900)是圖片寬高
image(go_img,860,750,150,75);//rule圖片的x,y座標(800,600),(150,75)是圖片寬高
if(pressed_go == true)rect(860,750,150,75);//按下go的按鈕後
}
if(stage==3){//當被切到舞台3時
draw2();//執行分頁stage3的程式
}
if(stage==4){//當被切換到舞台4時
image(stage4_img,0,0,1200,900);//可以調整圖片大小,規則說明的x,y座標(0,0),(1200,900)是圖片寬高
}
}
boolean pressed_start=false;//預設按壓開始遊戲鍵為關閉狀態
boolean pressed_go=false;//預設按壓規則介紹鍵為關閉狀態
void mousePressed(){//按下滑鼠時
if(stage==1){//當被切換到舞台1
if(1000<mouseX && mouseX < 1000+200 && 750<mouseY && mouseY<750+100){
//判定圖片範圍,xy座標(1000,600),1000+200就是判定範圍有多寬,600+100就是判定範圍有多高
pressed_start=true;//如果按壓開始遊戲鍵成立
stage=2;//切換到場景2,介紹遊戲
pressed_start=false;//關閉按下開始鍵
}
}
if(stage==2){//當被切換到舞台2
if(860<mouseX && mouseX < 860+150 && 750<mouseY && mouseY<750+80){
//判定圖片範圍,xy座標(1000,600),1000+200就是判定範圍有多寬,750+100就是判定範圍有多高
pressed_go=true;//如果按壓開始遊戲鍵成立
stage=3;//切換到場景3,開始遊戲
pressed_go=false;//關閉按下go鍵
}
}
if(stage==3){//當被切換到舞台3
len0 = dist(ballX,ballY,mouseX,mouseY);//計算白色母球和鼠標(X,Y)座標的距離向量
}
}
void mouseReleased(){//放開滑鼠時
if(stage==3){//當切換到舞台3時
len1 = dist(ballX,ballY,mouseX,mouseY);//計算白色母球和鼠標(X,Y)座標的距離向量
float v = len1-len0;//計算兩者向量相減後的力矩
ballVX = -v * cos(angle);//COS角度
ballVY = -v * sin(angle);//SIN角度
shooting=true;//打開布林變數,球可以被射出
}
}
程式分頁(stage3)
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 ballX=180,ballY=200,ballVX=0,ballVY=0,angle=0;//設定球一開始出現的xy位置,以及角度初始化
float score=0;//將成績初始化歸0
float len0=0,len1=0;//距離向量歸0
boolean shooting=false;//射擊的布林變數預設關閉
int startTime;//遊戲開始時間
int Time;//計時
void draw2(){
//場景地圖
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是長寬
fill(#A76565);//棕色的長方形
rect(0,750,1200,300);//測試畫長方(47,47是x,y座標/1110,660是長寬
//計時器
int m = (150-((millis()/1000)-(startTime/1000)))/60%60;//計時器,毫秒是千分之一秒,150秒約2:30,因為要倒數就要%60,設定分鐘
int s = (150-((millis()/1000)-(startTime/1000)))%60;//計時器,毫秒是千分之一秒,150秒約2:30,因為要倒數就要%60,設定秒鐘
String mm = nf(m, 2);//00,ex:01分鐘
String ss = nf(s, 2);//00,ex:01秒鐘
String time = "剩下"+":"+mm+":"+ss;//顯示剩餘的時間
if(millis()-startTime>=150000){//如果時間超過或剛好等於兩分半,切換到場景4
stage=4;
}else if(millis()-startTime<=150000){//如果時間還沒超過兩分半,就還在倒數
fill(#FFFFFF);//剩餘時間的白色字體顏色
textSize(40);//字體大小
text(time,20,830);//時間,X座標20,Y座標830
}
//母球相關
fill(#FFFFFF);//白色的球
ellipse(ballX,ballY,30,30);//畫個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){//計算白色母球和球袋的XY座標距離是否小於30
score++;//如果母球射入球袋就會扣分
reset();//隨機復活
println(score);//顯示成績
}
ballX += ballVX/10;
ballY += ballVY/10;
ballVX*=0.99;//替球增加摩擦力
ballVY*=0.99;//替球增加摩擦力
}
}
void reset(){//隨機生成在場地上
ballX=random(1100);//隨機X座標
ballY=random(750);//隨機Y座標
shooting=false;//關閉布林函數,預設非射擊狀態
ballVX=0;//X方向的速度歸0
ballVY=0;//Y方向的速度歸0
}
成績的顯示也是依樣畫葫蘆
加在draw2()的函式內
//成績顯示
fill(#FFFFFF);//白色字體顏色
textSize(40);//字體大小
text(score,300,830);//成績
以及設置了從頭到尾都會出現的障礙物(紅球),還有不同時間會持續存在並干擾玩家的其他色球
首先都要先宣告變數
float ballX2=200,ballY2=300,ballVX2=0,ballVY2=0;//設定球一開始出現的XY位置
float ballX3=300,ballY3=400,ballVX3=0,ballVY3=0;//設定球一開始出現的XY位置
float ballX4=400,ballY4=500,ballVX4=0,ballVY4=0;//設定球一開始出現的XY位置
float ballX5=400,ballY5=500,ballVX5=0,ballVY5=0;//設定球一開始出現的XY位置
float ballX6=200,ballY6=300,ballVX6=0,ballVY6=0;//設定球一開始出現的XY位置
然後在draw2()函式中寫出對應條件
//一直在場上的紅球
fill(#FF6A6A);//粉色的球
ellipse(random(1100),random(750),20,20);//畫個20*20圓形
//frameRate(3);//每秒刷新多少幀數,一秒鐘刷新10幀
if(shooting && dist(ballX,ballY,ballX2,ballY2)<15){//計算白色母球和橘球的XY座標距離是否小於15
score--;//如果母球射入球袋就會扣分
reset();//隨機復活
println(score);//顯示成績
}
//不同時間會跑出來干擾的色球
if(m==2 && s>0 && s<15){//在2:00~2:15秒時,會有橘色球來搗亂
fill(#FFCB1C);//橘色的球
ellipse(random(500),random(600),20,20);//畫個20*20圓形
//frameRate(3);//每秒刷新多少幀數,一秒鐘刷新10幀
if(shooting && dist(ballX,ballY,ballX6,ballY6)<20){//計算白色母球和橘球的XY座標距離是否小於20
score--;//如果碰到就會扣分
reset();//隨機復活
println(score);//顯示成績
}
}
if(m==1 && s>0 && s<59){//在1:00~1:59秒時,會有藍色球來搗亂
fill(#93B9EA);//藍色的球
ellipse(random(900),random(600),20,20);//畫個20*20圓形
//frameRate(3);//每秒刷新多少幀數,一秒鐘刷新10幀
if(shooting && dist(ballX,ballY,ballX3,ballY3)<15){//計算白色母球和藍球的XY座標距離是否小於15
score--;//如果碰到就會扣分
reset();//隨機復活
println(score);//顯示成績
}
}
if(m==1 && s>0 && s<30){//在1:00~1:30秒時,會有綠色球來搗亂
fill(#3BB281);//綠色的球
ellipse(random(900),random(600),20,20);//畫個20*20圓形
//frameRate(3);//每秒刷新多少幀數,一秒鐘刷新10幀
if(shooting && dist(ballX,ballY,ballX5,ballY5)<20){//計算白色母球和綠球的XY座標距離是否小於20
score--;//如果碰到就會扣分
reset();//隨機復活
println(score);//顯示成績
}
}
if(m==0 && s>0 && s<59){//在0:00~0:59秒時,會有藍色球來搗亂
fill(#93B9EA);//藍色的球
ellipse(random(800),random(300),20,20);//畫個20*20圓形
//frameRate(3);//每秒刷新多少幀數,一秒鐘刷新10幀
if(shooting && dist(ballX,ballY,ballX3,ballY3)<20){//計算白色母球和藍球的XY座標距離是否小於20
score--;//如果碰到就會扣分
reset();//隨機復活
println(score);//顯示成績
}
}
if(m==0 && s>0 && s<59){//在0:00~0:59秒時,會有黃色球來搗亂
fill(#FFFCA7);//黃色的球
ellipse(random(1000),random(800),20,20);//畫個20*20圓形
//frameRate(3);//每秒刷新多少幀數,一秒鐘刷新10幀
if(shooting && dist(ballX,ballY,ballX4,ballY4)<30){//計算白色母球和黃球的XY座標距離是否小於30
score--;//如果碰到就會扣分
reset();//隨機復活
println(score);//顯示成績
}
}







沒有留言:
張貼留言