Jak prawidłowo tworzyć akcje? Java swing

projektowanie-gier
gamedev
gry

#1

Czy ktoś doświadczony z javą może mi powiedzieć jak optymalizować akcje w grach? Już tłumacze o co chodzi.
Pisząc typowego snake’a mamy metode draw, do actionlistenera dodajemy timer i np. co pół sekundy wąż sobie pełznie w zależności od ustalonej zmiennej np. NORTH. Cała mapa i wszystkie obiekty (w tym jabłko) są “przerysowywane” co pół sekundy, i co pół sekundy jest wywoływana akcja która sprawdza kierunek węża. Czy nie jest to obciążające na dłuższą metę?
Piszę prostą gierkę obiektowo. Mam MainPanel który rozszerza JPanel, co kilka milisekund jest wywoływana metoda repaint(), w metodzie paint mam narysowaną podłogę i czołg. To wszystko jest przerysowywane co kilka milisekund. Jak zrobić to poprawnie by np. podłoga była narysowana tylko raz, czołg przerysowywał się tylko po wciśnięciu strzałki a nie non stop.
Czy pisząc obiektowo powinienem każdy obiekt rozszerzyć o JPanel i w każdej klasie stworzyć metode draw osobno i rysować te obiekty jako dodatkowe panele bo już nie rozumiem.
Chcę dodać metodę shoot jednak metoda paint mi to uniemożliwia, chcę by Pocisk był narysowany i przemieszczany DOPIERO po wciśnięciu spacji a nie, że metoda paint ciągle sprawdza bulletIsVisible(), jeśli true to dopiero narysuj jeśli nie to nie rysuj.


#2

Jak już tak bardzo chcesz używać Javy do tworzenia gier, to zrezygnuj ze Swinga, bo się do tego nie nadaje (bardzo słaba wydajność). Ze swojej strony polecam LibGDX, który jest nadal prężnie rozwijany i opiera się na OpenGLu.

Swing to już archaizm w dzisiejszych czasach, używany tylko dla legacy projektów w wielkich firmach, które nie chcą inwestować w przepisanie starych aplikacji w nowej technologii.

Przykładem dwuwymiarowej gry tworzonej w LibGDX może być np moja gra (TAnima) [Libgdx] TAnima - MMO Rogue-like
lub Slay The Spire (przepisany na mono o ile dobrze pamiętam w ramach portów konsolowych).

No i warto się zastanowić czy na pewno chcesz używać Javy do pisania gier.


#3

Generalnie problemem nie jest częste rysowanie czy logika.
Gry jadą najczęściej np 60 FPSów na logikę i grafikę, co daje budżet 16 ms na klatkę w którym musi się zmieścić rysowanie i logika gry.
I dobre gry się mieszczą w takim budżecie symulując tysiące obiektów i renderując miliony trójkątów z wieloma materiałami.

Kluczowe nie jest jakieś haczenie żeby się teren nie zmieniał co klatkę, bo przesuniesz kamerę i się zmieni. Kluczowe jest posiadanie technologii która nadaje się do takich wyzwań. Technologie do rysowania prostego UI który się zmienia max raz na klika sekund się nie nadają. Dużo z nich rysuje piksel po pikselu na procesorze i wysyła gotową grafikę na kartę, albo w ogóle renderuje z pamięci, czy rysuje piksel po pikselu komunikując się z kartą, generalnei dramat - jest to bardzo niewydajne.

Wydajne technologie to np DirectX czy OpenGL, które siedzą blisko kart graficznych i przekazują im wydajne instrukcje tak żeby karta graficzna a nie procesor skupiła się na rysowaniu.
I masa różnych bibliotek i silników do gier opartych na tych technologiach.

Robisz faktycznie zwykle trochę cullingu na procesorze żeby w ogóle nie wysyłać elementów których nie ma szans zobaczyć i nie marnować zasobów na nie. Ale na takiej małej grze jak wężyk to i bez cullingu spokojnie karta graficzna się wyrobi… culling to bardziej jak już masz naprawdę dużo obiektów żeby nie rysować czegoś co jest na drugim końcu świata albo po drugiej stronie kamery. I też trzeba uważać żeby nie przyciąć za dużo. Używa dużo różnych ifów + często systemu kolizji na uproszczonych bryłach otaczających obiekty.

