Autor Wątek: [Android] Duże tło w grze 2D i duże spowolnienie  (Przeczytany 1656 razy)

Offline Xaon

  • Użytkownik

# Sierpień 29, 2012, 17:51:22
Witam.

Piszę grę 2D, która celuje w ekrany o rozdzielczości 1280x800, więc i dość mocne urządzenia. Mimo to co chwila udaje mi się zajechać urządzenie, tym razem tłem.
Łopatologia stosowana podpowiada, by wrzucić statyczne tło o docelowej rozdzielczości (1280x800). Do takiego zachowania zachęca również framework z książki "Beginning Android Games" z którego korzystam, gdyż nie posiada on możliwości skalowania pixmap.
Jedyny problem jest taki, że gra szybko zaczyna ciąć. W związku z tym mam kilka pytań.
Czy to normalne, że odrysowanie 30 razy na sekundę tak dużej piksmapy jest kłopotliwe nawet dla dość mocnych tabletów? Doszukiwać się znacznego marnotrawienia zasobów po drodze? Powinienem używać mniejszego obrazka i rysować go ze skalowaniem? Będzie to ode mnie wymagać prowadzenia zmian do frameworka.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Cocomide

  • Użytkownik

# Sierpień 29, 2012, 18:21:56
W 99% to nie jest wina tego o czym myślisz.
Sprawdź jak ładujesz bitmape tła, jeżeli wczytujesz ją i wyświetlasz w każdej klatce to robisz to źle i prawdopodobnie zapychasz pamięć.

Offline deadeye

  • Użytkownik

# Sierpień 29, 2012, 19:17:01
Na pewno to nie wina tła :) Jak renderujesz obrazki? Mam nadzieję że nie robisz tego przez poruszanie ImageView po formie...
Jedyną płynną metodą renderowania w czystym Androidzie jest korzystanie z osobnego wątku i czegoś w stylu SurfaceView.

Offline Xaon

  • Użytkownik

# Sierpień 30, 2012, 01:46:14
Sprawa wygląda komicznie.
Nie ładowałem piksmapy co klatkę. Z ImageView też nie korzystam. Framework zapewnia mi oddzielenie wątku UI od wątki grafiki i logiki. Faktyczne rysowanie odbywa się poprzez wywoływanie odpowiednich metod obiektu Canvas i wyłuskiwaniu bitmap z klas okalających, czy wrapperów jak ktoś woli. Myślę więc, że powinno to wystarczać do prostej casual'ówki.
Teoretycznie Android 3.0 powinien próbować przerzucać takie wywołania na kartę grafiki, ale jawnie go do tego nie zmuszam.
Dodałem do frameworka możliwość rysowanie piksmapy ze skalowaniem. Wrzuciłem statyczne tło o rozdzielczości 640 x 400 i przeskalowałem na pełny ekran. Śmiga jak ta lala.
Przypomniałem sobie również, że już stosuję w tej grze przeźroczystą piksmapę o rozdzielczości 1280 x 800, po której rysuję. Więc jedyne co mi przychodzi do głowy, to że 2 tak duże grafiki są dla tabletu zbyt dużym obciążeniem. Brzmi to jednak bardziej jak lamerska wymówka, niż faktyczne wyjaśnienie.

Offline goshki

  • Użytkownik
    • Vigeo Games

# Sierpień 30, 2012, 09:05:02
Może spróbuj najpierw potwierdzić, czy Garbage Collector zbyt często się nie włącza, np. przy użyciu narzędzia DDMS (linijki w stylu: "GC freed 1307 objects / 88360 bytes in 159ms").

W ogóle z Twojego opisu tego frameworka odnoszę wrażenie, że to jakiś software'owy blitter? Jeśli tak, to taki rozmiar bitmapy faktycznie może stanowić problem dla urządzenia. Dobrze by było więc także sprofilować czas rysowania grafik, jeśli masz możliwość wpięcia się wokół wywołania kodu renderującego, np. w taki sposób.

Offline deadeye

  • Użytkownik

# Sierpień 30, 2012, 10:51:26
a włączyłeś chociaż akceleracje sprzętową w manifeście?

<application android:hardwareAccelerated="true" ...>

Offline Xaon

  • Użytkownik

# Sierpień 30, 2012, 13:32:06
@goshki
Nie zauważyłem wcześniej, by GC się włączał jakoś szczególnie często. Jak będę miał chwilę, to sprawdzę.

@deadeye
Teraz nie. Jak dodawałem tą linijkę wcześniej, przy mniejszych grafikach, to różnica była dosłownie żadna (Czas mierzony z użyciem System.currentTimeMillis() i wyrzucaniem do logcat-a). Ale się upewnię.


EDIT.
Porobiłem parę testów. Wrzucam bardziej jako ciekawostkę.
Czasy rysowania pojedynczej klatki wyglądają następująco (mediana z pięciu kolejnych):
800x1280400x640brak tła
menu z HA0.0550.0420.028
menu bez HA0.0550.0440.028
poziom z HA0.070.0570.04
poziom bez HA0.070.0570.04
Jak widać czasy dla akceleracji i bez są tu praktycznie identyczne. Przy przejrzeniu większej ilości wyników mam wrażenie, że z włączoną akceleracją czas rysowana ulegał nieco mniejszym wahaniom.

Ważniejsze jest co znalazłem we frameworku:
public void drawPixmap(IPixmap pixmap, int x, int y) {
canvas.drawBitmap(((AndroidPixmap)pixmap).bitmap, x, y, null);
}
Spróbuję się pozbyć tego paskudnego rzutowania.


EDIT2
Zamienienie rzutowania na wywołanie getera z interfejsu kompletnie nic nie zmieniło.
public void drawPixmap(IPixmap pixmap, int x, int y) {
// canvas.drawBitmap(((AndroidPixmap)pixmap).bitmap, x, y, null); // rzutowanie
canvas.drawBitmap(pixmap.getBitmap(), x, y, null); //kontra geter
}
« Ostatnia zmiana: Wrzesień 03, 2012, 18:50:06 wysłana przez Xaon »