Jak mogę łatwo wdrożyć swinging w grze platformowej?

9

Rozwijam grę, w której gracz może używać lin do huśtania się (tak jak to zrobił Spiderman lub Bionic Commando ) i mam problem z implementacją tego zachowania. Czy ktoś może mi pomóc, jak to zrobić, mam na myśli wzory fizyki itp. Do tej pory wpadłem na 3 pomysły. Jeden używa wiosny, ale zajmuje dużo czasu, a czasem jest nerwowy. Pozostali dwaj próbują obliczyć następny krok (jeden poprzez obliczenie energii potencjalnej i jeden przez obliczenie momentu obrotowego) i oba z nich prawie się zawieszają, gdy aktor próbuje się kołysać.

Oto kod, który napisałem, aby obliczyć moment obrotowy:

float dx = Runner->getPosition().x - ancher.x; 
float dy = Runner->getPosition().y - ancher.y;
float t0 = atan2(dy,dx); //my current angle
float k = ((dy) *vx - (dx) * vy) / (dx * dx+dy * dy); //previus angular velocity
k -= gravity * cos(t0) *dt; // new angular velocity (gravity is positive)
t0 += k * dt - acc * cos(t0) *dt * dt / 2; // rotate the rope
float dx1 = r0 * cos(t0); // new position (r0 is rope length)
float dy1 = r0 * sin(t0);
vx = (dx1 - dx) / dt; //calculate velocity
vy = (dy1 - dy) / dt;
Ali1S232
źródło
Istotne (przy robieniu liny): Wykrywanie kolizji
doppelgreener,
@JonathanHobbs odpowiedzią na to pytanie jest dokładnie to, jak próbuję wdrożyć moją linę z jednym wyjątkiem, ponieważ w moim przypadku kolizja jest niepożądana, dlatego ustawiam każdą część liny jako czujnik, aby mogły się swobodnie poruszać, nie blokując się wzajemnie.
Ali1S232,
Co powiesz na proste wahadło na linę + kilka animacji, które pojawiają się w postaci szarpaniny? Nie wierzę, że stare gry, takie jak Bionic Commando, miały coś innego niż wahadło.
user712092,
@ użytkownik, że pomysł na wahadło powinien działać dobrze. ale w moim przypadku z powodu szybkiego ruchu gracza lub złej implementacji nie przyniosło to dobrych rezultatów.
Ali1S232,
@Gajet spróbuj zrobić rysunek do debugowania, dopóki nie zrobisz tego poprawnie? Ta linia wahadła może być wykonana jako wystarczająco cienkie pudełko w Box2D, aby uzyskać zderzenia (a może wykluczyć to z fizyki i poruszać ręcznie?).
user712092,

Odpowiedzi:

6

Jeśli chcesz sztywnego huśtania, więc odległość do punktu obrotu jest stała, po prostu traktuj postać jako punkt na okręgu wyśrodkowanym w punkcie obrotu. Daj mu jednowymiarową (wzdłuż koła) prędkość kątową. W każdej klatce powinno być przyspieszenie kątoweaccelerationDueToGravity * cos(angleOfPlayerOnCircle) (z 0 stopni skierowanymi w prawo).

Jeśli chcesz, aby lina była dłuższa / krótsza, możesz skorzystać z powyższego schematu i po prostu zmienić promień każdej ramy.

BlueRaja - Danny Pflughoeft
źródło
odpowiedź była moją drugą próbą, ale porusza się z większą prędkością, że powinienem edytować moje pytanie i dodać mój kod. Może zauważysz, gdzie jest problem.
Ali1S232
3

po wielu próbach poszedłem z box2d.

do tej symulacji są zasadniczo dwa podejścia lub przynajmniej znalazłem 2:

  1. jednym z nich jest użycie niektórych kształtów kół i połączenie ich za pomocą odległych połączeń.
  2. a drugi to prostokąty dla samego łańcucha, a następnie przymocuj je za pomocą połączeń obrotowych

w każdym senario musisz mieć anchera (który w moim przypadku był statycznym pudełkiem). lepiej, jeśli zmniejszysz ciężar części liny (albo użyjesz kształtów koła, albo prostokątów), na przykład, aby uzyskać bardziej realistyczną fizykę, ustawię ich gęstość na 0,1, a dla pudełka podłączonego na końcu liny zastosowałem gęstość 10.

kolejną rzeczą, którą musisz się martwić o to, jak Twój segment liny reaguje na siebie. chciałem tylko, żeby moja lina poruszała się swobodnie na scenie, więc oznaczyłem wszystkie urządzenia linowe jako czujniki. możesz potrzebować innej approch.

Następną rzeczą, o którą musisz się martwić, jest liczba iteracji, które przekazujesz do aktualizacji światowej: dla niskiego segmentu liny (może najwyżej 8) nie ma potrzeby używania wysokiej wartości iteracji, może 10/10, która sama box2d sugerowała wystarczy, ale jeśli zwiększysz liczbę segmentów, na przykład wypróbowałem 30 segmentów, przy małej liczbie iteracji lina wydaje się zwiększać swoją długość bardziej niż powinna, więc być może potrzebujesz 40/40 iteracji, aby rozwiązać te sytuacje.

