Co to jest „kod logiki gry?”


50

Używam C # / XNA i kilkakrotnie powiedziano mi, aby nie mieszać kodu aktualizacji z rysowanym kodem - i jestem pewien, że nie! Ale czy ktoś mógłby opisać, czym dokładnie jest „kod logiczny”?

Jak widać tutaj: http://blogs.msdn.com/b/shawnhar/archive/2007/07/25/understanding-gametime.aspx

[...] upewnij się, że umieściłeś całą logikę gry w metodzie aktualizacji (nie w Draw!), a wszystko będzie działało z niezłą stałą prędkością.

Pytam o to, ponieważ szybkość mojej gry zmienia się w stosunku do FPS. Wolne FPS to wolno poruszające się obiekty i odwrotnie. I tak, dołączam oczekiwany position += speed * (float)gt.ElapsedGameTime.TotalSeconds;kod.

To jest prawdopodobnie duże pytanie dla początkujących, ale po prostu chcę mieć absolutną jasność co do definicji tego.


Myślę, że miałeś na myśli position = speed * ...TotalSeconds. Zauważ, że to =nie jest +=. Gdyby było +=tak, jak piszesz, twoja pozycja spadłaby z ekranu niemal natychmiast.
— DrZ214,

Mam kod, który wygląda jak „pozycja + = kierunek * prędkość * ... TotalSeconds” i działa bardzo dobrze. Mogłem coś pomylić, ale pozycja = prędkość przypisywałaby to każdej aktualizacji. Twój sposób może działać, ale mój kod działa w ten sposób. (Uwaga: kierunek jest znormalizowany)
— Nieśmiały facet

Myślałem, że gt.ElapsedGameTime.TotalSecondsupłynęła liczba sekund, które upłynęły od uruchomienia programu (gry). Jeśli pomnożysz przez to prędkość, to po 5 sekundach gry prędkość będzie 5 razy większa (z wyjątkiem specjalnego przypadku, w którym prędkość jest ustawiona na 0). Nie jestem pewien, co jeszcze mogłoby to spowodować, że to nieprawda, ale jestem zaintrygowany.
— DrZ214,

1
Aha, to od ostatniej aktualizacji. gamedev.stackexchange.com/questions/67968/…
— Shyy Guy

2
Fascynujące, nigdy bym tego nie zgadł. Nigdy nie potrzebowałem takiej rzeczy w kilka sekund, ponieważ osobiście używam własnej zmiennej o nazwie, iiiże ręcznie zwiększam każdą aktualizację, ponieważ nie chcę tego w kilka sekund, chcę kroki lub ramki. Widzę jednak, że twój sposób jest prawidłowym sposobem kodowania miękkiego.
— DrZ214,

Odpowiedzi:


102

Czy to zmienia stan twojego świata gry? To kod logiczny.

Czy pokazuje stan świata gry? To renderuje kod.


Przejrzę mój kod, aby być w 100% pewnym. Dobre wyjaśnienie, dzięki.
— Nieśmiały facet,

38
Czy obsługuje dane wejściowe? Jego kod kontrolera. Oddziel kontrolę od logiki, abyś mógł używać tej samej logiki z różnymi typami kontroli. Np. FPSInputController + CharacterMotor vs. AIInputController + CharacterMotor vs NetworkInputController (np. Inni gracze w instancji wieloosobowej) + CharacterMotor. Silnik (kod logiczny) nie dba o to, w jaki sposób otrzymuje instrukcje, tylko że są one dostarczane (ten rodzaj oddzielenia pozwala na łatwe przejście z odtwarzacza do bota AI (pomyśl Left 4 Dead i bezczynności graczy) iz powrotem, między innymi).
— Draco18s,

10
Draco porusza dobrą rację. Istnieje wiele różnych podziałów, które można wprowadzić do kodu. Podział Nilsa jest tym, co uważam za archetypowy podział na logikę i rendering, ale istnieje wiele innych warstw, które zobaczysz. Prawdziwym powodem rozdzielenia ich na warstwy jest to, że każda warstwa składa się z podobnych działań, które wymagają podobnego stylu kodu o podobnych wymaganiach. Na przykład w wielu grach można uniknąć logiki gry, która zajmuje 2 lub 3 klatki, ale jeśli nie wykonasz renderowania każdej klatki, oko użytkownika szybko to zauważy.
— Cort Ammon

Ich rozróżnienie pomoże ci zarządzać wymaganiami, gdy zaczną się one stresować.
— Cort Ammon

6
I pamiętaj, że jeśli rzucisz na nią zbyt dużo MVC, może to spowolnić do pełzania, więc zawsze staraj się zachować równowagę między konserwacją a optymalizacją. Ale nie optymalizuj zbyt wcześnie, chyba że masz absolutną pewność co robisz. I pamiętaj, że zawsze możesz refaktoryzować. I ... Uh, stwórz wiele gier i ucz się na własnych błędach.
— Maurycy

24

