Zderzenie ukośne kulek w oknie graficznym nie działa prawidłowo – prośba o pomoc

0

Probuje napisac grę w kręgle i od dluzszego czasu utknalem w jednym miejscu. Nie moge zrobic zderzenia ukosnego doskonale sprezystego kulek. Oto jeden z moich pomyslow w ktorym kulki raz odbijaja sie prawidlowo a innym razem nie, czasami zas znikaja.

Moj kod:


void collideBall (double *x, double *y, double *Vx, double *Vy)
{
	double alfa1=0, alfa2, alfa3, d=40;		//alfa2-kat miedzy wypadkowa predkosci a pozioma
	for (int i=1;i<16;i++)					//alfa3-kat miedzyskladowa w strone odbijanej kulki 
	{										//alfa1 kat miedzy skladowa w kierunku odbijanej kulki a wypadkowa predkoscia
		for (int j=0; j<i;j++)
		{
			if (sqrt((pow(x[i]-x[j],2)+pow(y[i]-y[j],2)))<=40.0)		//x[i] oraz y[i] wspolrzedne kulek
			{															//Vx[i] i Vy[i] predkosci skladowe
				double V=sqrt(Vx[i]*Vx[i]+Vy[i]*Vy[i]);
				alfa2=atan(fabs(Vy[i]/Vx[i])); 
				alfa3=atan(fabs(x[i]-x[j])/fabs(y[i]-y[j]));
				if ((alfa2>=0)&&(alfa2<=1.57)) alfa1=1.57-alfa2-alfa3;
				if ((alfa2<0)||(alfa2>1.57)) alfa1=1.57-alfa3;
				if (Vx[i]>0)
				{
					Vx[i]-=V*cos(alfa1)*cos(alfa1+alfa2);
					Vx[j]+=V*cos(alfa1)*cos(alfa1+alfa2);
				}
				else
				{
					Vx[i]+=V*cos(alfa1)*cos(alfa1+alfa2);
					Vx[j]-=V*cos(alfa1)*cos(alfa1+alfa2);
				}
				if (Vy[i]<0)
				{
					Vy[i]+=V*cos(alfa1)*sin(alfa1+alfa2);
					Vy[j]-=V*cos(alfa1)*sin(alfa1+alfa2);
				}
				else
				{
					Vy[i]-=V*cos(alfa1)*sin(alfa1+alfa2);
					Vy[j]+=V*cos(alfa1)*sin(alfa1+alfa2);
				}

				printf ("%lf\n %lf\n %lf\n", alfa1, alfa2, alfa3);
			}
		}
	}
}
2

Na początek bym zamienił atan na atan2 (on zajmuje się ćwiartkami za Ciebie).

0

Troche poczytalem o tym ale nadal nie bardzo rozumiem dzialania tej funkcji. Bylbym bardzo wdzieczny gdyby ktos mogl napisac ta funkcje albo chociaz mnie jakos nakierowac. Dobijajace sa te wszystie bezskuteczne proby wyprowadzania tych wzorow a podejrzewam ze z zastosowaniem tej funkcji program znacznie sie skroci i uprosci.

1

atan2(y, x) podaje w radianach kąt wektora [x, y]. Na górze układu współrzędnych (kolejno I i II ćwiartka) masz kąt od 0 do 180 stopni. Na dole (kolejno IV i III ćwiartka) masz kąt od 0 do -180 stopni.

0

Niestety nadal nie potrafie tego podzielic w zaden logiczny sposob na przypadki i napisac dzialajacej funkcji. Jakby ktos mial chwile to mogłby chociaz napisac mi jakis pomyslowy i nie przesadnie skomplikowany zarys?

1

Czy musisz to sam zaprogramować? Bo jak nie to skorzystaj z silnika fizycznego, który całą symulację odwali za Ciebie ;)

Poszukaj: Box2D

0

Niestety ten projekt mam oddac wykladowcy a watpie zeby chcial instalowac dodatkowa biblioteke zeby sprawdzić dzialanie programu. Ale ogolnie to pomysł dobry, na nastepnych cwiczeniach spytam sie czy moge zastosowac takie rozwiazanie.

0

Zrobilem to zderzenie na podstawie instrukcji jaka mielismy na laboratoriach z informatyki na studiach.
Czy moglby ktos przejrzec ta moja funkcje i podpowiedziec mi gdzie mam blad?

link do instrukcji ze wzorami: https://www.meil.pw.edu.pl/za/ZA/Courses/Informatyka-1
Instrukcja 5.2

Moja funkcja:

