Autore Topic: Canvas, OpenGL o altro?  (Letto 2791 volte)

Offline Alien94

  • Nuovo arrivato
  • *
  • Post: 31
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy SII
Canvas, OpenGL o altro?
« il: 07 Settembre 2012, 12:09:52 CEST »
0
Salve!
Ho già pensato a quasi tutto per il mio secondo gioco su android ed ho un problema che non mi fa iniziare.
Ho una mappa formata da 48x48 tiles (quadrati), ognuno ha una texture.
Ovviamente le textures sono caricate nel seguente modo UNA VOLTA SOLA:
Codice (Java): [Seleziona]
Bitmap floorTile = BitmapFactory.decodeResource(res, R.drawable.floortile);
Le texture sono 48x48 px.

All'inizio ho provato a disegnare tutta la mappa, ottenendo meno di 20 fps. Allora ho fatto in modo che disegnasse solo
l'area visibile attorno al giocatore, circa 10x10.
In questo modo ho ottenuto 30-40 fps.

Non vi sembrano un po pochini visto che devo ancora implementare gran parte del gioco ed ho disegnato solo la mappa?

Sbaglio a disegnare usando le canvas per un gioco 2D?
Cosa dovrei usare?

Grazie

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Canvas, OpenGL o altro?
« Risposta #1 il: 07 Settembre 2012, 12:22:00 CEST »
0
Prova a usare le opzioni di bitmapfactory e impostare che non deve scalarle e che deve usare argb8888 (o equivalente). A volte le risorse non vengono caricate esattamente o cambia il formato e se non c'è un match con il formato dello schermo (imposta pure quello) puoi avere grossi rallentamenti.

Tutti ti diranno di usare OpenGL. Per i motivi sbagliati ma te lo diranno.

Alla fine comunque è più complicato all'inizio (ma ti diranno di usare andengine o libgdx).

Quindi se lo scopo è fare qualcosa di buono in fretta la solzione è il solito andengine che usa opengl.

Se lo scopo è imparare va beh, questa è un'altra storia.  ;-)

Offline Alien94

  • Nuovo arrivato
  • *
  • Post: 31
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy SII
Re:Canvas, OpenGL o altro?
« Risposta #2 il: 07 Settembre 2012, 12:30:37 CEST »
0
Prova a usare le opzioni di bitmapfactory e impostare che non deve scalarle e che deve usare argb8888 (o equivalente). A volte le risorse non vengono caricate esattamente o cambia il formato e se non c'è un match con il formato dello schermo (imposta pure quello) puoi avere grossi rallentamenti.

Tutti ti diranno di usare OpenGL. Per i motivi sbagliati ma te lo diranno.

Alla fine comunque è più complicato all'inizio (ma ti diranno di usare andengine o libgdx).

Quindi se lo scopo è fare qualcosa di buono in fretta la solzione è il solito andengine che usa opengl.

Se lo scopo è imparare va beh, questa è un'altra storia.  ;-)

Andengine e libgdx li ho già usati entrambi.
Andengine non lo uso perche preferisco gestirmi il tutto con il solito ciclo while.
Con libgdx avevo lo stesso rallentamento che sto riscontrando con le canvas.
Libgdx è ottima e vorrei usarla ma anche li solo disegnando la mappa ho 20-30 fps.
Ce qualche impostazione delle texture anche li?

Comunque intanto grazie per la risposta

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Canvas, OpenGL o altro?
« Risposta #3 il: 07 Settembre 2012, 12:32:18 CEST »
0
Secondo me non dovrebbe succedere. Forse c'è qualcosa che non va nel tuo loop? Che device stai usando?

