搜索
bottom↓
回复: 1

小球碰撞的程序

[复制链接]

出0入0汤圆

发表于 2010-4-13 09:01:34 | 显示全部楼层 |阅读模式
#define MY_FLOAT double

#include <math.h>

#define M_PI     (MY_FLOAT)3.14159265358979323846
#define M_PI_2     (MY_FLOAT)1.57079632679489661923
//pi + pi/2
#define M_PI_PI_2    (MY_FLOAT)4.71238898038468985769
//pi*2
#define M_PI_M2     (MY_FLOAT)6.28318530717958647692
//min
#define M_F_MIN     (MY_FLOAT)0.00001
//等于
#define M_EQUAL(a, b)   (abs(a-b) < M_F_MIN)
//不等于
#define M_UNEQUAL(a, b)   (abs(a-b) > M_F_MIN)


//================================================================
// 函数名称:GetAngle
// 功能    :获得矢量与Y轴的夹角
// 返回值  :返回矢量与Y轴的夹角(弧度)(顺时针)(三四象限为负)( -M_PI - M_PI )
// 参数说明:矢量的X和Y坐标
//================================================================
MY_FLOAT GetAngle(MY_FLOAT fx,MY_FLOAT fy)
{
return atan2( fx , fy );
}

//================================================================
// 函数名称:GetAngle
// 功能    :获得矢量与Y轴(正值)的夹角
// 返回值  :返回矢量与Y轴(正值)的夹角(弧度)(顺时针)(三四象限为正)( 0 - M_PI_M2 )
// 参数说明:矢量的X和Y坐标
//================================================================
MY_FLOAT GetAngleNoMinus(MY_FLOAT fx,MY_FLOAT fy)
{
double tangle = atan2( fx , fy );
return tangle < 0 ? M_PI_M2 + tangle : tangle;
}

//================================================================
// 函数名称:GetAngleB
// 功能    :获得矢量与矢量的夹角
// 返回值  :返回矢量1到矢量2的夹角(弧度)(顺时针)( 0 - M_PI_M2 )
// 参数说明:矢量1和2的X和Y坐标
//================================================================
MY_FLOAT GetAngleB(MY_FLOAT fx1,MY_FLOAT fy1,MY_FLOAT fx2,MY_FLOAT fy2)
{
MY_FLOAT angle = GetAngle( fx2 ,fy2 ) - GetAngle( fx1 ,fy1 );
return angle >= 0 ? angle : ( M_PI_M2 + angle );
}

//================================================================
// 函数名称:LAtoXY
// 功能:    矢量的长度和角度转换成坐标
// 返回值  :成功:TRUE,否则FALSE
// 参数说明:fx,fy:[out]返回矢量坐标
//          flennth:[in]矢量长度
//          fangle:[in]矢量角度
//================================================================
void LAtoXY(MY_FLOAT &fx,MY_FLOAT &fy,MY_FLOAT flength,MY_FLOAT fangle)
{
fx = flength * sin( fangle );
fy = flength * cos( fangle );
}

//================================================================
// 函数名称:XYtoLA
// 功能:    矢量的坐标转换成长度和角度
// 返回值  :成功:TRUE,否则FALSE
// 参数说明:fx,fy:[in]返回矢量坐标
//          flennth:[out]矢量长度
//          fangle:[out]矢量角度
//================================================================
void XYtoLA(MY_FLOAT &flength,MY_FLOAT &fangle,MY_FLOAT fx,MY_FLOAT fy)
{
flength = sqrt( fx*fx + fy*fy );
fangle = GetAngle( fx , fy );
}

//================================================================
// 函数名称:GetHeft
// 功能    :获得矢量的分量(两个互相垂直的矢量)
// 返回值  :TRUE为可以获得分量,FALSE为不可以
// 参数说明:fx1和fy1是矢量的坐标,
//          fangle 为矢量与其中一分量的夹角,可以为负.
//          返回 fx1,fy1,fx2,fy2 为分量的坐标
//          分量 fx1,fy1 与矢量夹角为 fangle
//          分量 fx2,fy2 与矢量夹角为 M_PI_2 - fangle
//================================================================
BOOL GetHeft(MY_FLOAT &fx1,MY_FLOAT &fy1,MY_FLOAT &fx2,MY_FLOAT &fy2,MY_FLOAT fangle)
{
MY_FLOAT tlength,tangle;
MY_FLOAT tlength2,tangle2;
bool tbdeasil = true;
if( fangle < 0 )
  {
  if( fangle < -M_PI_2 )
   {
   if( fangle > -M_PI_PI_2 || fangle < -M_PI_M2 )
    {
    fx2 = 0;
    fy2 = 0;
    return FALSE;
    }
   else
    {
    fangle += M_PI_M2;
    }
   }
  else
   {
   fangle += M_PI_2;
   tbdeasil = false;
   }
  }
if( fangle > M_PI_2 )
  {
  if( fangle < M_PI_PI_2 || fangle > M_PI_M2 )
   {
   fx2 = 0;
   fy2 = 0;
   return FALSE;
   }
  else
   {
   fangle = M_PI_M2 - fangle;
   tbdeasil = false;
   }
  }
if( M_EQUAL( fangle , 0 ) )
  {
  fx2 = 0;
  fy2 = 0;
  return TRUE;
  }
XYtoLA( tlength , tangle , fx1 , fy1 );
if( tbdeasil )
  {
  tlength2 = tlength * cos( fangle );
  tangle2 = tangle + fangle;
  if( tangle2 > M_PI_M2 )
   {
   tangle2 -= M_PI_M2;
   }
  LAtoXY( fx1 , fy1 , tlength2 , tangle2 );

  tlength2 = tlength * sin( fangle );
  tangle2 = tangle2 - M_PI_2;
  if( tangle2 < 0 )
   {
   tangle2 += M_PI_M2;
   }
  LAtoXY( fx2 , fy2 , tlength2 , tangle2 );
  }
else
  {
  tlength2 = tlength * cos( fangle );
  tangle2 = tangle - fangle;
  if( tangle2 < 0 )
   {
   tangle2 += M_PI_M2;
   }
  LAtoXY( fx1 , fy1 , tlength2 , tangle2 );

  tlength2 = tlength * sin( fangle );
  tangle2 = tangle2 + M_PI_2;
  if( tangle2 > M_PI_M2 )
   {
   tangle2 -= M_PI_M2;
   }
  LAtoXY( fx2 , fy2 , tlength2 , tangle2 );
  }
return TRUE;
}

