@Sneiksus

Как сделать обработку столкновений между шарами?

У менят есть следующий код в котором два шарика двигаются по сцене и при столкновении со стеной сцены происходит отскок. Мне нужно сделать тоже самое но только уже когда один шар столкнется с другим шаром? Как проще всего это можно сделать, и какие еще формулы нужно использовать. Шаров может быть всего 2

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <math.h>
#include<time.h>
#include <GL/glut.h>
float t1 = 0, t2 = 0, t3 = 0, t4 = 0, dt=0.01;
float x = 0, y = 0;
float vx = 2, vy = 2;
float Lxmax = 10, Lymax = 10;
float r = 1;
float count = 1, dimensions = 2;
int odrazka = 0;
struct Coordinate {
	float x;
	float y;
	int vy;
	int vx;
};
struct Coordinate cords[100];
void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// Set color to red
	glColor3f(1.0f, 0.0f, 0.0f);
	for (int i = 0; i < count; i++) {
		glPushMatrix();
		glTranslatef(cords[i].x, cords[i].y, 0);
		glutSolidSphere(r, 20, 20);
		glPopMatrix();
	}

	glutSwapBuffers();
}


void obsluhaReshape(int width, int height) {
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (width == 0) width++;
	const float aspect_ratio = (float)width / height;
	gluOrtho2D(-0.5 * Lxmax, 0.5 * Lxmax * aspect_ratio, -0.5* Lymax, 0.5 * Lymax*aspect_ratio);
}

void timer(int value)
{
	
	
	/*t1 = (0.5 * Lxmax - (x + r)) / vx;
	t2 = (-0.5 * Lxmax - (x + r)) / vx;
	t3 = (0.5 * Lxmax - (y + r)) / vy;
	t4 = (0.5 * Lxmax - (y + r)) / vy;
	float tz = abs(t1)<abs(t2)?t1:t2;
	tz = abs(tz) < abs(t3) ? abs(tz) : abs(t3);
	tz = abs(tz) < abs(t4) ? abs(tz) : abs(t4);*/

	//float m = int(tz / dt) + 1;
	//	dt = tz / m;
	//x = x + vx * dt;
	//y = y + vy * dt;
	printf("dt: .%2f\n", dt);
	if (odrazka == 0) {
		float minsT[1000];
		for (int i = 0; i < count; i++) {
			float t1 = (0.5 * Lxmax - (cords[i].x + r)) / cords[i].vx;
			float t2 = (-0.5 * Lxmax - (cords[i].x + r)) / cords[i].vx;
			float t3 = (0.5 * Lymax - (cords[i].y + r)) / cords[i].vy;
			float t4 = (-0.5 * Lymax - (cords[i].y + r)) / cords[i].vy;
			if (t1 <= 0)
				t1 = 1000;
			if (t2 <= 0)
				t2 = 1000;
			if (t3 <= 0)
				t3 = 1000;
			if (t4 <= 0)
				t4 = 1000;
			minsT[i] = fminf(fminf(fminf(fabs(t1), fabs(t2)), fabs(t3)), fabs(t4));

		}
		float minT = minsT[0];
		//for (int i = 1; i < count; i++) {
		//	if (minT != 0)
		//		break;
		//	minT = minsT[i];

		//}
		for (int i = 1; i < count; i++) {
			if (minsT[i] < minT && minsT[i] >0.0) {
				minT = minsT[i];
			}
		}
		int n = 1 + (int)(minT / 0.01);
		dt = minT / n;
		if (dt == 0.0)
			return;
		odrazka = 1;
	}
	for (int i = 0; i < count; i++) {
		cords[i].x = cords[i].x + cords[i].vx * dt;
		cords[i].y = cords[i].y + cords[i].vy * dt;
		if (cords[i].x + r > 0.5 * Lxmax) {
			cords[i].vx *= -1;
			cords[i].x = cords[i].x + cords[i].vx * dt;
			odrazka = 0;
		}
		else if (cords[i].x - r < -0.5 * Lxmax) {
			cords[i].vx *= -1;
			cords[i].x = cords[i].x + cords[i].vx * dt;
			odrazka = 0;
		}
		else if (cords[i].y + r > 0.5 * Lymax) {
			cords[i].vy *= -1;
			cords[i].y = cords[i].y + cords[i].vy * dt;
			odrazka = 0;
		}
		else if (cords[i].y - r < -0.5 * Lymax) {
			cords[i].vy *= -1;
			cords[i].y = cords[i].y + cords[i].vy * dt;
			odrazka = 0;
		}
	}
	glutTimerFunc(25, timer, 0);
	glutPostRedisplay();
}

