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