//================================================================
// 函数名称:GetIpe
// 功能    :根据两个分量获得矢量
// 返回值  :TRUE为可以获得矢量,FALSE为不可以
// 参数说明:fx1,fy1,fx2,fy2 为分量的坐标
//          fx1和fy1是返回的矢量坐标,
//================================================================
void GetIpe(MY_FLOAT &fx1,MY_FLOAT &fy1,MY_FLOAT fx2,MY_FLOAT fy2)
{
fx1 += fx2;
fy1 += fy2;
}

//================================================================
// 函数名称:BallAfoul
// 功能:    计算两个质量相同的球碰撞后的运动,
//          根据两球的矢量,位置返回两球碰撞后的矢量.
// 返回值  :正常碰撞和未碰撞返回TRUE,异常碰撞返回FALSE
// 参数说明:x1,y1:第一个球的矢量,并返回碰撞后的矢量
//          x2,y2:第二个球的矢量,并返回碰撞后的矢量
//          xx1,xy1:第一个球的位置
//          xx2,xy2:第二个球的位置
//================================================================
BOOL BallAfoul(int &x1,int &y1,int &x2,int &y2,int xx1,int xy1,int xx2,int xy2)
{
MY_FLOAT
  fx1 = (MY_FLOAT)x1,
  fy1 = (MY_FLOAT)y1,
  fx2 = (MY_FLOAT)x2,
  fy2 = (MY_FLOAT)y2;

MY_FLOAT tx1,ty1,tangle1,tangle2;//

MY_FLOAT
  tfx1 = (MY_FLOAT)x1,
  tfy1 = (MY_FLOAT)y1,
  tfx2 = 0,
  tfy2 = 0;

MY_FLOAT
  ttfx1 = 0,
  ttfy1 = 0,
  ttfx2 = (MY_FLOAT)x2,
  ttfy2 = (MY_FLOAT)y2;

bool
  tboneball = true,
  tbtwoball = true;
/////////////
tx1=MY_FLOAT(xx2-xx1);
ty1=MY_FLOAT(xy2-xy1);
tangle1 = GetAngleB( fx1 , fy1 , tx1 , ty1 );

if( !GetHeft( tfx1 , tfy1 , tfx2 ,tfy2 , tangle1 ) )
  {
  tboneball = false;
  }


tx1=MY_FLOAT(xx1-xx2);
ty1=MY_FLOAT(xy1-xy2);
tangle2 = GetAngleB( fx2 , fy2 , tx1 , ty1 );

if( !GetHeft( ttfx2 ,ttfy2 , ttfx1 , ttfy1 , tangle2 ) )
  {
  tbtwoball = false;
  }

if( (tboneball^tbtwoball) == true )
  {
  //异常碰撞检测,异常时返回
  if( !tboneball )
   {
   tangle1 = tangle1 + M_PI;
   if( tangle1 > M_PI_M2 )
    {
    tangle1 -= M_PI_M2;
    }
   GetHeft( tfx1 , tfy1 , tfx2 ,tfy2 , tangle1 );
   if(sqrt( tfx1*tfx1 + tfy1*tfy1 ) >= sqrt( ttfx2*ttfx2 + ttfy2*ttfy2 ))
    return FALSE;
   tfx1 = (MY_FLOAT)x1;
   tfy1 = (MY_FLOAT)y1;
   tfx2 = 0;
   tfy2 = 0;
   }
  else
   {
   tangle2 = tangle2 + M_PI;
   if( tangle2 > M_PI_M2 )
    {
    tangle2 -= M_PI_M2;
    }
   GetHeft( ttfx2 ,ttfy2 , ttfx1 , ttfy1 , tangle2 );
   if(sqrt( tfx1*tfx1 + tfy1*tfy1 ) <= sqrt( ttfx2*ttfx2 + ttfy2*ttfy2 ))
    return FALSE;
   ttfx1 = 0;
   ttfy1 = 0;
   ttfx2 = (MY_FLOAT)x2;
   ttfy2 = (MY_FLOAT)y2;
   }
  }
else
  {
  //未发生碰撞
  if( !tboneball )
   {
   return TRUE;
   }
  }


GetIpe( ttfx1 , ttfy1 , tfx1 , tfy1 );
GetIpe( ttfx2 , ttfy2 , tfx2 , tfy2 );

/////////////
x1=int(ttfx2+0.5);
y1=int(ttfy2+0.5);
x2=int(ttfx1+0.5);
y2=int(ttfy1+0.5);
return TRUE;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2010-4-13 09:23:37 | 显示全部楼层
MARK~~
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 18:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表