2d碰撞

Posted on 2010-04-16 20:06  625747  阅读(228)  评论(0)    收藏  举报

 

代码
#include "ball.h"

ball::ball (POINT pt,speedVec V)
{
m_r
= 20;
m_pt
= pt ;
m_stateSur
= NO;
m_V
= V;
m_s
= NO;
}

ball::
~ball(void)
{
}

void ball::drawEllipse(HDC dc) ///画球函数
{
Ellipse (dc,m_pt.x
- m_r ,m_pt.y - m_r,m_pt.x + m_r,m_pt.y + m_r);
}


//运动
void ball::moveBall()
{
if(m_stateSur == NO)//两球没有撞
{
m_pt.x
+= m_V.x;
m_pt.y
+= m_V.y ;
}
if(m_stateSur == YES)
{
m_pt.x
+= m_newV.x;
m_pt.y
+= m_newV.y ;
m_V
= m_newV;
}
}

void ball::colliteSur()
{
if(m_pt.x - m_r <= 0||m_pt.x + m_r >= 780||m_pt.y - m_r <= 0||m_pt.y + m_r >= 560)
{
if(m_pt.x - m_r <= 0)
{
surface
= LEFT;
}

if (m_pt.x + m_r >= 780)
{
surface
= RIGHT;
}
if( m_pt.y - m_r <= 0)
{
surface
= UP;
}
if( m_pt.y + m_r >= 560)
{
surface
= BOTTON;
}
CollisionResponseBetweenEdge();
m_stateSur
= YES;
}
}

void ball::CollisionResponseBetweenEdge()
{
switch(surface )
{
case LEFT:
m_newV.x
= -m_V.x;
m_newV.y
= m_V.y;
break;
case RIGHT:
m_newV.x
= -m_V.x;
m_newV.y
= m_V.y;
break;
case BOTTON:
m_newV.x
= m_V.x;
m_newV.y
= -m_V.y;
break;
case UP:
m_newV.x
= m_V.x;
m_newV.y
= -m_V.y;
break;
}
}

//检查边界
void ball::checkAge()
{

if(m_pt.x - m_r<= 0)
{
m_pt.x
= m_r;
}

if(m_pt.x + m_r >= 780)
{
m_pt.x
= 780-m_r;
}

if(m_pt.y -m_r<= 00)
{
m_pt.y
= m_r;
}

if(m_pt.y + m_r >= 560)
{
m_pt.y
= 560-m_r;
}
}

/*



*/

#define NUM 8 //控制个数
ball
* b[NUM];
STATE ballstate[NUM][NUM];
WHERE wh;
bool cb;

enum WHERE
{
CORRECT ,
SL,
};


void Init();
void GameAction(HWND hWnd);

void Init() //初化数据
{
cb
= TRUE;
POINT pt1;
pt1.x
= 100;
pt1.y
= 150;
speedVec V1;
V1.x
= 5;
V1.y
= 3;
b[
0] = new ball(pt1,V1);

POINT pt2;
pt2.x
= 280;
pt2.y
= 350;
speedVec V2;
V2.x
= -3;
V2.y
= -4;
b[
1] = new ball(pt2,V2);

POINT pt3;
pt3.x
= 500;
pt3.y
= 230;
speedVec V3;
V3.x
= -3;
V3.y
= 5;
b[
2] = new ball(pt3,V3);

POINT pt4;
pt4.x
= 400;
pt4.y
= 300;
speedVec V4;
V4.x
= 3;
V4.y
= -4;
b[
3] = new ball(pt4,V4);

POINT pt5;
pt5.x
= 100;
pt5.y
= 200;
speedVec V5;
V5.x
= 2;
V5.y
=-1;
b[
4] = new ball(pt5,V5);

POINT pt6;
pt6.x
= 200;
pt6.y
= 350;
speedVec V6;
V6.x
= -5;
V6.y
= 3;
b[
5] = new ball(pt6,V6);

POINT pt7;
pt7.x
= 170;
pt7.y
= 270;
speedVec V7;
V7.x
= 3;
V7.y
= 3;
b[
6] = new ball(pt7,V7);

POINT pt8;
pt8.x
= 480;
pt8.y
= 380;
speedVec V8;
V8.x
= 3;
V8.y
= 2;
b[
7] = new ball(pt8,V8);

POINT pt9;
pt9.x
= 190;
pt9.y
= 200;
speedVec V9;
V9.x
= 5;
V9.y
= 3;
b[
8] = new ball(pt9,V9);

POINT pt10;
pt10.x
= 420;
pt10.y
= 300;
speedVec V10;
V10.x
= 1;
V10.y
= 2;
b[
9] = new ball(pt10,V10);

for( int i= 0;i<NUM;i++)
for (int j = 0;j < NUM;j++)
{
ballstate[i][i]
= NO;
}
}

