Android: FPS bajo que dibuja muchos mapas de bits en una vista de superficie
Estoy tratando de crear un juego Bullethell y he tenido un poco de problemas. No puedo conseguir más de 17 fps después de unas 500 balas. El código de la lógica de la actualización tarda alrededor de 1-4ms para todos ellos mientras que el código de la toma toma alrededor de 40ms
Por ahora mi código es
- Cómo crear y guardar una captura de pantalla desde una vista de superficie?
- ¿Es esto posible tener la opinión de la textura para la cámara en forma circular para el androide?
- Tomando capturas de pantalla mediante programación no captura el contenido de surfaceVIew
- Cómo reanudar MediaPlayer en Android después de presionar el botón de inicio y volver a abrir la aplicación
- Adición de vista de texto a la vista de superficie
private void drawEntities(Canvas canvas) { for (HashMap<UUID, Spatial> h: spatialList) { for (Spatial spatial: h.values()) { spatial.render(canvas); if(spatial.life > 0) spatial.life--; else if (spatial.life == 0) engine.deleteEntity(spatial.owner); } } }
spatialList es un arrayList donde cada índice es un zLevel
El espacial que muestra la bala real es
public void render(Canvas canvas) { float angle = (float) (vel.getAngle() * (180 / Math.PI)); matrix.reset(); matrix.setTranslate(pos.x - bullet.getWidth() / 2, pos.y - bullet.getHeight() / 2); matrix.postRotate(angle + 90, pos.x, pos.y); canvas.drawBitmap(bullet, matrix, paint); canvas.drawCircle(pos.x, pos.y, col.getRadius(), paint); }
Puedo proporcionar más código, pero estos parecen ser el principal problema. He intentado todo lo que puedo pensar y no puedo encontrar mucho más en línea. Lo único que puedo pensar en arreglar esto es cambiar de una superficie a una GLSurfaceview, pero realmente creo que hay una mejor manera y sólo estoy usando código malo.
Edit: Me di cuenta de mi temporizador estaba apagado y eliminado el drawcircle y después de ejecutarlo de nuevo me sale 40ms ~ alrededor de 500, que sigue siendo un poco demasiado bajo para un rendimiento razonable.
TLDR; 500 entidades = 17 fps.
- Las pantallas parpadean y cambian de tamaño al iniciar la grabación de vídeo
- Anular onDraw () o draw ()?
- ¿Puedo usar lockCanvas () en onPreviewFrame callback?
- Extraño problema de rendimiento con Galaxy Tab
- Android: Cámara Asynctask con devolución de llamada de vista previa
- SurfaceView UpdateWindow () - NullpointerException
- Android VideoView.setAlpha no funciona (Xoom con 3.0)
- Ejecutar una tarea larga en glThread sin bloquear el hilo de la interfaz de usuario en Android
Puede estar limitado por la tasa de relleno de píxeles. ¿Qué tamaño (en píxeles) tiene la pantalla en su dispositivo de prueba?
Una cosa simple para jugar es usar setFixedSize()
para reducir el tamaño de SurfaceViewView. Eso reducirá el número de píxeles que estás tocando. Ejemplo aquí , video aquí , post de blog aquí .
Por lo general, es una buena idea hacer esto, ya que los dispositivos más nuevos parecen competir hacia absurdos conteos de píxeles. Un juego de pantalla completa que realiza toda la representación en software va a luchar en una pantalla de 2560×1440, y flail mal en 4K. "Limitar" el juego a 1080p y dejar que el escalador de pantalla haga el trabajo pesado debería ayudar. Dependiendo de la naturaleza del juego, podría establecer la resolución incluso más baja sin pérdida aparente de calidad.
Otra cosa a intentar es eliminar la llamada de drawBitmap()
, comprobar sus horarios, después restaurarla y eliminar la llamada de drawCircle()
, para ver si uno o el otro está mascando para arriba la mayor parte del tiempo.
Puede que el cambio a OpenGL ES no sea tan malo. La actividad de "hardware scaler exerciser" en Grafika (del video adjunto) muestra un renderizado de mapa de bits simple. Reemplace drawCircle()
con un mapa de bits a escala y es posible que la mayoría de la forma realizada. (Tenga en cuenta que utiliza SurfaceView, no GLSurfaceView, para GLES en esa actividad.)
Tuve el mismo problema. El problema se resolverá en gran medida si haces todo el dibujo en un framebuffer de mapa de bits y luego dibujar el framebuffer al lienzo. Si usted está dibujando directamente en el lienzo, entonces hay varios gastos generales. Miré alrededor y encontré este tutorial " http://www.kilobolt.com/day-6-the-android-game-framework-part-ii.html "
Mire la implementación de AndroidGraphics y AndroidFastRenderView y vea cómo usa AndroidGraphics para hacer todo el dibujo real en un búfer y pinta ese búfer al lienzo en AndroidFastRenderView.
Pruebe el rendimiento al quitar las partes rotación y / o drawCircle del método render (). Ambos pueden ser bastante tiempo como probablemente contienen sin () / cos () cálculos.
Si eso ayuda, usted tendrá que averiguar cómo reemplazarlos con algo más rápido, si no, bueno …
- ¿Cómo puedo mostrar el diseño de MainActivity en el método onCreate ()?
- Android Marshmallow – cómo saber "Nunca preguntar de nuevo" se comprueba antes