int main(int argc, char** argv)
{
	srand(time(NULL));
	Lxmax = atof(argv[1]);
	Lymax = atof(argv[2]);
	count = atof(argv[3]);
	dimensions = atof(argv[4]);
	for (int i = 0; i < count; i++) {
		float minX = -0.5 * Lxmax + r;
		float maxX = 0.5 * Lxmax - r;
		float minY = -0.5 * Lymax + r;
		float maxY = 0.5 * Lymax - r;
		cords[i].x = ((float)rand() / (float)(RAND_MAX)) * (maxX - minX) + minX;
		cords[i].x = ((float)rand() / (float)(RAND_MAX)) * (maxY - minY) + minY;
		//cords[i].x = (float)rand() / RAND_MAX * (Lxmax - 0.5-r) * (Lxmax+r);
		//cords[i].y = (float)rand() / RAND_MAX * (Lymax - 0.5 - r) * (Lymax + r);
		cords[i].vy = rand()  % 5+1;
		cords[i].vx = rand() % 5 + 1;
	}
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(800, 800);
	glutCreateWindow("DU10");
	glutDisplayFunc(display);
	glutTimerFunc(0, timer, 0);
	glutReshapeFunc(obsluhaReshape);
	glutMainLoop();
	return 0;
}
  • Вопрос задан
  • 89 просмотров
Пригласить эксперта
Ответы на вопрос 3
mayton2019
@mayton2019
Bigdata Engineer
Да ты прикалываешся. Почему у тебя в параметрах цикла типы разные. Чтоб жилось труднее?

float count = 1, dimensions = 2;
count = atof(argv[3]);
...
for (int i = 0; i < count; i++) {
Ответ написан
Комментировать
Stalker_RED
@Stalker_RED
А в чем сложность?
Берете координаты шаров, считаете расстояние, если оно меньше, чем сумма радиусов - шары столкнулись.
Ответ написан
wataru
@wataru
Разработчик на С++, экс-олимпиадник.
Тут нужна школьная геометрия. Класс на 9, наврено даже раньше. Координаты центров шаров через время t будут (x1(t),y1(t))=(x1+vx1*t, y1+vy1*t)

Во-первых, проверьте, что шары сейчас не пересекаются. Иначе выталкивайте их вдоль прямой через центры.
Потом вам надо решить уравнение квадратное уравнение (x1(t)-x2(t))^2+(y1(t)-y2(t))^2 = 4*r^2.

Найдите минимальное положительное решение. Вот через это время шары столкнуться. Как вы там со стенами считаете - надо будет взять минимальное время и на него сдвинуть шары, а потом обработать столкновение.

Если 2 шара столкнулись, то их скорости поменяются вдоль вектора на их ценры. Надо решить уравнения сохрнения импульса и энергии. Решение смотрите тут (Формулы в комментарии в моем ответе там).

P.s. у вас там в коде вижу ошибку. Вы где считате пересечение со стенами знаки напутали. Должно быть:
float t1 = (0.5 * Lxmax - (cords[i].x + r)) / cords[i].vx;
float t2 = (-0.5 * Lxmax - (cords[i].x - r)) / cords[i].vx;


Ну и вы там не проверяете, вдруг скорость нулевая, тогда время до пересечения - бесконечность.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы