Autor Wątek: Problem z rzutem ukośnym  (Przeczytany 1131 razy)

Offline Buyuk

  • Użytkownik
    • Mój blog ;]

# Maj 13, 2010, 21:41:30
Cześć :)
Coby niepotrzebnie nie przedłużać, przejdę do problemu.
Mianowicie usiłuję sobie napisać w allegro grę polegającą na rzucaniu do kosza,
i próbuję napisać tor lotu takiej piłki. Wyskrobałem sobie więc taką pętlę:
    float y = 0.0f, y_p = 335.0f, x = 200.0f;  // y_p - początkowe y piłki, y - chwilowe y, x - początkowe x piłki
    float kat = degtorad(45.0f); //zamienia stopnie na radiany
    float Vp = 15.0f;  //prędkość początkowa piłki
   
    for(float i = -800-x; i<800; i+=0.001)
    {
        y = 335-(i*tan(kat) - (9.81*i*i)/2*Vp*Vp*cos(kat)*cos(kat))/100;  //równanie toru lotu piłki
        putpixel(screen, i*100+4*x, y-200, makecol(255, 0, 0)); //rysowanie toru lotu
        }

Pytanie brzmi: Czy mógłby mi ktoś wytłumaczyć co robię źle i ewentualnie jak zrobić żeby tor lotu zaczynał się w początkowej pozycji piłki niezależnie od ustawionego kąta i prędkości początkowej ?
« Ostatnia zmiana: Maj 13, 2010, 23:11:26 wysłana przez Buyuk »

Offline Mr. Spam

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

Offline Xirdus

  • Redaktor

# Maj 13, 2010, 21:48:34
Nie znam się na tym, nie bardzo rozumiem ten kod, ale wydaje mi się, że to przez to, że i jest ustawione na stałe na -800. Nie wiem, co z tego wynika, ale wydaje mi się, że wpływa to na pozycję piłki na początku pętli.

Offline DrUiD

  • Użytkownik
    • HaCra Team

# Maj 14, 2010, 00:04:34
na fizyce zapewne miales kiedys cos takiego jak:

http://pl.wikipedia.org/wiki/Rzut_ukośny

tam znajdziesz paragraf: polozenie

powodzenia :-)
« Ostatnia zmiana: Maj 14, 2010, 03:12:01 wysłana przez DrUiD »

Offline Buyuk

  • Użytkownik
    • Mój blog ;]

# Maj 14, 2010, 00:32:27
Tak ... dotarłem już do tego ;)   Ale chyba nieprecyzyjnie wyraziłem o co mi chodzi.
W tej pętli według wzoru podanego w Twoim linku obliczam tor lotu.
Pytanie jakie mam to w jaki sposób w allegrowskim układzie współrzędnych (lewy górny = 0, 0, prawy dolny narożnik = 800, 600) przekształcić tę funkcję, aby początkowy punkt był stały dla każdego kąta i każdej prędkości początkowej.

Offline neonesis

  • Użytkownik

# Maj 14, 2010, 01:24:36
Hmm, swego czasu pisałem taki program w SDL, i to z przypadkiem uwzględniającym opory powietrza... Buyuk, napisz na PW jeśli chcesz source, wydaje mi sie że SDL też ma układ wsp. (0,0) w lewym górnym.

Offline DrUiD

  • Użytkownik
    • HaCra Team

# Maj 14, 2010, 03:19:46
zacznij od tego zeby uniezaleznic liczenie od pozycji poczatkowej. jak to zrobic? masz polozenie poczatkowe - to juz cos.. teraz petla zamiast modyfikowac x niech zmienia jakas powiedzmy wirtualna zmienna czas w jakims przedziale np <0.0f;20.0f>.. w samej petli liczysz polozenie x i y wg w/w wzoru.. na koniec dodajesz polozenie poczatke do wyniku, ewentualnie odwracasz y (bo masz rosnacy uklad w dol) i tyle..
mam cicha tylko nadzieje ze w finalnej wersji uzyjesz jednak czasu do symulacji

Offline Anton Chigurh

  • Użytkownik