void GameAction(HWND hWnd)
{
HBITMAP hbm;
HDC dchbm;
HDC hDC;
hDC
= GetDC(hWnd);
dchbm
=CreateCompatibleDC(hDC);
hbm
= CreateBitmap(800,600, 1, 1, NULL); ;//创建存放图象的显示缓
::SelectObject (dchbm,hbm);


::Sleep (
100);
UpdateWindow(hWnd);



double dis ;
double temp;
for (int i = 0;i< NUM;i++)
for( int j = 0;j < NUM && i!=j;j++)
{
if(ballstate[i][j] == NO)//两球没有撞
{
if(b[i]->m_s == NO) //球i没有碰面
{
b[i]
->m_pt.x += b[i]->m_V.x;
b[i]
->m_pt.y += b[i]->m_V.y;
}

if(b[i]->m_s == YES)
{
b[i]
->m_pt.x += b[i]->m_newV.x;
b[i]
->m_pt .y += b[i]->m_newV.y;
b[i]
->m_V =b[i]->m_newV;

}

if(b[j]->m_s == NO) //球j没有碰面
{
b[j]
->m_pt.x += b[j]->m_V.x;
b[j]
->m_pt.y += b[j]->m_V.y;
}

if(b[j]->m_s == YES)
{
b[j]
->m_pt.x += b[j]->m_newV.x;
b[j]
->m_pt.y += b[j]->m_newV.y;
b[j]
->m_V =b[j]->m_newV;

}
}
if( ballstate[i][j] == YES) //两球相撞
{

b[i]
->m_pt.x += b[i]->m_V.x;
b[i]
->m_pt.y += b[i]->m_V.y;
b[j]
->m_pt.x += b[j]->m_V.x;
b[j]
->m_pt.y += b[j]->m_V.y;

b[i]
->m_V = b[i]->m_newV;
b[j]
->m_V = b[j]->m_newV;
}
temp
= (b[i]->m_pt.x - b[j]->m_pt.x)* (b[i]->m_pt.x - b[j]->m_pt.x) + (b[i]->m_pt.y - b[j]->m_pt.y)* (b[i]->m_pt.y - b[j]->m_pt.y);



dis
= sqrt (temp);
if ( dis > b[i]->m_r + b[i]->m_r)
{
cb
= TRUE;
}

if(dis <=b[i]->m_r + b[i]->m_r && cb == TRUE)
{

//MessageBox(NULL,"sdf","df",NULL);
ballstate[i][j] = YES;
double dx,dy;
dx
= b[j]->m_pt.x -b[i]->m_pt.x;
dy
= b[j]->m_pt.y -b[i]->m_pt.y;

double ax,ay ;
ax
= dx / dis;
ay
= dy / dis;
if( b[j]->m_V .x * b[i]->m_V .x <= 0 || b[j]->m_V .y * b[i]->m_V .y <= 0 )
{

speedVec pt1pt2;
//两球连线向量

pt1pt2.x
= b[j]->m_pt.x - b[i]->m_pt.x;
pt1pt2.y
= b[j]->m_pt.y - b[i]->m_pt.y;

speedVec Normal;
//两球连线向量
if( pt1pt2.y == 0 && pt1pt2.x == 0)
{
}
else if( pt1pt2.y == 0 && pt1pt2.x != 0)
{
Normal.x
= 1 ;
Normal.y
= 0;
wh
= CORRECT;
}
else if( pt1pt2.x == 0 && pt1pt2.y != 0)
{
Normal.x
= 0 ;
Normal.y
= 1;
wh
= CORRECT;
}
else if( pt1pt2.y != 0 && pt1pt2.y != 0 )
{
speedVec t;
double s;
s
= pt1pt2.x * pt1pt2.x + pt1pt2.y * pt1pt2.y;
double d;
d
= sqrt (s );

Normal.x
= pt1pt2 .x / d ; //法向量
Normal.y = pt1pt2 .y / d;

wh
= SL;

}

a:
speedVec Ni,Nj;
double temp_i,temp_j;
switch(wh)
{
case CORRECT:

temp_i
= -( b[i]->m_V.x * Normal.x + b[i]->m_V.y * Normal.y) ;
temp_j
= -( b[j]->m_V.x * Normal.x + b[j]->m_V.y * Normal.y) ;
Ni.x
= temp_i * Normal.x ;
Ni.y
= temp_i * Normal.y ;
Nj.x
= temp_j * Normal.x ;
Nj.y
= temp_j * Normal.y ;

b[i]
->m_newV.x =2*Ni.x + b[i]->m_V.x;
b[i]
->m_newV.y =2*Ni.y + b[i]->m_V.y;
b[j]
->m_newV.x =2*Nj.x + b[j]->m_V.x;
b[j]
->m_newV.y =2*Nj.y + b[j]->m_V.y;
cb
= false ;
break;
case SL:
speedVec Ni,Nj;
double temp_i,temp_j;
temp_i
= -( b[i]->m_V.x * Normal.x + b[i]->m_V.y * Normal.y) ;
temp_j
= -( b[j]->m_V.x * Normal.x + b[j]->m_V.y * Normal.y) ;
Ni.x
= temp_i * Normal.x ;
Ni.y
= temp_i * Normal.y ;
Nj.x
= temp_j * Normal.x ;
Nj.y
= temp_j * Normal.y ;

b[i]
->m_newV.x =2*Ni.x + b[i]->m_V.x;
b[i]
->m_newV.y =2*Ni.y + b[i]->m_V.y;
b[j]
->m_newV.x =2*Nj.x + b[j]->m_V.x;
b[j]
->m_newV.y =2*Nj.y + b[j]->m_V.y;

cb
= false ;
break;

}


}

}
}

for (int i = 0; i < NUM;i++)
{
b[i]
->drawEllipse(dchbm);//显示 //画球
b[i]->checkAge();
b[i]
->moveBall();//运动
b[i]->colliteSur();
}
//::BitBlt (hDC,0,0,800,600,dchbm,0,0,SRCCOPY);
//UpdateWindow(hWnd);
// DeleteDC(hDC);
// DeleteDC(dchbm);
// DeleteObject (hbm);
// DeleteObject (SelectObject (dchbm,hbm));

}



#include
"math.h"
#include
"windows.h"
#define WIDTH 100 //屏幕宽
#define HEIGHT 200 //屏幕高
const r1 = 10;
const r2 = 20;
const speed1 10; //像素
const speed2 10; //像素
struct speedVec //方向
{
int x;
int y;
};

void Func(POINT pt1,speedvec oldV1,speedVec newV1,POINT pt2,speedvec oldV2,speedVec newV2);//检测函数
speedVec unitFunc(speedVec V); //求单位向量
speedVec normalFunc(speedVec V);//法微量及单位向量
void checkAge(POINT pt,int r ,speedvec oldV,speedVec newV);//边缘检测
void Func(POINT pt1,speedvec oldV1,speedVec newV1,POINT pt2,speedvec oldV2,speedVec newV2)
{

/* 注意
oldv.x * oldv.x + oldv.y * oldv.y = speed * speed;
newV.x * newV.x + newV.y * newV.y = speed * speed;
*/

speedVec tempV1,tempv2;
oldV1
= speed1 * tempV1;
oldV1
= speed2 * tempV2;


checkAge(pt1,r1,oldV1,newV2);
//单个查测是否及球碰壁处理
checkAge(pt2,r2,oldV1,newV2);


double temp;
temp
= (pt2.x - pt1.x) * (pt2.x - pt1.x ) + (pt2.x - pt1.x) * (pt2.x - pt1.y ) ;
double dis = sqrt( temp);
if( dis <= r1 + r2)
{
speedVec conect,conectunit;
//两球连线向量
conect.x = pt2.x - pt1.x ;
conect.x
= pt2.x - pt2.x ;
conectunit
= unit(conectunit);

speedVec normal;
//法向量
normal = normalFunc(conect);

double dx,dy;
dx
= b[j]->m_pt.x -b[i]->m_pt.x;
dy
= b[j]->m_pt.y -b[i]->m_pt.y;

double ax,ay ;
ax
= dx / dis;
ay
= dy / dis;

tempVn_i
= speed1 * ax;
tempVn_j
= speed2 * ay;
speedVec Vn_1,Vn_2;
//切线方向
Vn_1.x = tempVn_1 * normal.x;
Vn_1.y
= tempVn_1 * normal.y;
Vn_2.x
= tempVn_2 * normal.x;
Vn_2.y
= tempVn_2 * normal.y;

double tempVt_i,tempVt_j; //连线方向
tempVt_i = speed * ay;
tempVt_j
= speed * ax;
speedVec Vt_i,Vt_j;
Vt_1.x
= tempVn_i * conectunit.x;
Vt_1.y
= tempVn_i * conectunit.y;
Vt_2.x
= tempVn_j * conectunit.x;
Vt_2.y
= tempVn_j * conectunit.y;

//speedVec tempV1,tempV2;
newV1.x = Vn_1.x - Vt_1.x;
newV1.y
= Vn_1.x - Vt_1.y;
newV2.x
= Vn_2.x - Vt_2.x;
newV2.y
= Vn_2.x - Vt_2.y;
}
}

