Duszki jako aktorzy

12

Nie mam doświadczenia w kwestiach związanych z tworzeniem gier, ale jako programista. W języku Scala możesz mieć skalowalne wielozadaniowość z aktorami, bardzo stabilną, jak słyszę. Możesz nawet uruchomić setki tysięcy z nich bez problemu.

Pomyślałem więc, że możesz użyć ich jako klasy podstawowej dla duszków 2D, aby wyrwać się z pętli gry, która wymaga przejścia przez wszystkie duszki i przeniesienia ich. Zasadniczo poruszaliby się sami, sterowani zdarzeniami.

Czy miałoby to sens w przypadku gry? Mając tak wielozadaniowość? W końcu będzie działał na JVM, choć w dzisiejszych czasach nie powinno to stanowić większego problemu.

EDYTOWAĆ:

Po dłuższej pogawędce zauważyłem, że ten pomysł ma tylko jedną prawdziwą zaletę: obsługa wielu rdzeni. Prosta pętla gry będzie działać tylko na jednym rdzeniu i będzie działać przez wszystko sekwencyjnie.

Ponieważ współczesne komputery, nawet w domu, mają obecnie wbudowane dwa lub więcej rdzeni, myślę, że dobrym pomysłem jest umożliwienie programistom gier efektywnego korzystania z innych rdzeni. W końcu myślę, że zwykle gracz będzie miał tylko grę uruchomioną na swoim ośmiordzeniowym komputerze, więc czemu nie.

Inną zaletą, którą widzę, jest to, że w Scali możesz mieć RemoteActors, który można traktować w ten sam sposób, ale uruchomić na innym komputerze. Może to może uprościć również gry sieciowe.

Zamierzam to jak najszybciej wbudować w mój silnik Scala 2D.

Lanbo
źródło
Byłbym bardzo zainteresowany wiedząc, jak to się potoczy. Patrzyłem na Scalę kilka razy, ale nigdy się przed nią nie zagłębiałem.
Davy8
Wielu twierdzi, że w przypadku jawnego wsparcia wielordzeniowego lepiej jest używać wątków niż procesów (i procesów modelujących podmioty Scala). Wynika to z faktu, że można wykorzystać pamięć współdzieloną w wątkach. Oczywiście jest to podatne na błędy w sposób, w jaki nie jest to model aktora.
Kylotan,
Aktorzy Scala są multipleksowani na szczycie puli wątków, dzięki czemu mogą być bardziej lekkie niż wątki. Oznacza to, że mogą manipulować pamięcią współużytkowaną w celu komunikacji, pod warunkiem, że jest ona poprawnie zsynchronizowana. Jeśli używasz aktorów zdalnych, mogą oni być na różnych procesach, a jedynym sposobem komunikacji jest wysyłanie wiadomości.
axel22

Odpowiedzi:

7

Nie próbowałem, ale jestem programistą Scala i powiedziałbym, że to nie jest najlepsze podejście. Duszki muszą być animowane synchronicznie. Aktorzy nie mają gwarancji, że zostaną one wykonane sprawiedliwie - niektóre duszki mogą być szybsze od innych, co nie jest tym, czego chcesz. Możesz użyć bariery do ich synchronizacji, ale potem - po co używać aktorów. Jeśli polegasz tylko na przekazywaniu wiadomości, wdrożenie tego rodzaju synchronizacji (wdrożenie bariery dla ponad 1000 aktorów) jest przesadą.

Kolejnym problemem jest - do czego używałbyś przekazywania wiadomości? Czy potrzebujesz swoich duszków do komunikacji? Możesz wysłać wiadomość od głównego aktora, informującą każdego duszka, aby przejść do następnej klatki, ale pod względem wydajności jest to o wiele więcej niż bezpośrednie wywoływanie metod i iterowanie przez zestaw duszek.

