Autor Wątek: [2D] Sily i ich dzialanie na obiekty  (Przeczytany 2550 razy)

Offline soku11

  • Użytkownik

# Czerwiec 05, 2008, 17:33:28
WITAM!
Mam takie pytanie dotyczace dzialania sil podczas pracy z obiektami na scenie 2D. Mianowicie zalozmy, ze mam klase sila, ktora wyglada tak:
struct Force
{
  float fx;
  float fy;
};

I teraz zalozmy, ze mamy na scenie jakas kulke. I pytanie dotyczy oddzialywania roznych sil na ta kulke. Bo rozumiem, ze ruch kulki bedzie wywolany przez sile wypadkowa, bedaca wynikiem dzialania roznych sil. Teraz pytanie. Czy przy obliczeniach co kazda klatke nalezy wyliczac  ta sile wypadkowa?? I jak np. odnosic sie do sily sprezystosci i sily normalnej(odbicie)?? Czy obiekt powinien posiadac tablice wskaznikow na sily i z niej jakos odczytywac jakie sily na nie dzialaja?? Jak w takim wypadku zrobic z podanymi silami?? Bo sprezystosc wystapi tylko przy kolizjach - trzeba ja dodac, wyliczyc wypadkowa i usunac - tak by dzialala tylko w jedynm momencie. Pytanie mam tez apropo predkosci generowanych przez dana sile. Bo jest taki wzorek:
v=v_0+a*t
W zwiazku z tym istnieje potrzeba przechowywania czasu :/ Tylko jak to zrobic?? Czy jesli sila wypadkowa sie wyzeruje to przestac liczyc czas?? I czy przechowoywac go indywidualnie dla kazdego obiektu?? Mam nadzieje, ze rozumiecie moj problem :P Z gory dzieki za pomoc. POZDRO

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Kos

  • Użytkownik
    • kos.gd

# Czerwiec 05, 2008, 18:15:21
Istotnie. Mierzysz po prostu aktualny czas systemowy w każdej klatce gry i podstawiasz go do tego właśnie wzoru :)

Odnośnie sił, to jak sobie to zaprojektujesz, tak będziesz miał. Albo każdy obiekt wie, jakie siły mają docelowo na niego działać, albo robisz jedną klasę która zajmuje się każdym istniejącym obiektem po kolei i im dodaje poszczególne siły co klatkę. Potem dla każdego obiektu sumujesz wszystkie, dzielisz przed masę, mnożysz przez czas i masz gotową zmianę prędkości.


Offline Ciunkos

  • Użytkownik
    • Black Sheep

# Czerwiec 05, 2008, 18:15:50
t - delta czasu, liczysz ją co klatkę zapisując ja najlepiej w jakiejś zmiennej(globalnej? ;)) np. float DeltaTime.
A zamiast struct Force dla sił, struct Velocity dla prędkości itp... użyj wektorów DirectX-owych, lub napisz sam np. tak:
class Vector2D {
float x;
float y;
...
};

Obiekt w grze może wyglądać mniej więcej tak:
class CObject {
...
float Mass;
Vector2D Position;
Vector2D Velocity;
Vector2D Force;
...
};

A potem co klatkę liczysz działające siły itp. po prostu dodając je do Object.force (traktujesz je jako wektory), a tak ogólnie to może wyglądać to tak:
float DeltaTime;
CObject Object;

PETLAGRY {
   //Tu sobie poczytaj o metodach mierzenia czasu i delty. Polecam już drugi chyba raz artykuł Xiona "Pętla czasu rzeczywistego".
   ObliczDeltaTime();
   //Wyczyść siły:
   Object.Force = Vector2D(0, 0);
   //Taka prosta grawitacja (przyjmując 1=1m).                   
   Object.Force += Vector2D(0.0f, Object.Mass*-10.0f);
   //Obliczenie prędkości:
   Object.Velocity += Object.Force/Object.Mass*DeltaTime;
   //Wyliczenie pozycji:
   Object.Position += Object.Velocity*DeltaTime;

   //Rysowanie:
   Draw();
}


Pętla czasu rzeczywistego - masz do poczytania bo naprawdę Ci się to przyda ;)


Offline soku11

  • Użytkownik

# Czerwiec 05, 2008, 18:47:14
Ok wielkie dzieki :) To w sumie tak jak myslalem :P

BTW. A co to za roznica, czy to struktura czy klasa o skladnikach publicznych?? W kazdym badz razie moze zrobie to na klasach i poukrywam skladowe... POZDRO

Offline Kos

  • Użytkownik
    • kos.gd

# Czerwiec 05, 2008, 18:55:26

Obiekt w grze może wyglądać mniej więcej tak:
class CObject {
...
float Mass;
Vector2D Position;
Vector2D Velocity;
[b]Vector2D Force;[/b]
...
};

Z tym się nie zgodzę. Obiekt powinien cały czas "pamiętać" swoją aktualną po pierwsze pozycję, po drugie prędkość.

Natomiast zarówno siły, jak i przyspieszenie (liczone na podstawie sumy sił oraz masy) są ważne jedynie dla obecnej klatki. Przyspieszenie przemnożone przez czas jest dodawane do prędkości, prędkość znowu przemnożona przez czas - do pozycji.
Następnie prędkość i pozycja obiektu są przez niego "zapamiętane", a wartość chwilowej sumy sił i chwilowego przyspieszenia są zapominane i liczone "od zera" w nowej klatce.

