天天看点

圆,矩形碰撞检测

  1.    private static final boolean isArcRectCollides(int arcX,int arcY,int arcR,int rectX,int rectY,int rectW,int rectH){   
  2.           int arcOx = arcX + arcR;//圆心X坐标   
  3.           int arcOy = arcY + arcR;//圆心Y坐标   
  4.           if(((rectX-arcOx) * (rectX-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR)   
  5.               return true;   
  6.           if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR)   
  7.               return true;   
  8.           if(((rectX-arcOx) * (rectX-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR)   
  9.               return true;   
  10.           if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR)   
  11.               return true;   
  12.           //分别判断矩形4个顶点与圆心的距离是否<=圆半径;如果<=,说明碰撞成功   
  13.           int minDisX = 0;   
  14.           if(arcOy >= rectY && arcOy <= rectY + rectH){   
  15.               if(arcOx < rectX)   
  16.                   minDisX = rectX - arcOx;   
  17.               else if(arcOx > rectX + rectW)   
  18.                   minDisX = arcOx - rectX - rectW;   
  19.               else    
  20.                   return true;   
  21.               if(minDisX <= arcR)   
  22.                   return true;   
  23.           }//判断当圆心的Y坐标进入矩形内时X的位置,如果X在(rectX-arcR)到(rectX+rectW+arcR)这个范围内,则碰撞成功   
  24.           int minDisY = 0;   
  25.           if(arcOx >= rectX && arcOx <= rectX + rectW){   
  26.               if(arcOy < rectY)   
  27.                   minDisY = rectY - arcOy;   
  28.               else if(arcOy > rectY + rectH)   
  29.                   minDisY = arcOy - rectY - rectH;   
  30.               else  
  31.                   return true;   
  32.               if(minDisY <= arcR)   
  33.                   return true;   
  34.           }//判断当圆心的X坐标进入矩形内时Y的位置,如果X在(rectY-arcR)到(rectY+rectH+arcR)这个范围内,则碰撞成功   
  35.           return false;   
  36.       }  
/*
     * arcX,arcY表示圆的绘制坐标,就是左上角坐标 ,arcR为圆半径;rectX,rectY,rectW,rectH分别表示矩形的绘制坐标与宽高
     */
    private static final boolean isArcRectCollides(int arcX,int arcY,int arcR,int rectX,int rectY,int rectW,int rectH){
           int arcOx = arcX + arcR;//圆心X坐标
           int arcOy = arcY + arcR;//圆心Y坐标
           if(((rectX-arcOx) * (rectX-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR)
               return true;
           if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR)
               return true;
           if(((rectX-arcOx) * (rectX-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR)
               return true;
           if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR)
               return true;
           //分别判断矩形4个顶点与圆心的距离是否<=圆半径;如果<=,说明碰撞成功
           
           
           int minDisX = 0;
           if(arcOy >= rectY && arcOy <= rectY + rectH){
               if(arcOx < rectX)
                   minDisX = rectX - arcOx;
               else if(arcOx > rectX + rectW)
                   minDisX = arcOx - rectX - rectW;
               else 
                   return true;
               if(minDisX <= arcR)
                   return true;
           }//判断当圆心的Y坐标进入矩形内时X的位置,如果X在(rectX-arcR)到(rectX+rectW+arcR)这个范围内,则碰撞成功
           
           int minDisY = 0;
           if(arcOx >= rectX && arcOx <= rectX + rectW){
               if(arcOy < rectY)
                   minDisY = rectY - arcOy;
               else if(arcOy > rectY + rectH)
                   minDisY = arcOy - rectY - rectH;
               else
                   return true;
               if(minDisY <= arcR)
                   return true;
           }//判断当圆心的X坐标进入矩形内时Y的位置,如果X在(rectY-arcR)到(rectY+rectH+arcR)这个范围内,则碰撞成功
           return false;
       }
           

//假定矩形由d1,d2,d3,d4顶点按顺时针方向组成,ywz为圆心位置,yzj为圆直径。

  int Y_ZFX_WZ(D3DXVECTOR2 &ywz,float &yzj,D3DXVECTOR2 &d1,D3DXVECTOR2 &d2,D3DXVECTOR2 &d3,D3DXVECTOR2 &d4)

 {

  float k,k1,k2;

  k=4*pow((d2.x-d1.x)*(d2.x-ywz.x)+(d2.y-d1.y)*(d2.y-ywz.y),2)-4*(pow(d2.x-d1.x,2)+pow(d2.y-d1.y,2))*(pow(d1.x-ywz.x,2)+pow(d1.y-ywz.y,2)-pow(yzj,2));

  //如果有在d2-d1确定的直线上有交点

  if (k>=0)  

  {

  k1=(-2*(d2.x-d1.x)*(d2.x-ywz.x)-2*(d2.y-d1.y)*(d2.y-ywz.y)+sqrt(k))/(2*(pow(d2.x-d1.x,2)+pow(d2.y-d1.y,2)));

  k2=(-2*(d2.x-d1.x)*(d2.x-ywz.x)-2*(d2.y-d1.y)*(d2.y-ywz.y)-sqrt(k))/(2*(pow(d2.x-d1.x,2)+pow(d2.y-d1.y,2)));

  if ((k1>0)&&(k1<1)) return 2;   

  if ((k2>0)&&(k2<1)) return 2;

  }

  k=4*pow((d3.x-d2.x)*(d3.x-ywz.x)+(d3.y-d2.y)*(d3.y-ywz.y),2)-4*(pow(d3.x-d2.x,2)+pow(d3.y-d2.y,2))*(pow(d2.x-ywz.x,2)+pow(d2.y-ywz.y,2)-pow(yzj,2));

  //如果有在d3-d2确定的直线上有交点

  if (k>=0)

  {

  k1=(-2*(d3.x-d2.x)*(d3.x-ywz.x)-2*(d3.y-d2.y)*(d3.y-ywz.y)+sqrt(k))/(2*(pow(d3.x-d2.x,2)+pow(d3.y-d2.y,2)));

  k2=(-2*(d3.x-d2.x)*(d3.x-ywz.x)-2*(d3.y-d2.y)*(d3.y-ywz.y)-sqrt(k))/(2*(pow(d3.x-d2.x,2)+pow(d3.y-d2.y,2)));

  if ((k1>0)&&(k1<1)) return 2;

  if ((k2>0)&&(k2<1)) return 2;

  }

  k=4*pow((d4.x-d3.x)*(d4.x-ywz.x)+(d4.y-d3.y)*(d4.y-ywz.y),2)-4*(pow(d4.x-d3.x,2)+pow(d4.y-d3.y,2))*(pow(d3.x-ywz.x,2)+pow(d3.y-ywz.y,2)-pow(yzj,2));

  //如果有在d4-d3确定的直线上有交点

  if (k>=0)

  {

  k1=(-2*(d4.x-d3.x)*(d4.x-ywz.x)-2*(d4.y-d3.y)*(d4.y-ywz.y)+sqrt(k))/(2*(pow(d4.x-d3.x,2)+pow(d4.y-d3.y,2)));

  k2=(-2*(d4.x-d3.x)*(d4.x-ywz.x)-2*(d4.y-d3.y)*(d4.y-ywz.y)-sqrt(k))/(2*(pow(d4.x-d3.x,2)+pow(d3.y-d3.y,2)));

  if ((k1>0)&&(k1<1)) return 2;

  if ((k2>0)&&(k2<1)) return 2;

  }

  k=4*pow((d1.x-d4.x)*(d1.x-ywz.x)+(d1.y-d4.y)*(d1.y-ywz.y),2)-4*(pow(d1.x-d4.x,2)+pow(d1.y-d4.y,2))*(pow(d4.x-ywz.x,2)+pow(d4.y-ywz.y,2)-pow(yzj,2));

  //如果有在d1-d4确定的直线上有交点   

  if (k>=0)

  {

  k1=(-2*(d1.x-d4.x)*(d1.x-ywz.x)-2*(d1.y-d4.y)*(d1.y-ywz.y)+sqrt(k))/(2*(pow(d1.x-d4.x,2)+pow(d1.y-d4.y,2)));

  k2=(-2*(d1.x-d4.x)*(d1.x-ywz.x)-2*(d1.y-d4.y)*(d1.y-ywz.y)-sqrt(k))/(2*(pow(d1.x-d4.x,2)+pow(d1.y-d4.y,2)));

  if ((k1>0)&&(k1<1)) return 2;

  if ((k2>0)&&(k2<1)) return 2;

  }

  D3DXVECTOR2 ls;

  float z,l1,l2,l3,l4;//l1,l2,l3,l4为记录圆心点与四边的距离,在边法向量正侧为正,反之为负

  ls=d2-d1;

  z=ls.x;ls.x=ls.y;ls.y=-z;  

  D3DXVec2Normalize(&ls,&ls);//第一个边的法向量

  l1= ls.x*(ywz.x-d1.x)+ls.y*(ywz.y-d1.y); //圆心与d2-d1边的距离

  l2= ls.y*(ywz.x-d2.x)-ls.x*(ywz.y-d2.y); //圆心与d3-d2边的距离

  l3= -ls.x*(ywz.x-d3.x)-ls.y*(ywz.y-d3.y); // 圆心与d4-d3边的距离

  l4= -ls.y*(ywz.x-d4.x)+ls.x*(ywz.y-d4.y); //圆心与d1-d4边的距离

  if ((l1>=yzj)&&(l2>=yzj)&&(l3>=yzj)&&(l4>=yzj))  

  return 3; //圆在长方形内部,也就是长方形包含圆

  //3、如果矩形四个顶点都在圆内,则返回4

  if ((pow(d1.x-ywz.x,2)+pow(d1.y-ywz.y,2)<=yzj*yzj)&&(pow(d2.x-ywz.x,2)+pow(d2.y-ywz.y,2)<=yzj*yzj)&&(pow(d3.x-ywz.x,2)+pow(d3.y-ywz.y,2)<=yzj*yzj)&&(pow(d4.x-ywz.x,2)+pow(d4.y-ywz.y,2)<=yzj*yzj))

  return 4;

  //4、必定剩余第一种情况,圆与正方形不相交,也不包含

  return 1;  

 }