2021年12月13日 星期一

ᐇ Week14

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



沒有留言:

張貼留言