//求单位
speedVec unitFunc(speedVec V)
{
speedVec result;
if( V.y == 0 && V.x == 0)
{
}
else if( V.y == 0 && V.x != 0)
{
result.x
= 1 ;
result.y
= 0;
return result;
}

else if( V.y == 0 && V.x != 0)
{
result.x
= 1 ;
result.y
= 0;
return result;
}
else if( V.y == 0 && V.x != 0)
{
double s;
s
= V.x * t.x + V.y * V.y;
double d;
d
= sqrt (s );

result.x
= V.x / d ;
result.y
= V.y / y ;
return result;
}
}

//法向量
speedVec normalFunc(speedVec V)
{
speedVec result;
if( V.y == 0 && V.x == 0)
{
}
else if( V.y == 0 && V.x != 0) //水平向量
{
result.x
= 0 ;
result.y
= 1;
return result;
}

else if( V.y == 0 && V.x != 0) //垂直向量
{
result.x
= 0 ;
result.y
= 1;
return result;
}

else if( V.y == 0 && V.x != 0)
{
speedVec t;
t.x
= - V.y/ V.x ;
t.y
= 1;

double s;
s
= t.x * t.x + t.y * t.y;
double d;
d
= sqrt (s );

result.x
= t.x / d ;
result.y
= t.y / y ;
return result;
}
}

//边缘检测
void checkAge(POINT pt,int r ,speedvec oldV,speedVec newV)
{
if(pt.x - r<= - (WIDTH/2)) //碰左
{
pt.x
= r - (WIDTH/2) ;
newV.x
= -oldV.x;
newV.y
= oldV.y;
}

if(pt.x + r >= (WIDTH/2) ) //碰右
{
pt.x
= (WIDTH/2)-m_r; //
newV.x = -oldV.x;
newV.y
= oldV.y;
}

if(pt.y -r<= - HEIGHT /2)) //碰上
{
pt.y
= r -HEIGHT /2;
newV.x
= oldV.x;
newV.y
= -oldV.y;
}

if(pt.y + r >= - HEIGHT /2) //碰下
{
pt.y
= HEIGHT /2 -_r;
newV.x
= oldV.x;
newV.y
= -oldV.y;
}
}