Odpowiedz do komentarza autora:
ok, dziękuję
A jak wygląda zapis takich sił. Jak możecie poradzić mi zapisanie jakiejś siły w niskopoziomowym C++
Czy to ma być jakiś wektor, długość i kąt nachylenia, czy jest jakiś lepszy sposób, jak poradzić sobie z panowaniem nad takim kodem kiedy jest tego dużo.
Podzielić zjawiska na osobne funkcje.
A później, jak odczytywać siłę i wykonywać ruch kiedy np. wektor siły jest dłuższy niż odległość od przeszkody.
Zamieszczam jako odpowiedz, by ten temat na chwilę był znów wyżej i by dostać łapkę ;)
Siłę to wektor. Wektor możesz zapisać jako 3 liczby (albo 2 w zależności od tego czy to fizyka 2D czy 3D). Najprościej zapisywać je jako współrzędne z racji prostego i łatwego kierowania nimi. Natomiast możesz to zrobić jako długość i kąt, ale podział siły na składowe Fx, Fy, Fz jest czytelniejszy. Marginesem mówiąc masz do czynienia z wektorem to wszędzie gdzie będą obliczenia z wektorami będziesz miał 3 równania.
Jak wykonywać obliczenia? Weźmy przykład symulacji grawitacji. Bierzesz wszystkie siły jakie działają na ciało i liczysz wypadkową:
Fwypadkowa = FgrawitacjiZiemi + FgrawitacjiKsiężyca + ....
Ogólnie mówiąc Fwyp = suma wszystkich sił działających na ciało (II Zasada Dynamiki Newtona). Tylko kłania się zasadnicze pytanie co to ta siła i jak przekłada się na rzeczywistość. I tu przychodzi znów II ZDN: Fwypadkowa=ma, siła = masa_tego_ciała razy przyśpieszenie. Z tego można obliczyć przyśpieszenie. Z przyśpieszenia natomiast prędkość. Z prędkości nowe położenia.
Przykładowy algorytm dla symulacji grawitacji np Układu Słonecznego:
void GravitySystem::gravity()
{
reset_acceleration();
for(int i=0; i<size(); i++) // petla obliczania przyspieszenia dla kazdego ciała
{
for(int j=0; j<size(); j++) // petla obliczania oddzialywania kazdego ciala z kazdym
{
if(j!=i) // zeby planeta nie przyciagala sama siebie, bo wyjdzie wtedy dzielenie przez 0!
{
double xx = objects[j].x - objects[i].x;
double yy = objects[j].y - objects[i].y;
double rr = sqrt(xx*xx + yy*yy);
double r3 = pow(rr, 3);
double mj = objects[j].m;
// przyspieszenie grawitacyjne z wektorowego prawa Newtona
// przyspieszenie to wektor, wiec mamy dwa rownania:
objects[i].ax += G*mj*xx/r3;
objects[i].ay += G*mj*yy/r3;
}
}
}
}
void GravitySystem::reset_acceleration()
{
for(int i=0; i<size() ; i++)
{
objects[i].ax = 0;
objects[i].ay = 0;
}
}
void GravitySystem::euler_method(double dt)
{
for(int i=0; i<size(); i++) // petla dla kazdego ciala
{
// Obliczanie wektora predkosci (2D) v+=dv, dv = a*dt
objects[i].vx += objects[i].ax*dt;
objects[i].vy += objects[i].ay*dt;
// Obliczanie wektora nowego polozenia (2D) s+=ds, ds=v*dt
objects[i].x += objects[i].vx*dt;
objects[i].y += objects[i].vy*dt;
}
}
Jak widać jest suma przyśpieszeń działających na i-te ciało i jest zamienianie na położenie... Nie liczyłem tutaj równań z sił, bo jest to niepotrzebne w tym przypadku. Są symulacje w, których wystarczą obliczenia z przyśpieszeń i prędkości (np bilard). Przykład czyściej z siłami: Rakieta ( nie chodzi o rzut ukośny ):
Fwypadkowa = Fgrawitacji + Fgazówodwylotowych
Fgrawitacji = -m*g (minus, bo w przeciwnym kierunku do siły unoszącej)
Fgazówodwylotowych = przykladowa_funkcja_zalezna_od(predkosci lotu, predkosci_utraty_masy_gazów
/* zależy jak bardzo chcemy być zgodni z fizyką */ )
Fwypadkowa = m*a
a = Fwypadkowa/m
No i dalej liczenie prędkości i nowego położenia np metodą Eulera.
Natomiast zadałeś jeszcze pytanie:
jak odczytywać siłę i wykonywać ruch kiedy np. wektor siły jest dłuższy niż odległość od przeszkody.
Powinno brzmieć: Co jeśli nowe położenie znajduje się wewnątrz jakiegoś obiektu... Należy przesunąć go tak by oba stykały się krawędziami. Przy małym kroku czasowym i małych prędkościach coś takiego jest mało zauważalne i nie trzeba uwzględniać. Wektor siły może być dłuższy od odległości od przeszkody, bo on jest tworem niejako wirtualnym, a nie czymś fizycznym jak realne przesunięcie (zależne od wartości tej siły).