Wydaje mi się, że to, czego tu potrzebujesz, to bardzo lekka wielozadaniowość i żadna wiadomość nie jest przekazywana. Wdrożenie własnej implementacji przypominającej aktora, która zapewnia uczciwość, jest prawdopodobnie najlepszą drogą, jeśli chcesz to zapewnić, ale to za dużo pracy dla zbyt małego zysku. Kolejną rzeczą, na którą należy zwrócić uwagę, jest funkcjonalne programowanie reaktywne i scala.reactuważam, że lepiej pasuje do tego przypadku użycia.

W Scali zaimplementowałem izometryczny silnik gry 2d. Użyłem tylko 1 aktora globalnego, aby zaktualizować widoczne duszki, które były animowane.

Możesz zaimplementować logikę gry za pomocą aktorów - na przykład, aby rozpowszechniać obliczenia na różnych częściach mapy gry wśród różnych aktorów, aby równolegle aktualizowali stan gry - i uzyskać wzrost wydajności. Nie użyłbym jednego aktora na obiekt gry, a raczej aktora na region. Jeśli pójdziesz zbyt drobnoziarnisty, wydajność spadnie.

Mimo to, gdybym był tobą, spróbowałbym tego, aby zobaczyć, co się stanie.

axel22
źródło
1

Pomyślałem więc, że możesz użyć ich jako klasy podstawowej dla duszków 2D, aby wyrwać się z pętli gry, która wymaga przejścia przez wszystkie duszki i przeniesienia ich. Zasadniczo poruszaliby się sami, sterowani zdarzeniami.

Jakie wydarzenie je poruszy?

Czy byłoby to wydarzenie emitowane raz na klatkę?

A jeśli tak, to jak to zmieniło system w praktyczny sposób?

Kiedy początkowo badałem orientację obiektową w kontekście C ++, dowiedziałem się, że niektórzy lubili myśleć o stwierdzeniu takim jak xyz.doThis(x)„wyślij wiadomość doT do tej wiadomości xyz (z ładunkiem x) i czekaj na natychmiastową odpowiedź”. Patrząc na tym poziomie, nie ma istotnej różnicy między systemem opartym na zdarzeniu lub komunikacie a normalnym systemem proceduralnym.

Kylotan
źródło
Aktorzy to rozwiązanie wielowątkowe. Komunikacja nie jest synchroniczna. Aktorzy Scala (koncepcja Erlanga) umożliwiają łatwe programowanie wielordzeniowe.
Ellis,
Masz tutaj rację, ale różnica polega na tym, że duszek oparty na Aktorze nie blokuje pętli gry podczas wykonywania akcji, podczas gdy podejście oparte na metodzie czeka na zakończenie xyz.doThis(x). Myślę, że może to nawet pomóc przyspieszyć logikę gry, szczególnie w systemach wielordzeniowych.
Lanbo
To prawda, że ​​łatwiej jest rozdzielić obsługę encji na wiele rdzeni. Ale kosztem tego jest to, że nie można łatwo polecić jednego aktora drugiemu bez dodatkowych wiadomości lub dodatkowych danych wysłanych w wiadomościach. Więc szybko zdajesz sobie sprawę, że naiwne podejście tutaj nie pomaga - czy możesz sformułować sposób aktualizacji oparty na aktorach?
Kylotan
Obecnie eksperymentuję z pewnego rodzaju aktualizacją rozproszoną: moi aktorzy są jak węzły w strukturze drzewa, a aktualizacja katalogu głównego aktualizuje dzieci, poprzez dystrybucję wiadomości. Prawdziwą zaletą będzie także tworzenie sieci: w Scali aktor i RemoteActor (aktor w innym systemie) mogą być adresowane w ten sam sposób, za pomocą tych samych komunikatów.
Lanbo,
Tak, ale problemem nie jest wyzwolenie aktualizacji jako takiej, ale zapewnienie odbiorcy wiadomości wszystkich informacji potrzebnych do działania.
Kylotan
0