Co do samej logiki gry to spokojnie powinieneś się wyrobić w 16 ms z symulacją węża.
Tak żeby się przemieszczał płynnie a nie skokowo.
Sama logika kolizji pewnie wystarczy odpalać na pełnych polach czyli raz na pół sekundy.
Ale też spokojnie się wyrobi jak nie robisz tam czegoś dziwnego.
Nawet odpalanie co klatkę jest bez sensu ale procesory potrafią dużo więcej udźwignąć.
Na nowoczesnym sprzęcie trzeba się nieźle postarać żeby się nie wyrobić :slight_smile: ale oczywiście da się jak się napisze odpowiednio niewydajny kod.

I większość osób korzysta z różnych silników które maja już napisaną masę kodu tak żeby nie było trzeba pisać tego wszystkiego od zera. A nawet jak chcesz mieć więcej kontroli i własny tech to warto poszukać bibliotek które trochę uproszczą korzystanie z niskopoziomowych rozwiązań.


#4

A co do zarządzania to generalnie królują systemy komponentowe.

Robisz sobie komponent SpriteRenderer, który ma pola typu image, x, y, width, height, zOrder;
I dajesz każdemu obiektowi takie pole ze wskaźnikiem na SpriteRenderer.
I trzymasz gdzieś listę wszystkich SpriteRenderer.
W każdej klatce przechodzisz po wszystkich SpriteRenderer (w kolejności zOrder żeby kontrolować co jest nad czym)
i je synchronizujesz z kartą graficzną jeśli wymagają zmian
(w najprostszej wersji rysujesz wszystkie na nowo, w bardziej złożonej karta graficzna już wie gdzie były i tylko poprawiasz jej dane).

Btw stare systemy próbowały tylko odrysowywać to co się zmieniło. Wystarczy zaznaczyć zmieniony obiekt polem typu bool dirty. Ale to jest masakra bo musisz potem odrysować wszystko co przesunięty obiekt odkrył, a rzeczy lubią się zasłaniać nawzajem. Nowoczesne karty graficzne zupełnie się w to nie bawią tylko zasuwają i odrysowują wszystko co klatkę używając Z buffera, a nie kolejności rysowania do detekcji co zasłania co (przezroczyste obiekty dalej mogą wymagać kolejności, i można trochę zyskać na wydajności dobrze sortując obiekty tak żeby Z test wyciął szybko więcej pikseli)

JPanel to jest komponent do składania UI do aplikacji biznesowej nie do gier.
Pewnie możesz go jakoś nachaczyć ale wydajne to nie będzie…
Już lepiej mieć jeden Canvas na czymś losowym typu JPanel i niech wszystko na nim rysuje.


ale to nie będzie szybkie ani wygodne, to w ogóle nie służy do robienia gier…
ale może wężyk jakoś będzie działał…


#5

Dziękuje Ci bardzo, wszystko super wyjaśniłeś :D. Generalnie w gry nie będę szedł jakoś znacznie bo bardziej param się webówką w Javie a grę chciałem zrobić dla dodatkowej nauki i powiem szczerze, że z początku była to czarna magia. Tak też myślałem, że są lepsze sposoby i frameworki by tworzyć gry niż wykorzystywać do tego JPanel jednak nie zależy mi by robić gigantyczną grę i uczyć się frameworków na nowo których pewnie i tak nigdy nie wykorzystam. Raczej chciałbym zrobić coś prostego np. jakiś prosty RPG ale napisany całkowicie ręcznie bez pomocy większych frameworków.


#6

Akurat RPGa tekstowego możesz zrobić na formatce biznesowej.
Jakiś drobny IMG dla klimatu.

Może strategię turową hackując przyciski z obrazkami…

Może coś zręcznościowego jak zdesiugnujesz gameplay wokół lekko podrasowanych standardowych kontrolek. (typu whack a mole na kilku przyciskach)

Ale wszelkiej maści animacje, modele 3d, czy nawet ładniejsza grafika 2d z efektami to nie pójdzie…

Jakieś turówki bez animacji itp… albo mega proste rysowanie.

Te API z biznesowych aplikacji do rysowania zupełnie nie są do gier, są do robienia mega prostych customowych wizualizacji typu może jakiś wykres… ale nawet to bez biblioteki to mordęga.

Możesz próbować trochę sobie ułatwić kładąc jakieś warstwy żeby mieć mega prymitywny Z bufor hack i nie musieć ręcznie odrysowywać wszystkiego co chwila. Ale nie wiem nawet czy tam jest sensowne wsparcie dla przezroczystości… żeby poukładać jedną nad drugą.