Week14:
本周主要解决游戏中物件碰撞的问题,利用两个物体接触侦测解决,有顶点包含和外积解法
1.正方形与正方形碰撞侦测
正方形与正方形之间碰撞侦测的方法,确保正方形的顶点在另一个正方形当中,需要做出两个侦测,不然会导致其中一个正方形出现差错。该方法根据两个正方形顶点的位置关系进行判断,容易理解。
float x1,y1,w1,h1;
float x2=0,y2=0,w2=100,h2=100;
void setup(){
size(400,400);
w1=random(40,80);
h1=random(40,80);
x1=random(400-w1);
y1=random(400-h1);
}
void draw(){
background(128);
if(testCollision() || testCollision2()) fill(255,0,0);//如果两个侦测回传值都为true,则正方形变红
else fill(255);
rect(x1,y1,w1,h1);
noFill(); rect(x2,y2,w2,h2);
x2=mouseX-w2/2;
y2=mouseY-h2/2;
}
boolean testCollision2(){//将正方形四个顶点放入oneCollision2函式经行侦测
if(oneCollision2(x1,y1)) return true;
else if(oneCollision2(x1+w1,y1)) return true;
else if(oneCollision2(x1+w1,y1+h1)) return true;
else if(oneCollision2(x1,y1+h1)) return true;
else return false;
}
boolean oneCollision2(float x,float y){//如果四个顶点都在另一个正方形的里面,回传true
if(x2<x && x<x2+w2 && y2<y && y<y2+h2) return true;
else return false;
}
boolean testCollision(){
if(oneCollision(x2,y2)) return true;
else if(oneCollision(x2+w2,y2)) return true;
else if(oneCollision(x2+w2,y2+h2)) return true;
else if(oneCollision(x2,y2+h2)) return true;
else return false;
}
boolean oneCollision(float x,float y){
if(x1<x && x<x1+w1 && y1<y && y<y1+h1) return true;
else return false;
}
2-1.三角形和正方形的碰撞侦测
该方法和上面的正方形与正方形碰撞侦测类似,都是用顶点位置判断,但对于三角形和正方形不适用,因为如果三角形三个顶点都没在四边形里,但正方形刚好进入,则会侦测失败,因此该方法不采用,用外积法。
float tx,ty;
float rx,ry;
void setup(){
size(300,300);
tx=random(100,200);
ty=random(100,200);
}
void draw(){
background(0);
fill(255); triangle(tx,ty,tx-25,ty+25,tx+25,ty+40);
if(collision()) fill(255,0,0);
else fill(255);
rect(rx,ry,50,50);
rx=mouseX-25;
ry=mouseY-25;
}
boolean collision(){
if(insideRect(tx,ty) || insideRect(tx-25,ty+40) || insideRect(tx+25,ty+40)) return true;
else return false;
}
boolean insideRect(float x,float y){
if(rx<x && x<rx+50 && ry<y && y<ry+50) return true;
else return false;
}
 |
| 顶点在正方形中则成功 |
 |
| 但这种情况下会侦测不到 |
2-2.三角形和正方形的碰撞侦测
该方法为外切法,又称交叉相乘,原理是检测四边形四个顶点和三角形三条边夹角的关系,只要有一点在三角形内就发生碰撞。
float tx,ty;
float rx,ry;
void setup(){
size(300,300);
tx=random(100,200);
ty=random(100,200);
}
void draw(){
background(0);
fill(255); triangle(tx,ty,tx-25,ty+40,tx+25,ty+40);
if(collision()) fill(255,0,0);//碰撞函式
else fill(255);
triangle(tx,ty,tx-25,ty+40,tx+25,ty+40);
rect(rx,ry,50,50);
rx=mouseX-25;
ry=mouseY-25;
}
boolean collision(){//把四个点放入侦测函式
boolean b1=insideTriangle(rx,ry);
boolean b2=insideTriangle(rx+50,ry);
boolean b3=insideTriangle(rx+50,ry+50);
boolean b4=insideTriangle(rx,ry+50);
if(b1 || b2 || b3 || b4) return true;
else return false;
}
boolean insideTriangle(float x,float y){//检测四个点和三条边关系
float c1=cross(x,y,tx,ty,tx-25,ty+40);
float c2=cross(x,y,tx-25,ty+40,tx+25,ty+40);
float c3=cross(x,y,tx+25,ty+40,tx,ty);
if(c1>0 && c2>0 && c3>0) return true;
else return false;
}
float cross(float xp,float yp,float x0,float y0,float x1,float y1){//交叉相乘,外积
return (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);
}
3.geometry dash碰撞侦测
与上周进度相比,增加了上层移动的木板,以及玩家方块与陷阱三角形的碰撞侦测。
float []badx,bubblex,bubbley,board;
int now;
void setup(){
size(600,400);
badx=new float[100];
badx[0]=300+random(200,300);
for(int i=1;i<100;i++){
badx[i]=badx[i-1]+random(200,250);
}
board=new float[100];
board[0]=500+random(200,300);
for(int i=1;i<100;i++){
board[i]=board[i-1]+random(350,600);
}
bubblex=new float[10];
bubbley=new float[10];
for(int i=0;i<10;i++){
bubblex[i]=0;
bubbley[i]=300;
}
}
float usery=300, vy=0, bgx=0;
void draw(){
background(#FF0A7D);
fill(#F5ADCF);
for(int i=0;i<100;i++){
now=i;
if(collision()) fill(255,0,0);
triangle(badx[i]-bgx,310,badx[i]-25-bgx,350,badx[i]+25-bgx,350);
}
fill(#AD0051);
for(int i=0;i<100;i++){
rect(board[i]-bgx,230,150,20);
}
fill(#AD0051); rect(0,350,600,400);
rect(150,usery,50,50);
if(jumping){
usery+=vy;
vy+=0.98/2.5;
if(usery>300){
jumping=false;
usery=300;
}
}
for(int i=9;i>0;i--){
bubblex[i]=bubblex[i-1];
bubbley[i]=bubbley[i-1];
ellipse(bubblex[i]+150-bgx,bubbley[i],10,10);
}
bubblex[0]=bgx;
bubbley[0]=usery;
bgx+=4;
}
boolean jumping=false;
void keyPressed(){
if(jumping==false){
jumping=true;
vy=-10;
}
}
boolean collision(){
boolean b1=insideTriangle(150,usery);
boolean b2=insideTriangle(200,usery);
boolean b3=insideTriangle(200,usery+50);
boolean b4=insideTriangle(150,usery+50);
if(b1 || b2 || b3 || b4) return true;
else return false;
}
boolean insideTriangle(float x,float y){
float c1=cross(x,y,badx[now]-bgx,310,badx[now]-25-bgx,350);
float c2=cross(x,y,badx[now]-25-bgx,350,badx[now]+25-bgx,350);
float c3=cross(x,y,badx[now]+25-bgx,350,badx[now]-bgx,310);
if(c1>=0 && c2>=0 && c3>=0) return true;
else return false;
}
float cross(float xp,float yp,float x0,float y0,float x1,float y1){
return (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);
}

沒有留言:
張貼留言