Twoja separacja jest prawidłowa, jeśli:

  • Wielokrotne wywoływanie Draw () bez przerywanych wywołań Update () nigdy nie spowodowałoby widocznych zmian między wywołaniami.
  • Wielokrotne wywoływanie aktualizacji () bez przerywanego wywołania Draw () byłoby jak gra z wyłączonym ekranem: wszystko przebiega idealnie i konsekwentnie, po prostu nie widać.

5
Prawidłowo napisane Draw()mogą rysować różne obrazy w miarę upływu czasu. Na przykład ramki animowanych duszków mogą się zmieniać. Ponadto obiekty mogą nadal poruszać się wizualnie do przodu, jeśli kod renderujący używa wspólnej sztuczki i zwiększa velocity * time since last update / period of updatewidoczną pozycję obiektów (podczas gdy ich rzeczywista pozycja pozostaje niezmieniona).
— HolyBlackCat

2
iffczyli jeśli i tylko jeśli?
— BalinKingOfMoria

3
@HolyBlackCat: to dyskusyjne. Co jeśli chcę zatrzymać grafikę? Co jeśli ramki animacji wpływają na grę (animacje ataku odpowiadające hitboxom itp.)? Interpolacja wizualna nadal sugeruje, że „czas” (jak w delcie gry) mija, ale jeśli czas mija, a ty nie grasz, Updateco jeszcze nie jest zsynchronizowane? Brak danych wejściowych odtwarzacza, zdarzenia sieciowe nie są przetwarzane itp.? Gra powinna być wyparta z jednego zegara, ze stałymi „tyknięciami” dla logiki gry lub fizyki pochodzącej z tego zegara, a stan grafiki pochodnej również sterowany przez ten sam zegar.
— Sean Middleditch

@SeanMiddleditch Zgadzam się, prawie zawsze możesz pisać Draw()w taki sposób, aby zawsze rysował ten sam obraz, gdy wywoływany kilka razy z rzędu. Należy to zrobić, jeśli to możliwe. Ale zdarzają się przypadki, gdy nie wiesz, z jaką częstotliwością Draw()będzie się nazywać. Na przykład, jeśli chcesz mieć pełne wsparcie (rzeczywiste 120 FPS) dla nowych monitorów 120Hz i włączysz vsync. What if I want to pause graphics?Następnie podajesz 0 zamiast faktycznego czasu delta do Draw().
— HolyBlackCat

2
@HolyBlackCat: Nic, o co mi chodziło, nie wykluczałoby użycia renderowania 120 Hz. Absolutnie nie zalecałem stałej stawki; to tylko amatorskie. Powinien istnieć jeden globalny zegar gry, którego delta jest mierzona w kategoriach ramek renderujących, które zasilają wartość akumulacji dla logiki gry o stałej szybkości. Ten globalny zegar steruje grafiką, w tym interpolacją. Możesz wstrzymać grafikę, ustawiając skalę zegara na 0. Możesz mieć zegary hierarchiczne, więc np. Interfejs użytkownika nadal działa i animuje, a interpolacja znaków również zatrzymuje się bardzo, bardzo łatwo.
— Sean Middleditch

7

Chodzi tutaj o rozdzielenie rzeczy, które nie są modelem.

Logika gry to model, o którym mowa w

Są to wszystkie różne, powiązane wzorce architektury oprogramowania. Ale w każdym przypadku Model jest tym samym, jest prawdziwą logiką i rzeczywistym stanem.

Podczas tworzenia oprogramowania biznesowego nazywa się go czasem logiką biznesową i koduje niektóre zasady biznesowe. Na przykład, jeśli kodujesz coś dla banku, aby obliczyć rachunki z karty kredytowej, to funkcja powodująca, że ​​ktoś nie musi płacić odsetek, jeśli spłaci dług w ciągu mniej niż 30 dni, jest częścią logiki biznesowej, żyje w Model. Nie działa na przykład na jednej z wyświetlanych warstw. Kod do drukowania rachunku nie służy na przykład do edycji tekstu na podstawie ich działań. W tym przykładzie być może podkreślono, dlaczego warto zorganizować swój kod w ten sposób.

Podobnie jest z logiką gry.

Wyobraź sobie, że w pewnym momencie twoja gra została przeniesiona na inną konsolę. Może pomóc wyobrazić sobie coś naprawdę innego niż twój obecny cel. Np. Jeśli celujesz w coś za pomocą gamepada / kontrolera, wyobraź sobie, że gra jest przeniesiona na tablet z ekranem dotykowym. Logika gry jest częścią kodu, która nie zmienia się po przeniesieniu.

Jeśli twoja gra była czymś w rodzaju strategii wojskowej, wyobraź sobie, że jest przekształcana w najbardziej złożoną grę planszową na świecie. Logika gry to sekcje kodu, które bezpośrednio odpowiadają wierszom w zbiorze reguł. (Nie wszystkie wiersze w zbiorze reguł, nie te dotyczące ruchomych elementów, ale niektóre.).

Logika gry nigdy się nie zmienia, bez względu na formę.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.