• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

SFML skok(fizyka), problem logiczny

Object Storage Arubacloud
0 głosów
850 wizyt
pytanie zadane 13 września 2016 w C i C++ przez prownnie Początkujący (280 p.)
edycja 13 września 2016 przez prownnie

Witam, wstępnie napisałem sobie jak miałby wyglądać skok w SFMLu w płaszczyźnie pionowej.

Aby było podobnie jak na Ziemi przyjąłem sobie g=10m/s^2

Przyjąłem, że 100 pixeli będzie odpowiadało 2 metrom, więc 1 metr to 50 px. Program wykonuje się 60 razy na sekundę.

Więc g w grze = 10m/s^2 * 50 / 60*60

Chcę, aby postać skakała na te 100 pixeli do góry, więc z zasady zachowania energii liczę prędkość początkową:
v=sqrt(2*g*h)

Obliczone wartości deklaruje w klasie (vp - prędkość początkowa i g deklaruje w klasie).

 

		if (player_r.getPosition().y<=200) {
			t += time.restart().asSeconds();
			v = vp - g*t;
			player_r.move(0, v);
			act_frame = 0;
			window.draw(player_r);
		}
		else {
			player_r.setPosition(player_r.getPosition().x, 200);
			v = vp;
			std::cout << t<<std::endl;
			t = 0;
		}

 

I nie rozumiem paru rzeczy, w zasadzie vp to tak na prawdę droga, która wykonuje się co klatkę, a nie prędkość, a ja obliczyłem prędkość więc jednostka tego wygląda tak [pixel/czas_klatki/czas_klatki]. W zasadzie jednostkę dobrałem tak, że nie potrzeba mnożyć przez czas_klatki, bo to po prostu 1. Ale czemu wszystko zaczyna w przybliżeniu trzymać się kupy jak tylko czynnik g*t pomnożę przez 60? To przypadek? Czy w ogóle dobrze kombinuję?

EDIT: Olśniło mnie jak byłem w toalecie! Chyba dlatego, że pobieram czas  sekundach. Ale nadal jeśli ktoś ma ochotę odpowiedzieć na pytanie, czy tak programiści piszą fizykę i czy o z tym wyglądem jednostki [pixel/czas_klatki/czas_klatki] jest ok to proszę. :D

 

W razie czego wrzucam klasę:

	sf::Texture player;
	sf::Sprite player_r;
	sf::Clock frameTime;
	sf::Clock time;
	float t=0;
	float g = -1.4, vp = -16.7, v = vp;
	int act_frame = 0;
	int a;

 

komentarz 13 września 2016 przez Avernis Nałogowiec (27,400 p.)

Pytałeś jak piszą. A więc ja piszę tak:

		if (MAK.oneKeyPressed(window, GLFW_KEY_SPACE) && !fall)
		{
			fall = true;
		}
		else if (camera_position.y < normalYCameraJump && fall == true)
		{
			camera_position.y += (float)getDeltaTime() * 3;
		}
		else if(camera_position.y > normalYCameraPosition)
		{
			camera_position.y -= 0.5 * getDeltaTime() * 8;

			fall = false;   
		}

 

komentarz 13 września 2016 przez prownnie Początkujący (280 p.)
Czy mógłbym prosić o jakiś mały komentarz, co do kodu, bo nie bardzo rozumiem. :P
komentarz 13 września 2016 przez Avernis Nałogowiec (27,400 p.)
1 if sprawdza czy został raz wciśnięty przycisk i czy zmienna bool jest false.

Jeśli tak to zamienia ów zmienną na true

2 if sprawdza czy pozycja kamery na osi y jest mniejsza niż maksymalna wysokość skoku i czy fall jest tówne true

Jeśli tak to dodaje do pozycji y kamery 3 razy coś w rodzaju pętli stałokrokowej.

3 if  sprawdza czy pozycja kamery y jest większa od minimalnej wysokości kamery

Jeśli tak to odejmuje od pozycji y to co widzisz i ustawia fall na false.

 

To wszystko daje efekt skoku, oczywiście w 3d
komentarz 14 września 2016 przez niezalogowany
Mnie też raz olśniło jak siedziałem na kiblu, witaj w klubie xd
komentarz 19 września 2016 przez prownnie Początkujący (280 p.)
lol i też masz na imię Filip xD
komentarz 19 września 2016 przez niezalogowany
Czyli że to widać? Kurde... No pewnie, że Filip! ;)

2 odpowiedzi

+2 głosów
odpowiedź 14 września 2016 przez Benek Szeryf (90,870 p.)
edycja 14 września 2016 przez Benek

Czy w ogóle dobrze kombinuję?

Pogubiłem się w Twoich rozważaniach. Chyba nie tylko ja. Rozłóżmy to zagadnienia na czynniki pierwsze, jeśli chodzi o samą fizykę. Po pierwsze mamy następujące dane:

1 m = 50 px
FPS = 60
g = 10 m/s^2
h = 2 m

Pierwsze co trzeba by policzyć to czas takiego skoku. Skok (dokładnie ruch wzdłuż pola grawitacyjnego) jest zjawiskiem symetrycznym (pomijając opór powietrza), tzn. najpierw obiekt ma jakąś prędkość początkową Vp (i to tylko od tej prędkości zależy jak obiekt wysoko się wzniesie), w najwyższym punkcie V = 0, po czym obiekt opada osiągając przy powierzchni Ziemi ponownie Vp. Skoro jest to symetria, to ograniczmy się tylko do sytuacji od wyskoku z V = Vp do osiągnięcia punktu w którym V = 0.

Policzmy więc czas trwania takiego zjawiska. Skorzystajmy ze wzoru na drogę w ruchu jednostajnie przyspieszonym (opóźnionym) oraz z danych wejściowych, przy czym załóżmy s = h:

s = (g * t^2) / 2 => t = sqrt(2 * s / g)
-----------------------------------------
t = sqrt(2 * 2 [m] / 10 [m/s^2]) = 0.63 s

Czyli wznoszenie (jak i opadanie) takiego obiektu powinno trwać 0.63 s, całkowity czas trwania skoku to 1.26 s. Ale wróćmy tylko do połowy skoku, w końcu zjawisko jest symetryczne. Nasz FPS wynosi 60, tak więc aby wyświetlić to zjawisko na ekranie potrzebujemy N klatek:

N = t * FPS
------------------
N = 0.63 * 60 = 38

Jedyne co jeszcze musimy znaleźć, to wysokości na jakich jest obiekt w poszczególnych klatkach. Policzmy prędkość początkową, jaką powinien posiadać obiekt, by wznieść się na te 2 metry. To jest już proste, wystarczy zauważyć że ruch do góry, to to samo co spadek obiektu z przyspieszeniem g w czasie t (tak, tak, symetria). Tak więc obiektowi trzeba nadać prędkość:

Vp = g * t
------------------------------------------------
Vp = 10 [m/s^2] * 0.63 [s] = 6.3 m/s ~ 22.7 km/h

by ten osiągnął żądaną wysokość. Czyli wyrzucamy obiekt nadając mu prędkość Vp, a ponieważ obiekt stara się uciec z pola grawitacyjnego Ziemi, to musimy zastosować wzór na drogę w ruchu jednostajnie opóźnionym:

s = Vp * t - (g * t^2) / 2

OK, ale tutaj czas mamy w sekundach. Wiemy, że powinniśmy wyświetlić N klatek. Musimy znaleźć zależność między sekundami a klatkami, a więc odwrotność FPS:

dt = 1 / FPS

Natomiast drogę chcemy otrzymać w pikselach, nie zaś w metrach, musimy ją przeskalować, by ostatecznie otrzymać:

s[px] = 50*(Vp*(i/FPS) - (g*(i/FPS)^2)/2)

Policzyłem to sobie w Pythonie, by sprawdzić czy się nie pomyliłem w rachunkach, oto output:

Frame:  1 -> Y:  0.000 pix = 0.000 m
Frame:  2 -> Y:  5.191 pix = 0.104 m
Frame:  3 -> Y: 10.242 pix = 0.205 m
Frame:  4 -> Y: 15.154 pix = 0.303 m
Frame:  5 -> Y: 19.926 pix = 0.399 m
Frame:  6 -> Y: 24.559 pix = 0.491 m
Frame:  7 -> Y: 29.053 pix = 0.581 m
Frame:  8 -> Y: 33.407 pix = 0.668 m
Frame:  9 -> Y: 37.622 pix = 0.752 m
Frame: 10 -> Y: 41.697 pix = 0.834 m
Frame: 11 -> Y: 45.633 pix = 0.913 m
Frame: 12 -> Y: 49.429 pix = 0.989 m
Frame: 13 -> Y: 53.086 pix = 1.062 m
Frame: 14 -> Y: 56.603 pix = 1.132 m
Frame: 15 -> Y: 59.981 pix = 1.200 m
Frame: 16 -> Y: 63.220 pix = 1.264 m
Frame: 17 -> Y: 66.319 pix = 1.326 m
Frame: 18 -> Y: 69.279 pix = 1.386 m
Frame: 19 -> Y: 72.099 pix = 1.442 m
Frame: 20 -> Y: 74.780 pix = 1.496 m
Frame: 21 -> Y: 77.321 pix = 1.546 m
Frame: 22 -> Y: 79.723 pix = 1.594 m
Frame: 23 -> Y: 81.985 pix = 1.640 m
Frame: 24 -> Y: 84.108 pix = 1.682 m
Frame: 25 -> Y: 86.092 pix = 1.722 m
Frame: 26 -> Y: 87.936 pix = 1.759 m
Frame: 27 -> Y: 89.641 pix = 1.793 m
Frame: 28 -> Y: 91.206 pix = 1.824 m
Frame: 29 -> Y: 92.632 pix = 1.853 m
Frame: 30 -> Y: 93.918 pix = 1.878 m
Frame: 31 -> Y: 95.065 pix = 1.901 m
Frame: 32 -> Y: 96.072 pix = 1.921 m
Frame: 33 -> Y: 96.940 pix = 1.939 m
Frame: 34 -> Y: 97.669 pix = 1.953 m
Frame: 35 -> Y: 98.258 pix = 1.965 m
Frame: 36 -> Y: 98.707 pix = 1.974 m
Frame: 37 -> Y: 99.018 pix = 1.980 m
Frame: 38 -> Y: 99.188 pix = 1.984 m