void collideBall (double *x, double *y, double *Vx, double *Vy)
{

for (int i=1;i<16;i++)
{
	for (int j=0; j<i;j++)
	{
		if (sqrt((pow(x[i]-x[j],2)+pow(y[i]-y[j],2)))<=40.0)
		{
			double v1x=Vx[i]-Vx[j];
			double v1y=Vy[i]-Vy[j];
			double L=sqrt( (Vx[i]-Vx[j])*(Vx[i]-Vx[j]) + (Vy[i]-Vy[j])*(Vy[i]-Vy[j]) );
			double nx=(x[i]-x[j])/L;
			double ny=(y[i]-y[j])/L;
			double Vnx=(v1x*nx+v1y*ny)*nx;
			double Vny=(v1x*nx+v1y*ny)*ny;
			double v1xnew=v1x-Vnx;
			double v1ynew=v1y-Vny;
			double v2xnew=Vnx;
			double v2ynew=Vny;

			Vx[i]=Vx[i]+v1xnew;
			Vy[i]=Vy[i]+v1ynew;
			Vx[j]=Vx[j]+v2xnew;
			Vy[j]=Vy[j]+v2ynew;

		}
	}
}

}

0

Przeanalizuj zachowanie symulatora przy większej ilości kul/kręgli.
Przykład: kołyska Newtona

0

Rozumiem jak dzialaja zderzenia i potrafie obliczyc predkosci na podstawie zasady zachowania energii i pedu, niestety nie potrafie tego przelozyc na uklad wspolrzednych. Po kazdej probie program zachowywal sie w nieprzewidywalny i dziwny sposob. Dlatego postanowilem sobie troche ulatwic i zastosowac wzory podane w instrukcji ktore byly podane w instrukcji na cwiczenia lecz to tez nie dziala prawidlowo (kulki zaczynaja przyspieszac i po chwili poruszaja sie bardzo szybko pojawiajac sie w losowych miejscach).
Siedzialem przy tym juz kilka dni i naprawde nie wiem co jest nie tak :(

0

Patrząc na Twój kod to przy kołysce Newtona, gdy prawa kula uderza w pozostałe będzie wszystko porządku. Natomiast gdy ta z lewej uderzy w pozostałe otrzymasz błędy (kulki w kolejnych krokach zaczną na siebie nachodzić).
Co do coraz szybszego poruszania się kulek to mogą być konsekwencja powyższego błędu, błędy zaokrągleń lub za duży krok symulacji.

0

sprawdzilem to i to samo dzieje sie przy zderzeniach z obu stron

0

Przeanalizuj ten fragment:

for (int i=1;i<16;i++)
{
    for (int j=0; j<i;j++)

Sytuacja pierwsza: kula k1 uderza w k2 i po tym k2 uderza w k3 (w jednym kroku symulacji)
Sytuacja druga: kula k3 uderza w k2 i po tym k2 uderza w k1 (w jednym kroku symulacji)

0
Delor napisał(a):

Przeanalizuj ten fragment:

for (int i=1;i<16;i++)
{
    for (int j=0; j<i;j++)

Sytuacja pierwsza: kula k1 uderza w k2 i po tym k2 uderza w k3 (w jednym kroku symulacji)
Sytuacja druga: kula k3 uderza w k2 i po tym k2 uderza w k1 (w jednym kroku symulacji)

Kroki sa na tyle male ze prawdopodobienstwo ze w jednym kroku zderza sie 3 kule jest bardzo male wiec to chyba nie powinno byc bledem. Musialyby jednoczesnie zetknac sie 3 kule. Zle myslę?
Ogolnie to nie jest glownym problemem poniewaz kulki odbijaja sie nieprawidlowo juz przy pierwszym odbiciu jednej kulki z druga nieruchoma

0

Jeśli coś może pójść źle, to pójdzie.
Początkowe ustawienie bil lub kręgli -> ta sytuacja

danielbr3 napisał(a):

Ogolnie to nie jest glownym problemem poniewaz kulki odbijaja sie nieprawidlowo juz przy pierwszym odbiciu jednej kulki z druga nieruchoma

No to inny problem do przeanalizowania:
Kula 1 - nieruchoma
Kula 2 - zbliża się z prędkością 10 [jednostek/krok] do kuli 1
Sytuacja a) kule są w odległości 9 od siebie
Sytuacja b) kule są w odległości 1 od siebie

0

Nastapil postep. Kulki juz sie odbijaja tylko nie zawsze prawidlowo (czasami widac ze w zlym kierunku).
Dodatkowo z czasem przyspieszaja. Po sprawdzeniu energii kinetycznej po kazdym uderzeniu okazuje sie ze zasada zachowania energii i pedu jest spelniona dla wiekszosci przypadkow poza kilkoma gdy z zerowej energii powstaje jakas niewielka energia.
Czym teraz moga byc spowodowane te dwie nieprawidlowosci?

void collideBall (double *x, double *y, double *Vx, double *Vy)
{

for (int i=1;i<16;i++)
{
	for (int j=0; j<i;j++)
	{
		if (sqrt((pow(x[i]-x[j],2)+pow(y[i]-y[j],2)))<=40.0)                              //sprawdzenie odleglosci
		{
			double Ek0=Vx[i]*Vx[i]+Vy[i]*Vy[i];                                          //Ek poczatkowa


			double v1x=Vx[i]-Vx[j];                                                            //roznica predkosci skladowych x i y
			double v1y=Vy[i]-Vy[j];                                                           
			double L=sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );          //odleglosc miedzy kulkami
			double nx=(x[i]-x[j])/L;                                                             //wartosci sinusa i cosinusa
			double ny=(y[i]-y[j])/L;                                                             
			double Vnx=(v1x*nx+v1y*ny)*nx;
			double Vny=(v1x*nx+v1y*ny)*ny;
			double v1xnew=v1x-Vnx;                                                  
			double v1ynew=v1y-Vny;
			double v2xnew=Vnx;
			double v2ynew=Vny;

			
			Vx[i]=v1xnew;                                //nowe predkosci
			Vy[i]=v1ynew;
			Vx[j]=v2xnew;
			Vy[j]=v2ynew;

			double Ek1=Vx[i]*Vx[i]+Vy[i]*Vy[i];                        //energie kinetyczne po zderzeniu kulki 1 i 2
			double Ek2=Vx[j]*Vx[j]+Vy[j]*Vy[j];
			printf ("%lf\t %lf\t %lf\t %lf\t %lf\t %lf\t %lf\t %lf\t %lf\t %lf\t %lf\n", v1x, v1y, L, nx, ny, Vnx, Vny, v1xnew, v1ynew, v2xnew, v2ynew);
			printf ("%lf\t %lf\t %lf\n", Ek0,Ek1, Ek2);
			
			
			
		}
	}
}

}