po niektórych testach wydaje się, że pole 2d jest przeznaczone do scen o rozmiarach obiektów od 0,1 m do 10 m, a maksymalny rozmiar sugerowany dla dużych scen wynosi około 50 x 50 m. więc w zasadzie musisz przeskalować obiekt, aby dopasować te parametry. w moim przypadku najpierw próbowałem przekazać pozycje pikseli bezpośrednio do box2d, ale wydawało się, że istnieją pewne ograniczenia prędkości, które uniemożliwiają światowi ruch tak szybko, jak powinien, więc musiałem przeskalować scenę około 64 razy, aby uzyskać najlepsze wyniki. chociaż sam nie testowałem, w box2d są pewne ograniczenia, które uniemożliwiają korzystanie z większych scen. na przykład w b2Setting.hpliku jest zdefiniowana wartość , #define b2_maxTranslation 2.0fktórą można zmienić ustawienia box2d, ale nie wydaje się to zalecane.

Ali1S232
źródło
dlaczego jest źle z box2d, aby zarobić mi opinię?
Ali1S232,
To nie odpowiada na pytanie. Przynajmniej napisz, jak to działa za pomocą Box2D.
bummzack
@bummzack: ok dodam to do mojej odpowiedzi
Ali1S232,
Jeśli zaakceptujesz to jako odpowiedź, twoje pytanie będzie błędne. Fizyka liny podzielonej na segmenty różni się znacznie od tego, co opisałeś.
AttackingHobo
@attackingHobo: quesiton był w tym czasie poprawny, ale kiedy przekształciłem swój kod w box2d, doszedłem do wniosku, że bez większego wysiłku mogę wdrożyć fizykę podzielonej liny. i nie jest to bardzo różne, pomyśl o moim pytaniu jako o tylko jednym odcinku podzielonej liny. i prawie wszystkie moje rozwiązania były sposobami na wdrożenie liny w stylu koła bez box2d.
Ali1S232,
2

Czy zastanawiałeś się nad spowolnieniem prędkości ruchu wahadłowego w zależności od odległości liny od linii pionowej (środek)?

Randolf Richardson
źródło
dla wszystkich 3 przybliżeń długość liny jest jednym z parametrów, których użyłem do obliczenia prędkości kołysania. Ale nie mogę zagwarantować, że użyłem go poprawnie. Właśnie wykonałem kilka obliczeń fizycznych i zastosowałem ich rozwiązaną wersję do gry.
Ali1S232,
Im dalej od środka, tym dłuższe opóźnienie przed kolejnym ruchem zamachu liny. Możesz także pomnożyć wartość ABSolute opóźnienia przez około 0,28 (będziesz musiał z tym eksperymentować).
Randolf Richardson
Nie mogę zrozumieć tego, co próbujesz powiedzieć, kiedy obliczam następny krok, mam pewną stałą wartość delta_time i używam wszystkich parametrów, które mam (takich jak prędkość poprzednia, pozycja poprzednia, długość liny itp.) Do obliczenia nową prędkość, a następnie dodaj tę prędkość pomnożoną przez delta_time do ostatniej pozycji, aby wygenerować nową pozycję. jeśli masz na myśli cokolwiek innego, podaj pełne dane w swojej odpowiedzi.
Ali1S232
1

Gdy gracz znajdzie się dalej niż długość liny, zostanie natychmiast odepchnięty z siłą równą odległości, którą przeszedł. To powinno działać bez poczucia sprężystości i powinno być intuicyjne dla gracza. Być może będziesz musiał dostosować swoją fizykę, aby uzyskać najlepsze wyniki w grze.

Kiedy lina jest przymocowana. Zapisz maxLengthwartość.

Przy każdej aktualizacji sprawdź distancemiędzy playeriattachPoint

Jeśli wartość distancejest mniejsza niż maxLengthnormalnie, brak efektów ze strony liny.

Jeśli odległość jest większa niż maxLength, znajdź normalod attachPointdo gracza. Uzyskaj różnicę między distancei maxLength. Dodaj do playerVelocity, normalpomnożonej przez różnicę.

Pseudo kod:

dx = (attachPoint.x - player.x)
dy = (attachPoint.y - player.y)

distance = sqrt(dx*dx+dy*dy);

if (distance > maxDistance)
{
    float dx1 = dx / distance * maxDistance;
    float dy1 = dy / distance * maxDistance;
    v.x += (dx1 - dx) / dt;
    v.y += (dy1 - dy) / dt;
}

playerVel += v * dt;
AttackingHobo
źródło
więc czy kod, który zredagowałem w twojej odpowiedzi (przepraszam za to, ale nie znalazłem lepszego miejsca do dodania go), ten, który sugerujesz?
Ali1S232,
Zatwierdziłem edycję i tak, myślę, że tak powinno być. Chociaż wcześniej używałem fizyki lin i użyłem o wiele bardziej skomplikowanego sposobu, aby zrobić to samo, z tego powodu nie jestem całkowicie pewien, czy ten kod będzie działał poprawnie, ale myślę, że powinien, a nawet jeśli nie, otrzyma 95 % drogi tam.
AttackingHobo
po kilku próbach chyba spróbuję box2d dla tego problemu i przy okazji, musisz zmienić ten kod, aby mieć dx = player.x - attachpoint.xi dy = player.y - attachpoint.y.
Ali1S232
1

Jeśli spojrzysz na http://www.cocos2d-iphone.org/archives/1112 istnieje implementacja liny ze sztywnym korpusem przymocowanym do końca liny. Wykorzystuje Box2D do silnika fizyki. Jeśli spojrzysz na kod źródłowy, jestem pewien, że możesz go zaimplementować w dowolnym języku, który ci się podoba.

Ponadto powyższy link do pytania na temat liny jest mój, a powyższa wersja demo (link podany powyżej) naprawdę pomogła.

Joey Green
źródło