Offline Alien94

  • Nuovo arrivato
  • *
  • Post: 31
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy SII
Re:Canvas, OpenGL o altro?
« Risposta #4 il: 07 Settembre 2012, 12:33:25 CEST »
0
Secondo me non dovrebbe succedere. Forse c'è qualcosa che non va nel tuo loop? Che device stai usando?
Galaxy s3.
Per questo mi stupisco

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Canvas, OpenGL o altro?
« Risposta #5 il: 07 Settembre 2012, 12:43:02 CEST »
0
Direi che NON dovrebbe succedere.  :-(

Stai usando una surfaceview???

Offline Alien94

  • Nuovo arrivato
  • *
  • Post: 31
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy SII
Re:Canvas, OpenGL o altro?
« Risposta #6 il: 07 Settembre 2012, 12:47:50 CEST »
0
Direi che NON dovrebbe succedere.  :-(

Stai usando una surfaceview???

Si si!
Consigli?

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Canvas, OpenGL o altro?
« Risposta #7 il: 07 Settembre 2012, 12:54:48 CEST »
0
Senza vedere il loop è difficile.

Setta questo:

Codice (Java): [Seleziona]
getHolder().setFormat(PixelFormat.RGBA_8888);
nel costruttore della surfaceview.

Poi quando carichi una bitmap fai questo semplice passaggio:

Codice (Java): [Seleziona]
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inScaled = false;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap myTileset = BitmapFactory.decodeResource(i_Context.getResources(),R.drawable.myTilesetGFX,opt);

Un altro suggerimento è quello di non fare niente per pulire lo schermo se lo sfondo/app è fullscreen.
Se hai una area x*y che ridisegni ogni frame non pulirla mai ma disegnaci lo sfondo e basta.

Disegna con:

Codice (Java): [Seleziona]
drawBitmap(Bitmap bitmap, float left, float top, Paint paint);
In questo modo sei sicuro che non vengono applicate trasformazioni e per il paint usa null.

Dimmi se migliora.  ;-)

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Canvas, OpenGL o altro?
« Risposta #8 il: 07 Settembre 2012, 13:00:23 CEST »
0
Tutti ti diranno di usare OpenGL. Per i motivi sbagliati ma te lo diranno.

Io sono uno di quelli, ma non dico il motivo :-)
adb logcat | tee /tmp/logcat | grep TAG

Offline Alien94

  • Nuovo arrivato
  • *
  • Post: 31
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy SII
Re:Canvas, OpenGL o altro?
« Risposta #9 il: 07 Settembre 2012, 13:03:14 CEST »
0
Senza vedere il loop è difficile.

Setta questo:

Codice (Java): [Seleziona]
getHolder().setFormat(PixelFormat.RGBA_8888);
nel costruttore della surfaceview.

Poi quando carichi una bitmap fai questo semplice passaggio:

Codice (Java): [Seleziona]
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inScaled = false;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap myTileset = BitmapFactory.decodeResource(i_Context.getResources(),R.drawable.myTilesetGFX,opt);

Un altro suggerimento è quello di non fare niente per pulire lo schermo se lo sfondo/app è fullscreen.
Se hai una area x*y che ridisegni ogni frame non pulirla mai ma disegnaci lo sfondo e basta.

Disegna con:

Codice (Java): [Seleziona]
drawBitmap(Bitmap bitmap, float left, float top, Paint paint);
In questo modo sei sicuro che non vengono applicate trasformazioni e per il paint usa null.

Dimmi se migliora.  ;-)

Mitico, 60 fps su galaxy s3!
60 fps anche su nexus 7.
Ora lo provo su un galaxy y
Ascolta, perchè un gioco risulti fluido all'utente, quanti fps deve avere almeno?
Grazie!

Offline Alien94

  • Nuovo arrivato
  • *
  • Post: 31
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy SII
Re:Canvas, OpenGL o altro?
« Risposta #10 il: 07 Settembre 2012, 13:03:34 CEST »
0
Io sono uno di quelli, ma non dico il motivo :-)
Perche?

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Canvas, OpenGL o altro?
« Risposta #11 il: 07 Settembre 2012, 13:12:29 CEST »
0
Io sono uno di quelli, ma non dico il motivo :-)
:-P

@Alien94:
Io come performance pura mi sono trovato bene con questa:

drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, Paint paint);

Ovviamente settando hasalpha false perchè stai disegnando uno sfondo e il paint è sempre null. Magari ci tiri fuori qualche fps in più.