0

Odbijanie się kul w nieodpowiednim kierunku: ten inny problem z mojego postu?
Mała energia powstająca z niczego: jak mała? https://wandbox.org/permlink/Ho1tV3TZaRko6as9

0

Nie do konca zrozumialem co miales na mysli w tym poprzednim poscie. Mam to podzielic na jakies dwa przypadki?

A ta energia powstajaca z niczego jednak nie zawsze taka mala.
Co do odbic to nie widze zadnej reguly kiedy sa poprawne a kiedy nie

0

W tych sytuacjach a) i b) powiedz gdzie znajdą się kule po przeliczeniu przez algorytm a gdzie powinny w rzeczywistym świecie.

0

Przy prekosciach rzedu (-3;3) i odleglosci kulek 40 nie moga tak mocno na siebie nachodzic, zmieniaja predkosci natychmiast po zblizeniu sie na odleglosc mniejsza niz 2 promienie, nie ma tez problemu za zlaczaniem sie kulek?
Mam rozumiec ze trzeba troche nagiac fizyke i po odbiciu do jednej dodac pewna niewielka odleglosc a od drugiej odjac zeby miec pewnosc ze po odbiciu przekrocza granice stycznosci?

1

Jeżeli zagwarantujesz że tylko dwie kule (ciała) uczestniczą w zderzeniu to nie będzie problemu z nachodzeniem na siebie. Nie musisz naginać fizyki.
Masz wzór który liczy zmianę prędkości kul w chwili zderzenia a dajesz mu stany z czasu przed lub czasu po zderzeniu.
Musisz się pogodzić z tym, zmniejszyć krok symulacji aby zmniejszyć te błędy (mogą jednak wtedy zwiększać się błędy zaokrągleń) lub zacząć liczyć odbicia wtedy gdy zachodzą.

0

Mozliwe ze masz racje ale trudno mi to sprawdzic gdzy to nie jest glownym i pierwszym problemem jaki chce rozwiazac. Piszesz ze jest to spowodowane tym ze w zderzeniu moga brac udzial wiecej niz 2 kule jednoczesnie.
Jednak odbicie nie zachodzi prawidlowo nawet gdy wyraznie w odbiciu uczestnicza jednoczesnie 2 kule a reszta jest w sporo wiekszych odleglosciach od nich

1

Więcej ciał -> zachodzenie na siebie.
Reszta była o zderzeniu 2 ciał.

1 użytkowników online, w tym zalogowanych: 0, gości: 1