Zauważmy, że jest to tylko sam ruch ku górze. Opadanie będzie symetryczne, jeśli chodzi o wartości wysokości.

komentarz 14 września 2016 przez draghan VIP (106,230 p.)

Pogubiłem się w Twoich rozważaniach. Chyba nie tylko ja.

Jup. :)

0 głosów
odpowiedź 13 września 2016 przez criss Mędrzec (172,590 p.)
Chyyba jest spoko ale napisałbym to tak:
    t = time.restart().asSeconds();
    v -= g*t;

Żeby nie musieć zerować t w odpowiednim momencie. A vp przypisywać do v tylko raz (na początku skoku).

Z tym, że w sfml (i w ogóle w grafice komputerowej) oś y jest odwrócona, więc player_r.move(0, v); z v > 0 sprawi, że poruszy się w dół. Także powinno być player_r.move(0, -v); i będzie ok.

I nie rozumiem paru rzeczy, w zasadzie vp to tak na prawdę droga, która wykonuje się co klatkę, a nie prędkość, a ja obliczyłem prędkość więc jednostka tego wygląda tak [pixel/czas_klatki/czas_klatki].

Tutaj kompletnie nie rozumiem o co ci chodzi. Jak to droga? Btw pixel/czas_klatki/czas_klatki to po prostu pixel

komentarz 13 września 2016 przez prownnie Początkujący (280 p.)

Dzięki za odpowiedz. :D

 

Btw pixel/czas_klatki/czas_klatki to po prostu pixel

Ale przecież pixel/czas_klatki/czas_klatki to pixel/czas_klatki^2. Tak samo jak a=v/t.

To znaczy dręczy mnie to, że to co podajemy w komendzie move(x,y), to w zasadzie nie prędkość, tylko droga, jaką pokona ciało po 1 klatce. A to co ja obliczyłem na papierze, to prędkość, która ma jednostkę pixel/klatkę. Prędkość x`ową i y`ową uzyskujemy dopiero po 1 klatce, więc jest to wtedy x/klatkę. A jak w miejsce x`a wstawiam jeszcze prędkość, to mam x/klatkę/klatkę, więc trzeba pomnożyć przez klatkę, żeby się zgadzało. (chyba)

komentarz 13 września 2016 przez DragonCoder Nałogowiec (36,500 p.)
Pixel/czas/czas zapisz to jako ulamek i skroc i wyjdzie pixel/1 bo czas sie zredukuje, a pixel/1 to po prostu pixel
komentarz 13 września 2016 przez DragonCoder Nałogowiec (36,500 p.)
A wiec, zeby obliczyc droge potrzebujesz 2 czynnikow w ruchu jednostajnym i 3 w przyspieszonym. Czyli czas i predkosc lub czas i przyspieszenie, predkosc poczatkowa i koncowa, na koncu masz droge, bo jej nie znasz na poczatku. Popatrz na wzor i s bedzie nie wiadomo i oblicz to sobie znajac predkosc i czas
komentarz 13 września 2016 przez draghan VIP (106,230 p.)
krrr123 - wynikową jednostką jest px / (t^2), gdzie px to piksel, zaś t to czas.

http://vpx.pl/i/2016/09/13/ulamek.png
komentarz 13 września 2016 przez DragonCoder Nałogowiec (36,500 p.)
To w takim razie pixel/czas*czad da nam wzor u gory a nie pixel/czas/czas
komentarz 13 września 2016 przez criss Mędrzec (172,590 p.)
@ draghan - tak masz racje. Pomyliłem się. Ale w sumie to nie ma znaczenia. Co do samego pytania (żeby jednak zejść z tematu jednostek XD), to nie mam pojęcia o co właściwie chodzi.

Podobne pytania

0 głosów
0 odpowiedzi 386 wizyt
pytanie zadane 17 maja 2020 w OpenGL, Unity przez Stami Gaduła (3,790 p.)
+10 głosów
2 odpowiedzi 1,640 wizyt
0 głosów
0 odpowiedzi 671 wizyt
pytanie zadane 27 grudnia 2021 w C# przez The_xeenq Nowicjusz (120 p.)

92,556 zapytań

141,404 odpowiedzi

319,561 komentarzy

61,942 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...