Proprio a tale riguardo (fps e benchmarking) tu conta i millisecondi da DOPO la lockcanvas a PRIMA della unlockcanvasandpost. Questo perchè una delle due (non ricordo quale) è sincrona e quindi anche se scrivi codice che disegna in 1 ms (e quindi farebbe 1000fps) aspetta il retrace dello schermo (solitamente 60hz/fps ma su alcuni device 50/30fps). Sul mio galaxy s2 il tempo si aggira sui 16ms (60hz) anche se la funzione di disegno finisce in 3-4ms!

Fino a 30fps comunque un gioco va bene a patto che sia regolato in modo da gestire il tempo del frame.
Mi spiego. Se tu stabilisci che il tuo sfondo si sposta di mezzo schermo ogni secondo se non scali l'offset per il tempo su un device a 30fps ti ci vogliono due secondi. Il gioco sembra lento anche se in realtà non lo sarebbe. Se tu invece scali per il tempo trascorso tra un rendering e l'altro (in questo caso misurando TRA la lockcanvas e la unlockcanvasandpost) su ogni device il tuo gioco impiegherà sempre un secondo per spostare lo sfondo di metà schermo.

 ;-)

EDIT: per spiegarmi meglio

per il benckmark due controlli sul tempo, uno dopo la lockcanvas e uno prima della unlockcanvasandpost. ti da la velocità pura del tuo rendering.

per il tempo tra un frame e l'altro un solo controllo sul tempo, ad una riga predererminata (in teoria subito dopo la lockcanvas). ti da il tempo totale trascorso dall'ultima operazione di rendering.
siccome avrei qualcosa del tipo

Codice (Java): [Seleziona]
curtime  = System.currentTimeMillis();
frametime = curtime-oldtime;
oldtime = curtime;
tuocodicedirendering(frametime);

al primo frame avrai valori sballati che ti puoi gestire semplicemente settando frametime a -1 nel costruttore e facendo:

Codice (Java): [Seleziona]
curtime  = System.currentTimeMillis();
if( frametime == -1 )
frametime = 0.016f; // 60hz
else
frametime = curtime-oldtime;
oldtime = curtime;

tuocodicedirendering(frametime);

Così facendo se risetti frametime = -1 nella onpause ti gestisci pure quando il telefono va in sleep o l'utente clicca il tasto home.
 ;-)
« Ultima modifica: 07 Settembre 2012, 13:21:34 CEST da undead »

Offline Alien94

  • Nuovo arrivato
  • *
  • Post: 31
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy SII
Re:Canvas, OpenGL o altro?
« Risposta #12 il: 07 Settembre 2012, 13:14:27 CEST »
0
:-P

@Alien94:
Io come performance pura mi sono trovato bene con questa:

drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, Paint paint);

Ovviamente settando hasalpha false perchè stai disegnando uno sfondo e il paint è sempre null. Magari ci tiri fuori qualche fps in più.

Proprio a tale riguardo (fps e benchmarking) tu conta i millisecondi da DOPO la lockcanvas a PRIMA della unlockcanvasandpost. Questo perchè una delle due (non ricordo quale) è sincrona e quindi anche se scrivi codice che disegna in 1 ms (e quindi farebbe 1000fps) aspetta il retrace dello schermo (solitamente 60hz/fps ma su alcuni device 50/30fps). Sul mio galaxy s2 il tempo si aggira sui 16ms (60hz) anche se la funzione di disegno finisce in 3-4ms!

Fino a 30fps comunque un gioco va bene a patto che sia regolato in modo da gestire il tempo del frame.
Mi spiego. Se tu stabilisci che il tuo sfondo si sposta di mezzo schermo ogni secondo se non scali l'offset per il tempo su un device a 30fps ti ci vogliono due secondi. Il gioco sembra lento anche se in realtà non lo sarebbe. Se tu invece scali per il tempo trascorso tra un rendering e l'altro (in questo caso misurando TRA la lockcanvas e la unlockcanvasandpost) su ogni device il tuo gioco impiegherà sempre un secondo per spostare lo sfondo di metà schermo.

 ;-)

Grazie mille!
Sei stato gentilissimo!

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Canvas, OpenGL o altro?
« Risposta #13 il: 07 Settembre 2012, 13:20:23 CEST »
0
Perche?

Così nessuno potrà giudicare le mie motivazioni ;-)
adb logcat | tee /tmp/logcat | grep TAG