【手游开发系列2】碰撞检测

来源:互联网 发布:通联支付网络备付金 编辑:程序博客网 时间:2024/04/30 05:05
在网易游戏研发笔试题中有一题就是这个碰撞检测,之前我看过一些文章,现在整理一个写个整理后的文章
之前大二写了一个简单的游戏【http://shouji.baidu.com/game/item?docid=6487395&from=as】,里面就是用很笨的枚举所有来相互检测是否碰撞  这样效率太慢了

1、前言:



下面这是我写的益智类小游戏  也要有碰撞检测和重力掉落  那时大二比较无知用了枚举去做碰撞检测  orz



飞机有很多子弹  还有敌机  相互之前要做碰撞检测


2、碰撞基础知识:
AABB包围盒:二维来说就是如图  三个矩形判断是否相交





OBB包围盒:就是AABB加一个方向  矩形可以旋转  在全民打飞机可以看到有的飞机会转弯



3、碰撞检测  
AABB: 
struct Point
{ int x,y;};
struct Rect
{
       Point LeftBottom;
       Point RightTop;
       bool IsIntersect(const Rect & A)
      {
             return !(
            RightTop.x< A.LeftBottom.x||
            RightTop.y< A.LeftBottom.y||
            LeftBottom.x> A.RightTop.x||
            LeftBottom.y> A.RightTop.y);
      }
};

OBB:
要用到sat分离轴定理
只针对凸多边形  凹多边形可以变成多个凸多边形  然后再运用sat
为:
(1)如果可以找到一条轴使得两个多边形在这条轴上的投影不相交,则这两个凸多边形就不相交
(2)以两个多边形的所有边的法线为轴  如果两个多边形在所有这些轴上的投影都相交,则这两个多边形就是相交的



4、OBB的实际代码
因为是矩形,所以法线也就是找长宽这两条线
代码有点挫  后期改进


struct Point
{ int x,y;};
struct Line
{
       Point p1,p2;
};
struct Vector {
      Vector( int x=0, int y=0)
      {
       this ->x=x ;
       this ->y=y ;
      }
int x,y;};
struct OBBRect
{
       Line Line1;
       Line Line2;
       bool IsIntersect(const OBBRect & A)
      {
             //在Line1投影
             Vector v(Line1.p2.x-Line1.p1.x,Line1.p2.y-Line1.p1.y);
             //四个点在v上面的投影
             Vector p1,p2,p3,p4;
             float L1 = (v *[点乘] p1)/|p1|;
             float L2 = (v *[点乘] p2)/|p2|;
             float L3 = (v *[点乘] p3)/|p3|;
             float L4 = (v *[点乘] p4)/|p4|;
            
             float minL=min(L1,L2,l3,l4);
             float maxL=max(L1,L2,l3,l4);

             //所以矩形的投影是v上面长度minL 到 maxL的线段
             //同理
             Vector Ap1,Ap2,Ap3,Ap4;
             float AL1 = (v *[点乘] Ap1)/|Ap1|;
             float AL2 = (v *[点乘] Ap2)/|Ap2|;
             float AL3 = (v *[点乘] Ap3)/|Ap3|;
             float AL4 = (v *[点乘] Ap4)/|Ap4|;
            
             float AminL=min(L1,L2,l3,l4);
             float AmaxL=max(L1,L2,l3,l4);


             //查看是否相交
             //如果minL>AmaxL  或者  maxL<AmaxL  则不相交
             //反之,相交

             //同理
             //在Line2投影

             //同理
             //在A.Line1投影

             //同理
             //在A.Line2投影
      }
};

5、未完待续:
还有四叉树的优化  减少枚举全部的飞机或者说是子弹   orz



【关于博客】:每次都要上传图片  好麻烦   还是印象比较好尴尬
http://app.yinxiang.com/l/AAWup3uJQvVHt5GyjQdKpLBOuOebP36MbOg/


1 0