📄 game_physics.cpp
字号:
if(t<h0.r*h0.r)return true;
}
return false;
}
detect_boundary(CBall *b0,CBoundary *bd,double step){
double x0,y0,x1,y1,d;
x0=b0->x[0];
y0=b0->x[1];
x1=x0+b0->v[0]*step;
y1=y0+b0->v[1]*step;
//////first
if(b0->v[0]*bd->n[0][0]+b0->v[1]*bd->n[0][1]<0){
d=dist(x0,y0,bd->x[0][0],bd->x[0][1],bd->x[1][0],bd->x[1][1]);
if(d>0){
d=dist(x1,y1,bd->x[0][0],bd->x[0][1],bd->x[1][0],bd->x[1][1]);
if(d>0 && d<b_radius*b_radius)return 1;
if(d<0){
d=dist_l(bd->x[1][0],bd->x[1][1],bd->x[0][0],bd->x[0][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 1;
d=dist_p(x1,y1,bd->x[1][0],bd->x[1][1]);
if(d>0 && d<b_radius*b_radius)return 2;
d=dist(bd->x[1][0],bd->x[1][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 2;
}
}
else{
d=dist_l(bd->x[1][0],bd->x[1][1],bd->x[0][0],bd->x[0][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 2;
if(d<0){
d=dist_p(x1,y1,bd->x[1][0],bd->x[1][1]);
if(d>0 && d<b_radius*b_radius)return 2;
}
d=dist(x1,y1,bd->x[1][0],bd->x[1][1],bd->x[0][0],bd->x[0][1]);
if(d>0 && d<b_radius*b_radius)return 1;
}
}
//second
if(b0->v[0]*bd->n[1][0]+b0->v[1]*bd->n[1][1]<0){
d=dist(x0,y0,bd->x[1][0],bd->x[1][1],bd->x[2][0],bd->x[2][1]);
if(d>0){
d=dist(x1,y1,bd->x[1][0],bd->x[1][1],bd->x[2][0],bd->x[2][1]);
if(d>0 && d<b_radius*b_radius)return 3;
if(d<0){
d=dist_l(bd->x[1][0],bd->x[1][1],bd->x[2][0],bd->x[2][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 3;
d=dist_p(x1,y1,bd->x[1][0],bd->x[1][1]);
if(d<b_radius*b_radius)return 2;
d=dist(bd->x[1][0],bd->x[1][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 2;
d=dist_l(bd->x[2][0],bd->x[2][1],bd->x[1][0],bd->x[1][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 3;
d=dist_p(x1,y1,bd->x[2][0],bd->x[2][1]);
if(d<b_radius*b_radius)return 4;
d=dist(bd->x[2][0],bd->x[2][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 4;
}
}
else{
d=dist_l(bd->x[1][0],bd->x[1][1],bd->x[2][0],bd->x[2][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 2;
if(d<0){
d=dist_p(x1,y1,bd->x[1][0],bd->x[1][1]);
if(d>0 && d<b_radius*b_radius)return 2;
}
d=dist_l(bd->x[2][0],bd->x[2][1],bd->x[1][0],bd->x[1][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 4;
if(d<0){
d=dist_p(x1,y1,bd->x[2][0],bd->x[2][1])<b_radius*b_radius;
if(d>0 && d<b_radius*b_radius)return 4;
}
d=dist(x1,y1,bd->x[1][0],bd->x[1][1],bd->x[2][0],bd->x[2][1]);
if(d>0 && d<b_radius*b_radius)return 3;
}
}
//third
if(b0->v[0]*bd->n[2][0]+b0->v[1]*bd->n[2][1]<0){
d=dist(x0,y0,bd->x[2][0],bd->x[2][1],bd->x[3][0],bd->x[3][1]);
if(d>0){
d=dist(x1,y1,bd->x[2][0],bd->x[2][1],bd->x[3][0],bd->x[3][1]);
if(d>0 && d<b_radius*b_radius)return 5;
if(d<0){
d=dist_l(bd->x[2][0],bd->x[2][1],bd->x[3][0],bd->x[3][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 0;
d=dist_p(x1,y1,bd->x[2][0],bd->x[2][1]);
if(d>0 && d<b_radius*b_radius)return 4;
d=dist(bd->x[2][0],bd->x[2][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 4;
}
}
else{
d=dist_l(bd->x[2][0],bd->x[2][1],bd->x[3][0],bd->x[3][1],x0,y0,x1,y1);
if(d>0 && d<b_radius*b_radius)return 4;
if(d<0){
d=dist_p(x1,y1,bd->x[2][0],bd->x[2][1]);
if(d>0 && d<b_radius*b_radius)return 4;
}
d=dist(x1,y1,bd->x[2][0],bd->x[2][1],bd->x[3][0],bd->x[3][1]);
if(d>0 && d<b_radius*b_radius)return 5;
}
}
return -1;
}
int mid_boundary(CBall *b1,CBoundary *bd,double mstep){
int t,i=16,j=16;
for(int k=0;k<4;k++){
t=detect_boundary(b1,bd,mstep*j);
if(t!=-1){
j=j-i/2;
}
else j=j+i/2;
i/=2;
}
return j;
}
int mid_ball(CBall &b1,CBall &b2, double mstep){
int i=16,j=16;
for(int k=0;k<4;k++){
if(detect_ball(b1, b2, mstep*j))j=j-i/2;
else j=j+i/2;
i/=2;
}
return j;
}
void hit_ball(CBall *b1,CBall *b2,double step){
double v1x,v1y,v2x,v2y,x0,y0,value,mx,my,nx,ny,v1m,v1n,v2m,v2n,v1m0,v2m0;
v1x=b1->v[0];
v1y=b1->v[1];
v2x=b2->v[0];
v2y=b2->v[1];
x0=b2->x[0]-b1->x[0];
y0=b2->x[1]-b1->x[1];
value=sqrt(x0*x0+y0*y0);
mx=x0/value;
my=y0/value;
nx=-my;
ny=mx;
v1m=point_mul(v1x,v1y,mx,my);
v1n=point_mul(v1x,v1y,nx,ny);
v2m=point_mul(v2x,v2y,mx,my);
v2n=point_mul(v2x,v2y,nx,ny);
v1m0=v1m-(1+expense_ball)*(v1m-v2m)/2;
v2m0=v2m-(1+expense_ball)*(v2m-v1m)/2;
b1->v[0]=v1m0*mx+v1n*nx;
b1->v[1]=v1m0*my+v1n*ny;
b2->v[0]=v2m0*mx+v2n*nx;
b2->v[1]=v2m0*my+v2n*ny;
}
void hit_tip(CBall *b0,double &xt,double &yt, double step){
double x1=b0->v[0];
double y1=b0->v[1];
double x0=b0->x[0]-xt;
double y0=b0->x[1]-yt;
if(x0*x1+y0*y1<0){
b0->v[0]=(y0*y0*x1-x0*x0*x1-2*x0*y0*y1)*expense_bd/(x0*x0+y0*y0);
b0->v[1]=(x0*x0*y1-y0*y0*y1-2*y0*x0*x1)*expense_bd/(x0*x0+y0*y0);
}
}
void hit_bd(CBall *b0,double x0,double y0, double step){
double x1=b0->v[0];
double y1=b0->v[1];
if(x0*x1+y0*y1<0){
b0->v[0]=(y0*y0*x1-x0*x0*x1-2*x0*y0*y1)*expense_bd;
b0->v[1]=(x0*x0*y1-y0*y0*y1-2*y0*x0*x1)*expense_bd;
}
}
void hit_boundary(CBall *b0,CBoundary *bd,int n, double step){
switch (n)
{
case 1: hit_bd(b0,bd->n[0][0],bd->n[0][1], step);break;
case 3: hit_bd(b0,bd->n[1][0],bd->n[1][1], step);break;
case 5: hit_bd(b0,bd->n[2][0],bd->n[2][1], step);break;
case 2: hit_tip(b0,bd->x[1][0],bd->x[1][1], step);break;
case 4: hit_tip(b0,bd->x[2][0],bd->x[2][1], step);break;
}
}
void inhole(CBall *b0,CHole *h0){
double v0=sqrt((h0->x[0]-b0->x[0])*(h0->x[0]-b0->x[0])+(h0->x[1]-b0->x[1])*(h0->x[1]-b0->x[1]));
double x0=(h0->x[0]-b0->x[0])/v0;
double y0=(h0->x[1]-b0->x[1])/v0;
if(b0->ball_alpha<PI){
if(b0->ball_alpha<PI/2){
b0->x[0]=b0->before_in[0]+x0*sin(b0->ball_alpha)*b_radius;
b0->x[1]=b0->before_in[1]+y0*sin(b0->ball_alpha)*b_radius;
b0->x[2]=cos(b0->ball_alpha)*b_radius;
}
else{
b0->x[0]+=x0*0.01;
b0->x[1]+=y0*0.01;
b0->x[2]-=0.1;
}
b0->ball_alpha+=b0->ball_alpha;
}
else {
b0->status=BS_REMOVED;
b0->ball_alpha=0.02;
}
}
void CPoolGame::Collision(double time_step)
{
//detect balls
double mstep=time_step/32;
for(int i=0;i<num_balls;i++){
if (balls[i].status==BS_IN_THE_HOLE || balls[i].status==BS_REMOVED)
continue;
for(int j=0;j<num_balls;j++){
if (i==j) continue;
if (balls[j].status==BS_IN_THE_HOLE || balls[j].status==BS_REMOVED)
continue;
if(balls[i].status==BS_STATIONARY && balls[j].status==BS_STATIONARY)
continue;
if(detect_ball(balls[i],balls[j], time_step)){
///////////////////////////////////////////////////////////////
if(ballhit==0 && i==0)ballhit=j;
///////////////////////////////////////////////////////////////
int midb=mid_ball(balls[i],balls[j],mstep);
balls[i].x[0]=balls[i].x[0]+balls[i].v[0]*mstep*midb;
balls[i].x[1]=balls[i].x[1]+balls[i].v[1]*mstep*midb;
balls[j].x[0]=balls[j].x[0]+balls[j].v[0]*mstep*midb;
balls[j].x[1]=balls[j].x[1]+balls[j].v[1]*mstep*midb;
hit_ball(&balls[i],&balls[j],time_step);
if(balls[i].v[0]==0 && balls[i].v[1]==0)balls[i].status=BS_STATIONARY;
else balls[i].status=BS_MOVING;
if(balls[j].v[0]==0 && balls[i].v[1]==0)balls[j].status=BS_STATIONARY;
else balls[j].status=BS_MOVING;
balls[i].x[0]=balls[i].x[0]+balls[i].v[0]*mstep*(32-midb);
balls[i].x[1]=balls[i].x[1]+balls[i].v[1]*mstep*(32-midb);
balls[j].x[0]=balls[j].x[0]+balls[j].v[0]*mstep*(32-midb);
balls[j].x[1]=balls[j].x[1]+balls[j].v[1]*mstep*(32-midb);
balls[i].hit=balls[j].hit=true;
}
}
}
//detect boundaries
int e;
for(int b=0;b<num_balls;b++){
CBall *ball=balls+b;
if(ball->status == BS_MOVING){
for(int bnd=0;bnd<num_boundaries;bnd++){
CBoundary *bd=boundaries+bnd;
e=detect_boundary(ball,bd,time_step);
if(e > 0){
int midbd=mid_boundary(ball,bd,mstep);
ball->x[0]+=ball->v[0]*mstep*midbd;
ball->x[1]+=ball->v[1]*mstep*midbd;
hit_boundary(ball,bd,e,time_step);
ball->x[0]+=ball->v[0]*mstep*(32-midbd);
ball->x[1]+=ball->v[1]*mstep*(32-midbd);
ball->hit=true;
bdhit[bdhitnum]=b;
if(bdhitnum==0)bdhitnum++;
else{
bool newball=true;
for(int kk=0;kk<bdhitnum;kk++){
if(b==bdhit[kk])newball=false;
}
if(newball)bdhitnum++;
}
}
}
}
}
//detect holes
for(int bl=0;bl<num_balls;bl++){
if(balls[bl].status==BS_MOVING){
for(int h=0;h<num_holes;h++){
if(detect_hole(balls[bl],holes[h],time_step)){
////////////////////////////////////////////////////////////
ballin[numin]=bl;
numin++;
///////////////////////////////////////////////////////////////
balls[bl].status=BS_IN_THE_HOLE;
balls[bl].h_num=h;
balls[bl].before_in[0]=balls[bl].x[0];
balls[bl].before_in[1]=balls[bl].x[1];
balls[bl].before_in[2]=balls[bl].x[2];
}
}
}
}
}
void CPoolGame::Move(double time_step)
{
double a=-0.18;
double nv[2];
for(int i=0;i<num_balls;i++){
CBall *p=balls+i;
if(p->status==BS_MOVING){
if(p->hit==false){
p->x[0]+=p->v[0]*time_step;
p->x[1]+=p->v[1]*time_step;
}
}
if(p->hit==true)p->hit=false;
}
for(i=0;i<num_balls;i++){
CBall *p=balls+i;
if(p->status==BS_IN_THE_HOLE){
CHole *hole=holes+p->h_num;
inhole(p,hole);
}
if(p->status==BS_MOVING){
double v0=p->v[0];
double v1=p->v[1];
double temp=sqrt(p->v[0]*p->v[0]+p->v[1]*p->v[1]);
temp=1.0/temp;
nv[0]=p->v[0]*temp;
nv[1]=p->v[1]*temp;
p->v[0]+=a*nv[0]*time_step;
p->v[1]+=a*nv[1]*time_step;
if(v0*p->v[0]+v1*p->v[1] <= 0){
p->v[0]=0;
p->v[1]=0;
p->status=BS_STATIONARY;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -