2011-02-14 10 views
7

He escrito una aplicación simple de Android que dibuja un laberinto utilizando una vista personalizada derivada de SurfaceView. Sigue el modelo de LunarLander sample application y realiza todos los cálculos y dibujos utilizando una cadena de fondo directamente en el objeto SurfaceHolder.¿Mejora el rendimiento de la vista personalizada derivada de SurfaceView?

Todo va bien y está funcionando bien para laberintos pequeños/medianos, sin embargo, si configuro el tamaño de la celda laberinto de 8 píxeles, hay muchas celdas en el laberinto en las que la aplicación se arrastra.

El código está haciendo algo que no me gusta porque dibuja todas las células incluso si no ha cambiado y esto es necesario para evitar el parpadeo de la pantalla desde el doble buffer SurfaceView (en iteraciones previas de la aplicación que estaba dibujando justo lo que cambió y que resultó en un desastre nervioso).

Lo que quiero entonces es la capacidad de usar SurfaceView, pero sé más selectivo sobre lo que se dibuja. es posible? si no, cuales son las alternativas? ¿Qué hay de mantener un mapa de bits fuera de pantalla, y de forma selectiva dibujar en ese primero?

EDIT: Implementé una combinación fuera de pantalla Bitmap y Canvas, escrita por mi máquina de estado accionada por temporizador, dibujando solo aquellas áreas afectadas durante la talla/solución. Luego, simplemente dibuje todo el mapa de bits fuera de pantalla en el SurfaceView dentro del método run() y esto ha resuelto mi problema; Puedo reducir el tamaño de la celda a 5 píxeles y el rendimiento es bueno.

+1

Si bien esto es antiguo, un SurfaceView que utiliza el Thread-SurfaceHolder estándar puede especificar un Rect en 'lockCanvas'; cuando esto se hace, solo esa región necesita ser actualizada. En algunas situaciones, puede ahorrar un poco de redibujado pero también requiere administrar la región sucia. –

Respuesta

5

acerca de los problemas de doble búfer:

Tome un vistazo a esta serie de tutoriales. ¿Ves alguna diferencia en la forma en que manejas el dibujo? https://web.archive.org/web/20121109162356/http://www.droidnova.com/playing-with-graphics-in-android-part-iii,176.html

Acerca de la optimización de su dibujo:

En el siguiente enlace, explica algunos enfoques:

http://developer.android.com/guide/topics/graphics/opengl.html

http://developer.android.com/reference/android/opengl/GLSurfaceView.html

representación continua versus render-cuando-sucia

mayoría 3D aplicaciones, como juegos o simulaciones , son continuamente animados. Pero algunas aplicaciones 3D son más reactivas: esperan pasivamente hasta que el usuario hace algo, y reaccionan. Para esos tipos de aplicaciones , el comportamiento GLSurfaceView predeterminado de forma continua redibujar la pantalla es un desperdicio de tiempo . Si está desarrollando una aplicación reactiva , puede llamar al GLSurfaceView.setRenderMode (RENDERMODE_WHEN_DIRTY), , que desactiva la animación continua . A continuación, llame al GLSurfaceView.requestRender() siempre que desee volver a procesar.

Además, en los juegos 2D es particularmente fácil calcular lo que está viendo el usuario, así que evite dibujar objetos fuera de la escena visible.

Una nota final:

Dijiste

Todo esto está muy bien y que está funcionando bien para los pequeños laberintos/medianos, sin embargo si fijo el tamaño de celda laberinto para ser de 8 píxeles haya muchas celdas en el laberinto en las que la aplicación se arrastra.

¿Esto significa que está calculando la solución del laberinto? Si es así, no debes hacerlo en el mismo hilo donde lo dibujas. Debes resolverlo en otro hilo. (Podría haberte entendido mal)

+0

Gracias por la respuesta. No, el primer ejemplo al que se vinculó no es como la forma en que mi vista se basa actualmente; el mío se parece más a la muestra LunarLander. Además, el segundo enlace y la sección sobre Representación continua vs render-when-dirty parecen relacionarse con OpenGL, por lo que no estoy seguro de cómo se relaciona mi aplicación. En lo que se refiere a la resolución del laberinto, estoy seguro de que no hay diferencia en el rendimiento: la solución es modificada por un temporizador y es muy simple. – trojanfoe

+0

Aunque obtuve el rendimiento mejorado después de utilizar un mapa de bits fuera de pantalla, ahora también he implementado su idea de realizar la actualización de UI y la solución/tallado de laberinto en hilos separados. Esto no fue por motivos de rendimiento, sino simplemente porque era confuso tener ambos en el mismo subproceso y clase, uno en el ciclo 'run()' y el otro en el tiempo. – trojanfoe

+1

Se relacionó porque está dibujando cada cuadro una y otra vez. Tal vez podrías actualizar la UI cuando algo se mueve. Para tener más mejoras, en su método de sorteo, evite dibujar objetos fuera del área visible. –

Cuestiones relacionadas