⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game_physics.cpp

📁 这是一个台球游戏的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -