0
点赞
收藏
分享

微信扫一扫

物理引擎-弹性碰撞动量守恒

河南妞 2022-04-21 阅读 75
c语言
// 多物体物理引擎.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include<graphics.h>
#include <math.h>
#include <malloc.h>
#define PI 3.14159265
#define G 6.67259*10e-11
double val = 180.0 / PI;
 struct OBB {
	int radius;
	double x, y;
	double vx, vy;
	int m;
	double fx, fy;
	double a;
};
 struct vector {
	 double x;
	 double y;
 };
OBB* initOBB(
	int vx0, int vy0,
	int radius,int b)//结构体指针函数,给出点,初始化OBB;
{
	OBB* obb = (OBB*)malloc(sizeof(OBB));
	obb->x = b%200;
	obb->y = b%300;
	if (obb->x < 30) { obb->x += 30; }
	if (obb->y < 30) { obb->y += 30; }
	if (600-(obb->x) < 30) { obb->x -= 30; }
	if (500- (obb->y) < 30) { obb->y -= 30; }
	obb->radius = radius;
	obb->vx = vx0;
	obb->vy = vy0;
	/*printf("%d ", obb->vx);*/
	
	return obb;
}

double distance(OBB* a1, OBB* a2) {
	return sqrt(pow((a1->x - a2->x) ,2) + pow((a1->y - a2->y) ,2));
}
double angle(vector* v1,vector* v2){
	double ret = (atan2(v1->y,v1->x)- atan2(v2->y, v2->x)) * val;
	return ret;
}
//bool collapse(OBB* b1, OBB* b2) {
//	if (distance(b1, b2) < double(b1->radius + b2->radius)) {  return true; }
//	else {return false; }
//}
vector sub(vector* v1, vector* v2) {
	vector v0 = { v1->x - v2->x,v1->y - v2->y };
	return v0;
}
double multiply(vector* v1, vector* v2) {
	double mul = (v1->x * v2->x + v1->y * v2->y) / sqrt(pow(v2->x,2)+pow(v2->y,2));
	return mul;
}
vector direct(vector* v) {
	vector unit = {v->x/sqrt(pow(v->x,2)+pow(v->y,2)),v->y/ sqrt(pow(v->x,2) + pow(v->y,2)) };
	if (fabs(unit.x * unit.y) > 0.000001) { return { unit.x,unit.y }; }
	else { return{ 0,0 }; }
}
void conservation(OBB* obj1, OBB* obj2) {
	vector vd = { obj2->y - obj1->y, obj2->x - obj1->x };
	vector v1 = { obj1->vx,obj1->vy };
	vector v2 = { obj2->vx,obj2->vy };
	double v1x = multiply(&v1, &vd);
	double v2x = multiply(&v2, &vd);
	double v1xx = ((obj1->m - obj2->m) * v1x + 2 * obj2->m * v2x) / (obj1->m + obj2->m);
	double v2xx= ((obj2->m - obj1->m) * v2x + 2 * obj1->m * v1x) / (obj1->m + obj2->m);
	vector vec = direct(&vd);	
	vector vec1 = { vec.x * (v1xx - v1x),vec.y * (v1xx - v1x) };
	vector vec2 = { vec.x * (v2xx - v2x),vec.y * (v2xx - v2x) };
	obj1->vx += vec1.x;
	obj1->vy += vec1.y;
	obj2->vx += vec2.x;
	obj2->vy += vec2.y;
}
void interaction(OBB* obj1, OBB* obj2) {
	double ret = atan2(obj1->vy - obj2->vy, obj1->vx - obj2->vx)*val;
	double r = distance(obj1, obj2);
	vector f1, f2;
	if (r > (obj1->radius + obj2->radius+3)) {
		f1 = { G * obj2->m * obj1->m * cos(ret) / r * r,G * obj2->m * obj1->m * sin(ret) / r * r };
		f2 = { G * obj2->m * obj1->m * cos(180 + ret) / r * r,G * obj2->m * obj1->m * sin(180 + ret) / r * r };
		obj1->fx = f1.x;
		obj1->fy = f1.y;
		obj2->fx = f2.x;
		obj2->fy = f2.y;
		
	}
} 
void move(OBB*obb1,OBB*obb2) {
	
	while (1)
	{
		interaction(obb1,obb2);
		obb1->x = obb1->x + obb1->vx;
		obb1->y = obb1->y + obb1->vy;
		obb2->x = obb2->x + obb2->vx;
		obb2->y = obb2->y + obb2->vy;
		if (distance(obb1, obb2) <= (obb1->radius + obb2->radius + 3)) {
			obb1->x = obb1->x - obb1->vx;
			obb1->y = obb1->y - obb1->vy;
			obb2->x = obb2->x - obb2->vx;
			obb2->y = obb2->y - obb2->vy;
			conservation(obb1, obb2);
			obb1->x = obb1->x + obb1->vx;
			obb1->y = obb1->y + obb1->vy;
			obb2->x = obb2->x + obb2->vx;
			obb2->y = obb2->y + obb2->vy;
		}
		circle(obb2->x, obb2->y, obb2->radius);
		circle(obb1->x, obb1->y, obb1->radius);
		Sleep(1);
		if (500 - obb1->y <= 30)
			obb1->vy = -(obb1->vy);
		if (600 - obb1->x <= 30)
			obb1->vx = -(obb1->vx);
		if (obb1->x <= 30)
			obb1->vx = -(obb1->vx);
		if (obb1->y <= 30)
			obb1->vy = -(obb1->vy);
		if (500 - obb2->y <= 30)
			obb2->vy = -(obb2->vy);
		if (600 - obb2->x <= 30)
			obb2->vx = -(obb2->vx);
		if (obb2->x <= 30)
			obb2->vx = -(obb2->vx);
		if (obb2->y <= 30)
			obb2->vy = -(obb2->vy);
		clearcircle(0, 0, 1000);
	}
}
int main() 
{
	int i;
    OBB* obj[2];
	int a[2];
	srand((unsigned)time(NULL));
	for (i = 0; i<2; i++) {
		 a[i] = rand();
	}
	obj[0] = initOBB(2, -1, 35, a[0]);
	obj[1] = initOBB(3, 2.5, 35, a[1]);
	obj[0]->m = 1;
	obj[1]->m = 1;
	if (distance(obj[0], obj[1]) <= 70 ){
		obj[1]->x = obj[1]->x + 2*obj[1]->radius+2*obj[2]->radius;
	}
	initgraph(600, 500);
	move(obj[0],obj[1]);
	getchar();
	closegraph();
	return 0;

}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 作者qq:2356224391,欢迎交流。
------------------------------版权所有:啾啾啾佳------------------------------------------

咕咕咕了好久 这几天终于狠心写了个物理引擎。

用了graphics库。引入向量,最主要的函数是conservation,把两球速度分解到球心连线上进行动量加能量守恒即可。预留了接口,可以扩展为多个物体

举报

相关推荐

0 条评论