PVector v0,v1,v;
PVector ball;
PVector wall0,wall1,N;
void setup(){
size(600,500);
v0= new PVector(300,600);//new PVector 類似image //球的起始點
v1= new PVector(300,300);//球的終點
v=PVector.sub(v1,v0).div(30);//(v1-v0)/10
ball=new PVector(v0.x,v0.y);
wall0=new PVector(280,200);
wall1=new PVector(300,350);
N=PVector.sub(wall0,wall1);//.rotate(10);//.rotate(-HALF_PI);
a=N.x; b=N.y;c=a*wall0.x+b*wall0.y;
}
void mousePressed(){
v=PVector.sub(v1,v0).div(10);
}
void draw(){
stroke(0);line(v0.x,v0.y,v1.x,v1.y);
ellipse(ball.x,ball.y,10,10);
if(collision(ball,PVector.add(ball,v))==true){
PVector N1=N.copy().normalize();
float len=PVector.dot(N1,v);
v.add(N1.mult(-2*len));
}
ball.add(v);
line(wall0.x,wall0.y,wall1.x,wall1.y);
stroke(255,0,0);line(wall0.x,wall0.y,wall0.x+N.x,wall0.x+N.y);
}
float a,b,c;
boolean collision(PVector p1, PVector p2){
if(a*p1.x+b*p1.y >= c && a*p2.x+b*p2.y <=c)return true;
if(a*p1.x+b*p1.y <= c && a*p2.x+b*p2.y >=c)return true;
return false;
}
計畫變更
原定要將球合乎方向前進,改為對手將球朝不同的x軸打擊,己方則要進行防守,時間歸0後即可過關
👉程式碼(主要更改部分為豆沙粉色 )
PShape obj;
PShape obj2;
PImage img;
PImage img2;
PImage img3;
PVector v0,v1,v;
void setup(){
size(600,500,P3D);///場景為3D
obj=loadShape("hand1.obj");
obj2=loadShape("hand2.obj");
camera(0,-70,120,0,0,0,0,1,0);
img=loadImage("vs.png");
img2=loadImage("me.png");
img3=loadImage("no.png");
}
float x=0,y=-25,z=0;//y為球上下高度
float vx=0,vy=0,vz=+0.2;///vz為前後
float obj2x=0;
void draw(){
lights();//打光
background(112,146,190);
fill(34,177,76);//綠色
box(100,5,120);//綠色球桌
pushMatrix();
translate(0,-10,0);
fill(255,0,0);//紅色
box(98,20,5);//紅色網子
popMatrix();
pushMatrix();
translate(-40,35,50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(40,35,50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(-40,35,-50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(40,35,-50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
lights();
fill(255);//球的顏色
float dx=(mouseX-width/2.5)/8.0-10 ,dy=(mouseY-height*0.9)/5.0+100;
pushMatrix();
translate(x,y,z);
lights();noStroke();sphere(3);
popMatrix();
pushMatrix();//正電paipai
translate(dx,-20,dy);//球拍高度//-20等於z軸
//box(10);
rotate(radians(180));
shape(obj,0,0);
stroke(0);
popMatrix();
pushMatrix();//負電paipai
translate(obj2x,-20,-60);
rotate(radians(180));
shape(obj2,0,0);
stroke(0);//line(-50,0,+50,0);
popMatrix();
if( dist( x,y,z, dx, -20, dy)<10 )
{
vz = -vz;//我方反彈
}
x+=vx;
y+=vy/2; //上下
z+=vz*20;//前後
vy+=0.98;
if(y>-10) vy=-vy*0.9;
//if(x<0) vx=-vx;///反彈!
if(z<-60)
{
vz=-vz;///對方的回彈
//x=x-1;
}
//負
if(z<-60 && x>=-5 && x<=0 )
{
x-=3;
}
else if(z<-60 && x>=-10 && x<-5 )
{
x+=10;
}
else if(z<-60 && x>=-15 && x<-10 )
{
x-=5;
}
else if(z<-60 && x>=-20 && x<-15 )
{
x+=5;
}
else if(z<-60 && x>=-25 && x<-20 )
{
x-=8;
}
else if(z<-60 && x>=-30 && x<-25 )
{
x+=4;
}
else if(z<-60 && x>=-35 && x<-30 )
{
x+=9;
}
else if(z<-60 && x>=-40 && x<-35 )
{
x-=2;
}
else if(z<-60 && x>=-45 && x<-40 )
{
x-=1;
}
else if(z<-60 && x>=-50 && x<-45 )
{
x+=5;
}
//正
else if(z<-60 && x>0 && x<5 )
{
x+=10;
}
else if(z<-60 && x>=5 && x<10 )
{
x-=30;
}
else if(z<-60 && x>=10 && x<15 )
{
x+=20;
}
else if(z<-60 && x>=15 && x<20 )
{
x+=3;
}
else if(z<-60 && x>=20 && x<25 )
{
x-=8;
}
else if(z<-60 && x>=25 && x<30 )
{
x-=5;
}
else if(z<-60 && x>=30 && x<35 )
{
x-=8;
}
else if(z<-60 && x>=35 && x<40 )
{
x+=10;
}
else if(z<-60 && x>=40 && x<45 )
{
x+=8;
}
else if(z<-60 && x>=45 && x<50)
{
x-=2;
}
//藍色拍子動
float paidx=obj2x-x;
obj2x-=paidx*0.2;
//obj2x=x;
//if(obj2x>0 && obj2x>2)obj2x=2;
//if(obj2x<0 && obj2x<-2)obj2x=-2;
image(img,-70,-60,width/20,height/20);
image(img2,45,-60,width/20,height/20);
image(img3,60,-50,width/30,height/30);
}
加入倒數計時器

👉程式碼(主要更改部分為豆沙粉色 )
PShape obj;
PShape obj2;
PImage img;
PImage img2;
PImage img3;
PVector v0,v1,v;
int time;
void setup(){
size(600,500,P3D);///場景為3D
obj=loadShape("hand1.obj");
obj2=loadShape("hand2.obj");
camera(0,-70,120,0,0,0,0,1,0);
img=loadImage("vs.png");
img2=loadImage("me.png");
img3=loadImage("no.png");
}
float x=0,y=-25,z=0;//y為球上下高度
float vx=0,vy=0,vz=+0.2;///vz為前後
float obj2x=0;
void draw(){
lights();//打光
background(112,146,190);
fill(34,177,76);//綠色
box(100,5,120);//綠色球桌
pushMatrix();
translate(0,-10,0);
fill(255,0,0);//紅色
box(98,20,5);//紅色網子
popMatrix();
pushMatrix();
translate(-40,35,50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(40,35,50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(-40,35,-50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(40,35,-50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
lights();
fill(255);//球的顏色
float dx=(mouseX-width/2.5)/8.0-10 ,dy=(mouseY-height*0.9)/5.0+100;
pushMatrix();
translate(x,y,z);
lights();noStroke();sphere(3);
popMatrix();
pushMatrix();//正電paipai
translate(dx,-20,dy);//球拍高度//-20等於z軸
//box(10);
rotate(radians(180));
shape(obj,0,0);
stroke(0);
popMatrix();
pushMatrix();//負電paipai
translate(obj2x,-20,-60);
rotate(radians(180));
shape(obj2,0,0);
stroke(0);//line(-50,0,+50,0);
popMatrix();
if( dist( x,y,z, dx, -20, dy)<10 )
{
vz = -vz;//我方反彈
}
x+=vx;
y+=vy/2; //上下
z+=vz*20;//前後
vy+=0.98;
if(y>-10) vy=-vy*0.9;
//if(x<0) vx=-vx;///反彈!
if(z<-60)
{
vz=-vz;///對方的回彈
//x=x-1;
}
//負
if(z<-60 && x>=-5 && x<=0 )
{
x-=3;
}
else if(z<-60 && x>=-10 && x<-5 )
{
x+=10;
}
else if(z<-60 && x>=-15 && x<-10 )
{
x-=5;
}
else if(z<-60 && x>=-20 && x<-15 )
{
x+=5;
}
else if(z<-60 && x>=-25 && x<-20 )
{
x-=8;
}
else if(z<-60 && x>=-30 && x<-25 )
{
x+=4;
}
else if(z<-60 && x>=-35 && x<-30 )
{
x+=9;
}
else if(z<-60 && x>=-40 && x<-35 )
{
x-=2;
}
else if(z<-60 && x>=-45 && x<-40 )
{
x-=1;
}
else if(z<-60 && x>=-50 && x<-45 )
{
x+=5;
}
//正
else if(z<-60 && x>0 && x<5 )
{
x+=10;
}
else if(z<-60 && x>=5 && x<10 )
{
x-=30;
}
else if(z<-60 && x>=10 && x<15 )
{
x+=20;
}
else if(z<-60 && x>=15 && x<20 )
{
x+=3;
}
else if(z<-60 && x>=20 && x<25 )
{
x-=8;
}
else if(z<-60 && x>=25 && x<30 )
{
x-=5;
}
else if(z<-60 && x>=30 && x<35 )
{
x-=8;
}
else if(z<-60 && x>=35 && x<40 )
{
x+=10;
}
else if(z<-60 && x>=40 && x<45 )
{
x+=8;
}
else if(z<-60 && x>=45 && x<50)
{
x-=2;
}
//藍色拍子動
float paidx=obj2x-x;
obj2x-=paidx*0.2;
image(img,-70,-60,width/20,height/20);//對手
image(img2,45,-60,width/20,height/20);//己方
image(img3,60,-50,width/30,height/30);//己方糰子
fill(#020F1F);//文字顏色
textSize(10);
text("Time:"+time,-20,-60);
time=60-(frameCount/60);//倒數計時60秒
}
程式碼可以參考第八週-TextSize
https://2021interaction.blogspot.com/2021/11/week08_61.html
加入AGAIN畫面
當球掉入Z>=100的地方則會跳出,將不能繼續遊戲

👉程式碼(主要更改部分為豆沙粉色 )
PShape obj;
PShape obj2;
PImage img;
PImage img2;
PImage img3;
PImage img4;
PImage img5;
PVector v0,v1,v;
int time;
void setup(){
size(600,500,P3D);///場景為3D
obj=loadShape("hand1.obj");
obj2=loadShape("hand2.obj");
camera(0,-70,120,0,0,0,0,1,0);
img=loadImage("vs.png");
img2=loadImage("me.png");
img3=loadImage("no.png");
img4=loadImage("again.png");
img5=loadImage("end.png");
}
float x=0,y=-25,z=0;//y為球上下高度
float vx=0,vy=0,vz=+0.2;///vz為前後
float obj2x=0;
void draw(){
lights();//打光
background(112,146,190);
fill(34,177,76);//綠色
box(100,5,120);//綠色球桌
pushMatrix();
translate(0,-10,0);
fill(255,0,0);//紅色
box(98,20,5);//紅色網子
popMatrix();
pushMatrix();
translate(-40,35,50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(40,35,50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(-40,35,-50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
pushMatrix();
translate(40,35,-50);
fill(#502C0F);//桌腳的顏色
box(10,70,10);//咖色桌腳
popMatrix();
lights();
fill(255);//球的顏色
float dx=(mouseX-width/2.5)/8.0-10 ,dy=(mouseY-height*0.9)/5.0+100;
pushMatrix();
translate(x,y,z);
lights();
noStroke();
sphere(3);
popMatrix();
pushMatrix();//正電paipai
translate(dx,-20,dy);//球拍高度//-20等於z軸
//box(10);
rotate(radians(180));
shape(obj,0,0);
stroke(0);
popMatrix();
pushMatrix();//負電paipai
translate(obj2x,-20,-60);
rotate(radians(180));
shape(obj2,0,0);
stroke(0);//line(-50,0,+50,0);
popMatrix();
if( dist( x,y,z, dx, -20, dy)<10 )
{
vz = -vz;//我方反彈
}
x+=vx;
y+=vy/2; //上下
z+=vz*20;//前後
vy+=0.98;
if(y>-10) vy=-vy*0.9;
//if(x<0) vx=-vx;///反彈!
if(z<-60)
{
vz=-vz;///對方的回彈
//x=x-1;
}
//負
if(z<-60 && x>=-5 && x<=0 )
{
x-=3;
}
else if(z<-60 && x>=-10 && x<-5 )
{
x+=10;
}
else if(z<-60 && x>=-15 && x<-10 )
{
x-=5;
}
else if(z<-60 && x>=-20 && x<-15 )
{
x+=5;
}
else if(z<-60 && x>=-25 && x<-20 )
{
x-=8;
}
else if(z<-60 && x>=-30 && x<-25 )
{
x+=4;
}
else if(z<-60 && x>=-35 && x<-30 )
{
x+=9;
}
else if(z<-60 && x>=-40 && x<-35 )
{
x-=2;
}
else if(z<-60 && x>=-45 && x<-40 )
{
x-=1;
}
else if(z<-60 && x>=-50 && x<-45 )
{
x+=5;
}
//正
else if(z<-60 && x>0 && x<5 )
{
x+=10;
}
else if(z<-60 && x>=5 && x<10 )
{
x-=30;
}
else if(z<-60 && x>=10 && x<15 )
{
x+=20;
}
else if(z<-60 && x>=15 && x<20 )
{
x+=3;
}
else if(z<-60 && x>=20 && x<25 )
{
x-=8;
}
else if(z<-60 && x>=25 && x<30 )
{
x-=5;
}
else if(z<-60 && x>=30 && x<35 )
{
x-=8;
}
else if(z<-60 && x>=35 && x<40 )
{
x+=10;
}
else if(z<-60 && x>=40 && x<45 )
{
x+=8;
}
else if(z<-60 && x>=45 && x<50)
{
x-=2;
}
//藍色拍子動
float paidx=obj2x-x;
obj2x-=paidx*0.2;
//obj2x=x;
//if(obj2x>0 && obj2x>2)obj2x=2;
//if(obj2x<0 && obj2x<-2)obj2x=-2;
image(img,-70,-60,width/20,height/20);//對手
image(img2,45,-60,width/20,height/20);//己方
image(img3,60,-50,width/30,height/30);//己方糰子
textSize(10);
text("Time:"+time,-20,-60);
time=60-(frameCount/60);//倒數計時60秒
noStroke();
if(z>=100)///again
{
camera(0,0,120,0,0,0,0,1,0);
background(112,146,190);
image(img4,-83,-70,width/3.5,height/3.5);
}
}
AGAIN圖片
WIN(END)圖片
加入WIN(END)畫面
當時間歸0後即會跳出結束畫面
👉增加程式碼
if(time<0)
{
camera(0,0,120,0,0,0,0,1,0);
background(112,146,190);
image(img5,-83,-70,width/3.5,height/3.5);
}
那麼簡單做個收尾
遊戲規則說明
首先由對方擊球給己方,己方需將球打回去,對方會偵測打回來的球的x軸來改變下一次擊球的位置,如己方未能夠打到球,導致球的z軸掉進>=100的區域,則會顯示try again的圖示,遊戲結束。如果能夠在時間結束(倒數計時為0)前,準確打到對方的每一顆擊球,則會顯示贏此場遊戲的圖示。能夠藉著改變程式碼中球的速度、不同擊球位置、時間,依照每個人的需求,打造不一樣的等級。
原定計畫未完成
1:3D球網
2:控制發球強度
3:擊球聲
4:計分
能夠更好部分
1:用計算法向量的方式使球回彈
2:讓對手也可能打不到球(現在對手是無敵的)
期末作品製作心得
透過這次期末作品的製作,能夠將以前所教過的所有功能整合,因為題目由自己而定,有一個機會選擇想做的小遊戲。雖然過程很辛苦且與預想的製作結果有些差異,但最後能夠做出一個打桌球遊戲真的很開心!
如果喜歡我的部落格的話
請幫我按右上角的愛心(根本按不下去)
也可以按右上角的小鈴鐺(這也按不下去)
才不會錯過我的更新哦!😉
我們下次見!!!
沒有留言:
張貼留言