Jak powinienem efektywnie rozwijać swoją grę na Androida? [Zamknięte]

11

Dołączyłem obraz schematu wykonanego w farbie. Schemat ideowy koncepcji gry

Obraz pokazuje, jak chcę rozwinąć swoją grę. Chcę gry, która działa świetnie z inteligentnym kodowaniem, która jest łatwa do aktualizacji i funkcji reklamowych w miarę upływu czasu. Moją platformą docelową jest smartfon z Androidem, a cały kod zostanie napisany w języku Java z wykorzystaniem zawyżonych zasobów XML, jeśli to ma znaczenie. Nie szukam twardego kodu, chociaż pseudo kod pomoże, wolałbym raczej sugestie i porady od profesjonalistów.

Moje pytania to:

Czy to dobry sposób na zaprogramowanie gry, czy są na to lepsze sposoby? Czy należy wprowadzić jakieś modyfikacje? Wszelkie sugestie byłyby przydatne, ponieważ nie mam doświadczenia w programowaniu gier, dlatego wolałbym porady od kogoś, kto napisał kilka gier i wie z doświadczenia, jak należy skonfigurować swój kod, aby działał wydajnie.

kdavis8
źródło

Odpowiedzi:

12

Wiele gier na Androida nie ma nawet wystarczająco dużego zasięgu, aby uzasadnić zapisanie / wczytanie lub opcje / preferencje, nie wspominając o niestandardowych postaciach itp. Po prostu dlatego, że gra się je od ręki przez 10 minut w pociągu do domu.

Nie popełnij błędu, gdy popełniłem coś o dużym zasięgu w pierwszej grze na Androida. Stwórz kilka mniejszych gier, a następnie wybierz coś większego

Specyfika Androida mądra:

Struktura:

Poleciłbym mieć prawie całą grę w jednej klasie aktywności. Android działa na zasadzie, że każda aktywność jest jak mini-aplikacja, częściowo niezależna od innych działań w aplikacji. Aplikacja jest zasadniczo zbiorem działań, z których użytkownik widzi, co kiedykolwiek jest na górze.

Kiedy zdejmiesz jeden z góry, na ogół ulega zniszczeniu i zostanie odtworzony następnym razem, gdy użytkownik rozpocznie nową aktywność (intencja startActivity). Utrudnia to utrzymanie stanów między działaniami i prowadzi do architektury pojedynczego działania

Możesz chcieć mieć aktywność typu Ekran główny z menu „Nowa gra / Załaduj grę / Opcje” i spraw, aby była to aktywność uruchamiania. Będziesz jednak musiał mieć menu w grze, które będzie zawierało większość tych samych funkcji

Własną aplikację stworzyłem „MenuActivity”, która ma funkcje, które uruchamiają nową grę, zapisują, ładują, zmieniają opcje. Następnie moja HomeActivity rozszerza to, podobnie jak moja GameActivity.

Ponieważ wszystko znajduje się w jednej klasie Activity, zaleciłbym zrobienie hierarchii klas aktywności i użycie prywatnych, chronionych i domyślnych partii zakresu. Robiąc to w ten sposób, możesz przynajmniej podzielić rzeczy na inny plik, aby przestać mieć jeden niemożliwy do zarządzania plik działania. Np. Dla mojej własnej aplikacji:

GraphicsEngine extends MenuActivity.

PhysicsEngine extends GraphicsEngine.

GameLogicActivity extends PhysicsEngine.

UIActivity extends GameLogicActivity.

Ponieważ moją aplikacją są trójwymiarowe pliki OpenGL, wiele rzeczy, które robię, nie działają między różnymi aktywnościami, więc wszystko jest w tej samej aktywności, więc może jestem skłonny do korzystania z jednej architektury działań

-

Gwintowanie

W przypadku aktywności w grze masz dwa wątki (lub 3, jeśli robisz 3D w OpenGL). Jednym wątkiem jest interfejs użytkownika / główny wątek. To jest wątek, w którym aktywność zaczyna się i działa i jest dostarczana przez Androida.

Ten wątek interfejsu użytkownika jest jedynym, w którym można aktualizować elementy interfejsu użytkownika (widoki, układy itp.). Jest to również ten, w którym będą uruchamiane wszelkie nasłuchiwania danych wejściowych użytkownika. Nie widzisz żadnej mechaniki wątku interfejsu użytkownika, po prostu działa on gdzieś w pętli w tle.

Drugi wątek, który sam tworzysz (polecam korzystanie z AsyncTask , pomimo wszystkich jego wad). Robi to wszystko, co nie robisz w interfejsie użytkownika, np. Aktualizowanie ruchu, obliczanie kolizji, obliczenia walki i tak dalej.

Ten wątek / klasę AsyncTask tworzysz jako wewnętrzną klasę swojej aktywności. W ten sposób możesz mieć pewne obiekty o szerokim zakresie aktywności ( Vector<Spaceship>), do których można uzyskać dostęp zarówno przez wątek interfejsu użytkownika, jak i wątek pętli gry.

Ponieważ logika gry toczy się w wątku pętli gry, jest to jedyny wątek, który będzie musiał faktycznie zmienić wartości zmiennych (aktualizacja prędkości czołgu, zmniejszenie HP gracza). Wątek interfejsu użytkownika po prostu odczytuje wartości, więc powinny wystąpić minimalne problemy z współbieżnością.

Trudnym zadaniem jest nakłonienie wątku interfejsu użytkownika do wykonania aktualizacji na żądanie wątku pętli gry. Można to zrobić na kilka sposobów. Jeśli czytasz dokumentację AsyncTask, ma ona metodę opublikujProgress () / onProgressUpdate (). To właściwie dodaje rzeczy do kolejki wątków interfejsu użytkownika, aby wykonać następną pętlę.