Offline Ciunkos

  • Użytkownik
    • Black Sheep

# Czerwiec 05, 2008, 19:09:12
A co powiesz na to, że jakieś ciało działa w pewnym obszarze np. siłą przyciągania skierowana do środka tego obiektu (dla ułatwienia równą 1N/m) na wszystkie obiekty w promieniu np. 100m? Co z takim fantem zrobić? A no można zrobić to tak:
...
//Object - obiekt przyciągający;

vector<CObject*> ObiektyWPozblizu = ZnajdzObiektyWPozblizu(Object, 100.0f);
IloscObiektowWPoblizu = ObiektyWPozblizu.size();

for(unsigned int i=0; i<IloscObiektowWPoblizu; i++) {
   ObiektWPozblizu[i]->Force += Vector2D(Object.Position.x-ObiektWPozblizu[i]->Position.x, Object.Position.y-ObiektWPozblizu[i]->Position.y);
}
...

Offline soku11

  • Użytkownik

# Czerwiec 07, 2008, 00:33:52
A jeszcze mi sie urodzilo takie pytanko... Majac roznice czasu od wczesniejszej klatki chyba nie za bardzo sie to przyda przy generowaniu wartosci predkosci... Bo przeciez wzor jest
v=v_0+at

A to moje t, to nie roznica czasu, tylko czas przez jaki dziala dana sila :/ Gdzie tkwi blad w moim rozumowiu?? POZDRO

maxest

  • Gość
# Czerwiec 07, 2008, 00:54:07
Moze inaczej... Pomysl o tym wzorze nie w fizycznym sensie, ale w bardziej "naturalnym", czyli:
obecna_predkosc = obecna_predkosc + wektor_predkosci
To jest, powiedzmy, taki dosc standardowy i "naturalny" wzor na zmiane predkosci. Teraz aby animacja dzialala w "stalym" czasie niezaleznie od ilosci FPS'ow to mnozy sie to, co dodajemy, przez czas trwania ostatniej klatki, a wiec
obecna_predkosc = obecna_predkosc + wektor_predkosci*czas_trwania_ostatniej_klatki
Z fizycznego punktu widzenia w powyzszym nawet jednostki sie nie zgadzaja :D, ale to jest poprawne :)

// po prostu wszystkie wielkosci, ktore powoduja jakas "zmiane ruchu" obiektu, trzeba przemnozyc przez czas trwania ostatniej klatki

Offline Netrix

  • Redaktor
    • Netrix’s devBlog

# Czerwiec 07, 2008, 09:38:31
A jeszcze mi sie urodzilo takie pytanko... Majac roznice czasu od wczesniejszej klatki chyba nie za bardzo sie to przyda przy generowaniu wartosci predkosci... Bo przeciez wzor jest
v=v_0+at

A to moje t, to nie roznica czasu, tylko czas przez jaki dziala dana sila :/ Gdzie tkwi blad w moim rozumowiu?? POZDRO

To co podałeś to jest wzór na prędkość w określonym czasie, jest to funkcja stosowna do rysowania wykresu, ponieważ zawiera wartość początkową.
Tego co potrzebujesz to przyrost prędkości w czasie, czyli zwykły wzór
v= a * t (t - zmiana czasu, czyli czas trwania klatki)Aby obliczyć prędkość w kolejnej klatce potrzebujesz wartość prędkości w poprzedniej klatce, więc wychodzi:
v = v' + at

v - nowa wartość prędkości
v' - poprzednia wartość prędkości

@maxest
Jednostki w fizyce muszą się zgadzać.


« Ostatnia zmiana: Czerwiec 07, 2008, 09:46:43 wysłana przez Netrix »

Offline Rav

  • Użytkownik

# Czerwiec 07, 2008, 11:00:47
@maxest: To czego dokonałeś to podmiana nazwy wektor przyspieszenia na wektor prędkości. Może niektórym wyda sie bardziej zrozumiałe jednak to pewne kaleczenie fizyki.

@soku11: czas przez jaki działa siła na ciało  jest właśnie różnicą czasu pomiędzy klatkami.

Offline soku11

  • Użytkownik

# Czerwiec 07, 2008, 13:10:56
Ok teraz juz rozumiem :) Teraz tylko zaimplementuje jakas klase abstrakcyjna z podobnymi funkcjami do obliczania sl i predkosci itd :) W kazdym badz razie juz wsystko jasne dzieki wam :P BTW. Nie ma tutaj czegos takiego jak przycisk, ze mi ktos pomogl?? POZDRO

maxest

  • Gość
# Czerwiec 07, 2008, 13:31:50
Jest taki plusik obok napisu "Karma" ;)

Offline RedHot

  • Użytkownik

# Czerwiec 07, 2008, 13:44:25
Niestety karmę można dawać od 20  czy 25 postów. Wychodzi na to, że pomagając nowym użytkownikom karmy nie zarobimy.

Offline yorp

  • Użytkownik
    • ProfessionGG Project

# Czerwiec 07, 2008, 14:59:08
to nie pomagajmy ;)

...no to chyba koniec tematu ;)

Offline soku11

  • Użytkownik

# Czerwiec 07, 2008, 14:59:39
No wlasnie ja tego plusika jeszcze nie mam :) Sporo mi pomogliscie, no ale jak nabije wiecej postow kiedys to na pewno sie odwdziecze :) POZDRO