# Maj 14, 2010, 11:32:33
Bezpośrednie operacje na czasie nie mają tu sensu, bo mogą doprowadzić do tego, ze w trajektorii będą przerwy (może być wtedy kanciasta), lub będzie ona obliczana za gęsto. Proponuję taki algorytm:

(zakładam, że dobrze rozumiesz tu koncepcyjne rozdzielenie ruchu w poziomie (jednostajny) od tego w pionie (przyspieszony) - to jest dość ważne).

1. ustalić punkt początkowy na współrzędne (0,0).
2. zwiększyć x o arbitralną wartość tak, żeby odpowiadało to przesunięciu o 1 piksel (czyli np. o 1)
3. wyznaczyć CZAS, po jakim punkt znajdzie się w danym x (rozpatrując TYLKO ruch w poziomie - jednostajny x = v0x*t) - v0x początkowa prędkość w poziomie
4. wyznaczyć y jaki osiągnie punkt po danym czasie (TYLKO ruch w pionie - przyspieszony y = v0y*t + (g*(t^2)) / 2. - v0y - początkowa prędkość w pionie
5. arbitralnie wybrany x z pkt. 2 i y z pkt. 4 to kolejny interesujący Cię punkt (zapisz do listy wyników)
6. Jeżeli osiągnąłeś końcowy x (prawdopodobnie położenie kosza) to zakończ, w przeciwnym razie wróć do 2. Najlepiej za końcowy x uznać ODLEGŁOŚć od rzucającego do kosza, a nie absolutny x kosza, bo w końcu zaczynamy "symulację" od x = 0.

Na liście masz teraz "surowe" wyniki w dziewiczej przestrzeni newtonowskiego modelu rzeczywistości - to jeszcze nie wyjdzie ładnie na ekranie.
Teraz kwestia układu współrzędnych. Jako, że początek ruchu był nie w (0, 0) a w jakimś(x0, y0), to (zrobimy to po kolei ;-)):
- po pierwsze, dla każdego x i y z uzyskanej wcześniej listy zastosuj zwykłe przesunięcie takie, że:
Kod: (cpp) [Zaznacz]
lista[i].x = lista[i].x - x0 oraz
lista[i].y = lista[i].y - y0
to jeszcze nie jest okej, bo łuk zamiast w górę wygnie się w dół (i to niechybnie poza ekranem ;-)).  Żeby temu zapobiec wystarczy mały zabieg. Wystarczy zauważyć, że y rosną w dół, a my liczyliśmy to tak, jakby rosły w górę. Zgodnie z oczekiwaniem wystarczy w powyższym kroku zastąpić:
Kod: (cpp) [Zaznacz]
lista[i].y = lista[i].y - y0 operacją:
lista[i].y = y0 - lista[i].y (zwróć uwagę, że obie składowe po prostu zmieniły znaki - to odzwierciedla "odwrotność" wzrostu y).
teraz, zakładając, ze x0 i y0 znajdują się gdzieś w przestrzeni ekranowej - powinno być okej.

Dodam tylko, że punkty najlepiej łączyć odcinkami a nie po prostu rysować, ale to już zależy od upodobania.
Tytułem błyskawicznego wyjaśnienia: odejmowanie x0 i y0 odpowiada znanej i lubianej przez grafików komputerowych operacji przesunięcia, natomiast mnożenie y przez -1 (a zostawienie x w spokoju) odpowiada równie sympatycznemu skalowaniu o współczynnikach x=1 i y=-1.

I gotowe ;-)

P.S. Napisałem dużo i szybko więc zachęcam co mądrzejszych do ew. wytykania usterek :)

edit: okazuje się, że operator [] o argumencie i jest na tym forum rozumiany jako formater do kursywy. objąłem odpowiednie fragmenty blokami code.
« Ostatnia zmiana: Maj 14, 2010, 20:30:56 wysłana przez kzysiek »

Offline Buyuk

  • Użytkownik
    • Mój blog ;]

# Maj 14, 2010, 18:22:27
Dzięki ;) Przeczytam, zobaczę, pewnie pomoże ;)