Program obsługi robi dokładnie to samo, jeśli implementujesz metodę handleMessage () i ta metoda jest faktycznie wykonywana przez następną pętlę wątku interfejsu użytkownika.

Wreszcie, wszelkie dane wprowadzone przez użytkownika, znajdujące się w wątku interfejsu użytkownika, można natychmiast zaktualizować z niego elementy interfejsu użytkownika (czyli wewnątrz implementacji dowolnych detektorów onClick / onTouch). Jeśli musisz zaktualizować obiekty gry, możesz albo użyć synchronizacji, albo zaimplementować własną kolejkę aktualizacji w AsyncTask, która podobnie jak wątek interfejsu użytkownika, przechodzi przez następne uruchomienie pętli gry

Android Threading Guide .

-

Interfejs użytkownika

Jeśli chodzi o rzeczywistą strukturę interfejsu użytkownika w ramach pojedynczego działania, zalecam układ ramki jako układ podstawowy. Elementy potomne w układzie ramki działają jak kolejka. Pierwszy element jest rysowany pierwszy, drugi rysowany na pierwszym, trzeci na drugim.

W ten sposób możesz mieć wiele plików układu XML, a zarządzając dziećmi podrzędnymi układu ramki, możesz łatwo zamieniać zestawy widoków na zewnątrz i na zewnątrz.

Jeśli zawsze masz SurfaceView na dole (pierwsze dziecko w układzie ramki), możesz użyć wszystkich zwykłych widoków / widżetów Androida (przyciski, widoki tekstu, widoki przewijania) itp. U góry widoku powierzchni, co po prostu powoduje część graficzna gry.

Na przykład, jeśli coś się ładuje, możesz zatrzymać pętlę gry / po prostu sprawić, aby pominąć wszystko, dodać nieprzejrzysty ekran „ładowanie” jako ostatnie dziecko do układu ramki, a użytkownik zobaczy na ekranie komunikat „ładowanie” , zupełnie nieświadomy, że stoją za tym inne poglądy. W ten sposób nie musisz usuwać widoków, których konfiguracja zajmuje dużo czasu ani nie powoduje komplikacji za każdym razem, gdy są dodawane / usuwane.

Poleciłbym również korzystanie z partii View.setVisibility. Możesz na przykład dodać cały układ „ekwipunku” do podstawowego układu ramki, a następnie po prostu ustawić na nim widoczność (View.Visible), gdy użytkownik kliknie, aby wyświetlić swój ekwipunek, i ustawić widoczność (View.Gone), gdy zamknie go ponownie. W ten sposób nie zarządzasz nawet elementami potomnymi układu ramki, a jedynie dodajesz wszystko i sprawiasz, że rzeczy są widoczne / niewidoczne, gdy użytkownik robi różne rzeczy

Pomaga to w ponownym wątkowaniu; gdy użytkownik klika, aby otworzyć swój ekwipunek, onCLickListener jest obsługiwany w wątku interfejsu użytkownika, inwentarz jest widoczny w nim, a metoda updateInventory jest wywoływana ponownie z wątku interfejsu użytkownika, a wywoływane są tylko obiekty pobierające wszystkie obiekty gry

Oto schemat, który stworzyłem dla wcześniejszego pytania dotyczącego idei pojedynczego działania / układu ramki:

wprowadź opis zdjęcia tutaj

Łyżka Kciuk
źródło
więc Twoim zdaniem powinienem mieć układ ramki, który pomieści wszystkie elementy pętli gry, prawda? Gdybym to zrobił, w jaki sposób uzyskałbym widoki w klasie HUD, aby mieć interaktywność z SurfaceView, np. Powiedzmy wirtualny d-pad / wirtualny analog? próbowałem robić takie rzeczy wcześniej i napotkałem błędy.
kdavis8,
Ponownie napiszę moją odpowiedź, aby była nieco jaśniejsza
Spoon Thumb
Ponownie napisałem moją odpowiedź. Mam nadzieję, że to wszystko wyjaśni
Spoon Thumb
Bardzo dziękuję za podział, który naprawdę wyjaśnia rzeczy, naprawdę nie ma zbyt wielu dobrych samouczków do tworzenia gier na Androida
kdavis8
11

Wiele z tego, co widzę na twoim diagramie, jest związane z interfejsem użytkownika, i to wydaje się dość rozsądne. Tylko niewielka część twojego diagramu jest zarezerwowana na rzeczywistą logikę gry i jest bardzo niejasna.

Myślę, że za bardzo się starasz. Sugerowałbym, żebyś po prostu zaczął pisać kod. Wybierz konkretny problem i zacznij go rozwiązywać. Dowiesz się tak dużo, że zanim będziesz miał lepsze pojęcie o tym, gdzie jest twoja przestrzeń problemowa, będziesz mieć zupełnie inną (bardziej użyteczną) perspektywę.

notlesh
źródło
2
Nie mogłem się z tym bardziej zgodzić. Wybierz architekturę pasującą do gry i swoich preferencji, a następnie zacznij pisać. Po trafieniu w konkretną pułapkę wydajności optymalizuj, aż zadziała. Każdy mechanizm w twojej grze będzie miał swoją własną charakterystykę wydajności i potencjalne optymalizacje - musisz myśleć o nich indywidualnie, a nie jako całość.
Wielomian
gdzie można znaleźć przewodnik po takich wzorcach architektury gier? byłoby to dla mnie bardzo pomocne.
bot_bot