To fajne podejście do myślenia o aktualizowaniu obiektów w grze. Nie znam Scali, ale mówię, daj jej szansę i zobacz, jak to się potoczy, a jeszcze lepiej opublikuj swoje wyniki!

Główne pytania, które przychodzą mi do głowy, to: Jak zarządzasz częstotliwością aktualizowania niektórych obiektów gry w porównaniu do innych? Czy będziesz musiał się martwić, że aktorzy spriterzy podejmą zbyt wiele cykli, tak że system renderujący nie będzie miał czasu rysować ramki co 1/60 | 30 | 24 sekundy?

Inną rzeczą do rozważenia jest to, jak wpłynie to na rozdzielczość interakcji gracza z AI, które zależą od kolejności sekwencji bardzo szybkich zdarzeń. W zależności od rodzaju gry może to nie mieć większego znaczenia.

michael.bartnett
źródło
Wspaniałą rzeczą w Scala Actors jest to, że kierują się wiadomościami. Każdy z nich ma własną kolejkę komunikatów / zdarzeń. Nie jestem pewien, czy „Draw” powinien być komunikatem, czy metodą wywoływania. Myślę, że będzie to ta ostatnia, aby Sprite można było narysować w dowolnym momencie, bez względu na stan ich kolejki zdarzeń. I mogą wysyłać sobie nawzajem wiadomości, aby mieć pewność, że wszystko zostanie wykonane w określonej kolejności.
Lanbo
Uważaj tam, nie sądzę, aby posiadanie każdego duszka posiadało metodę losowania lub zdarzenie byłoby przydatne, z wyjątkiem może jako flagi do zmiany widoczności. W fazie renderowania pętli gry kolejność renderowania duszków na ekranie ma duży wpływ na wynik. Jeśli masz jedną duszkę, która znajduje się przed drugą (wymiar jest skierowany w stronę monitora), chcesz, aby ta druga była rysowana jako druga. Widzę, że aktorzy Scali są przydatni w części aktualizacyjnej / logicznej pętli gry.
michael.bartnett
Zwykle masz tam tylko metodę rysowania, więc wdrażając ją w ten sposób, nie powinno być dużej różnicy w normalnym sposobie radzenia sobie ze sprajtami.
Lanbo
Ach, dobrze, źle zrozumiałem, co opisałeś. W jakiś sposób wyobrażałem sobie, że duszki renderują się, ilekroć im się podoba. Poinformuj nas jak to się okazuje!
michael.bartnett
0

Cóż, nie jestem też zbytnio programistą, ale nie widzę żadnego problemu w twojej propozycji. Nawet nie myślałem o takim sposobie rozwijania aktorów.

Może to być nie lada wyzwanie, ponieważ ocena skutków musi być bardzo dokładna, aby uniknąć nieoczekiwanego zachowania, ale poza tym widzę, że jest to całkiem dobra propozycja

Carlos Valenzuela
źródło
0

Jeśli przez duszka masz na myśli byt gry, to na pewno.

Podmioty z gry nigdy nie powinny się rysować. Powinny zaktualizować uchwyt graficzny, który opisuje, gdzie i jak należy je narysować. System renderowania lub wykres sceny lub cokolwiek robi rzeczywisty rysunek. Jest jedna karta graficzna, ponadto karta graficzna musi być synchronizowana co 16 ms. Taka konfiguracja po prostu nie działa dobrze w przypadku rozproszonego przetwarzania asynchronicznego.

System renderowania powinien być jednym aktorem (lub być może parą, jeśli jesteś podstępny). Gdy podmioty gry aktualizują uchwyt grafiki, wysyła wiadomości do systemu renderowania. System renderowania może podejmować wszelkiego rodzaju decyzje i / lub optymalizować, np. Renderowanie partii, okluzja, wygładzanie jittera fizyki itp.

Nie jestem programistą Scala, ale sporo zrobiłem z Erlangiem. Więc jeśli część mojej terminologii Scala jest niepoprawna, proszę wybacz mi.

deft_code
źródło