2008-09-29 11 views
31

Estoy en el proceso de escribir un juego Java 2D. Estoy utilizando las bibliotecas de dibujo 2D integradas de Java, dibujando en un Graphics2D que obtengo de una BufferStrategy desde un Lienzo en un JFrame (que a veces es una selección completa). BufferStrategy tiene doble amortiguación. Repintar se hace de forma activa, a través de un temporizador. Sin embargo, estoy teniendo algunos problemas de rendimiento, especialmente en Linux.Java 2D Drawing Optimal Performance

Y Java2D tiene tantas formas de crear búferes gráficos y dibujar gráficos que simplemente no sé si estoy haciendo lo correcto. He estado experimentando con graphics2d.getDeviceConfiguration(). CreateCompatibleVolatileImage, que parece prometedor, pero no tengo una prueba real de que vaya a ser más rápido si cambio el código de dibujo a eso.

En su experiencia, ¿cuál es la forma más rápida de renderizar gráficos 2D en la pantalla en Java 1.5+? Tenga en cuenta que el juego está bastante adelantado, por lo que no quiero cambiar a un método de dibujo completamente diferente, como OpenGL o un motor de juego. Básicamente, quiero saber cómo obtener la forma más rápida de usar un objeto Graphics2D para dibujar cosas en la pantalla.

+0

Simplemente por curiosidad, ¿de qué se trata el juego? : D –

+0

Re: Mario Ortegon: http: // www.metalbeetle.com/spaceexploration/. No puse un enlace en el principal ya que eso sería solo publicidad furtiva. El enlace – Zarkonnen

+1

se ve un poco extraño (... pero eso fue hace 8 años) –

Respuesta

16

Estoy teniendo los mismos problemas que usted, creo. Echa un vistazo a mi post aquí:

Java2D Performance Issues

Se muestra la razón de la disminución del rendimiento y cómo solucionarlo. Sin embargo, no está garantizado que funcione bien en todas las plataformas. Verás por qué en la publicación.

0

asegúrate de utilizar doble almacenamiento en búfer, dibuja primero a un gran búfer en la memoria que luego tiras a la pantalla cuando todo el dibujo está hecho.

+1

Actualmente, uso myCanvas.createBufferStrategy (2). Pero no sé si crear manualmente un búfer volátil no sería más rápido. – Zarkonnen

1

He hecho algunas aplicaciones básicas de dibujo usando Java. No he trabajado en nada demasiado intensivo en gráficos, pero recomendaría que tenga un buen manejo de todas las invocaciones de 'repintar'. Una llamada de repintado adicional en un contenedor principal podría duplicar la cantidad de renderizado.

0

Hay algunas cosas que tendrá que tener en cuenta

1) es refrescante this link muestra cómo utilizar swingtimers que podrían ser una buena opción para llamar a pintar. Obteniendo el repainting descifrado (como los carteles anteriores han dicho que es importante para que no estés haciendo demasiado trabajo).

2) Asegúrate de que solo estás dibujando en un hilo. La actualización de la interfaz de usuario de varios hilos puede llevar a cosas desagradables.

3) Double Buffering. Esto hace que la representación sea más suave. this site tiene más información buena para usted

+0

[link] (https://docs.oracle.com/javase/tutorial/extra/fullscreen/rendering.html) [link] (http://zetcode.com/tutorials/javagamestutorial/animation/) Es mejor para evitar osciladores y confiar en los hilos para la anmation. También es una buena práctica usar la representación activa en lugar de pasar la representación confiando en volver a pintar() – ingframin

1

He estado viendo esta pregunta, esperando que alguien le ofrezca una mejor respuesta que la mía.

Mientras tanto, encontré el siguiente Sun white paper que se escribió después de una versión beta de jdk 1.4. Hay algunas recomendaciones interesantes aquí en la puesta a punto, incluyendo las banderas de tiempo de ejecución (en la parte inferior del artículo):

"Bandera de ejecución Para Solaris y Linux

partir de la versión Beta 3 del SDK , versión 1.4, Java 2D almacena imágenes en mapas de píxeles de forma predeterminada cuando DGA no está disponible, si está trabajando en un entorno de visualización local o remota. Puede anular este comportamiento con el indicador pmoffscreen:

-Dsun.java2d.pmoffscreen = verdadero/falso

Si configura esta bandera como verdadera, el soporte de mapa de píxeles fuera de pantalla está habilitado incluso si DGA está disponible. Si establece este indicador en falso, el soporte de mapa de píxeles fuera de pantalla se desactiva. La desactivación del soporte de mapa de píxeles fuera de la pantalla puede resolver algunos problemas de representación. "

10

Aquí hay algunos consejos sobre mi cabeza.Si fueras más específico y estuvieras tratando de hacer, quizás pueda ayudarte más. Suena como un juego, pero no quiero suponer.

¡Solo dibuja lo que necesitas! No llame ciegamente a repintado() todo el tiempo, pruebe con algunos de los hermanos como volver a pintar (Rect) o volver a pintar (x, y, w, h).

Tenga mucho cuidado con la mezcla alfa, ya que puede resultar una operación costosa mezclar imágenes/primitivas.

Intente prerender/caché tanto como sea posible. Si te encuentras dibujando un círculo de la misma manera, una y otra vez, considera dibujar en una Imagen Buffered y luego dibuja la Imagen Buffered. Está sacrificando la memoria por la velocidad (típico de juegos/gráficos de alto rendimiento)

Considere usar OpenGL, use JOGL de LWJGL. JOGL es más parecido a Java, mientras que LWJGL proporciona más funcionalidad de juego además de acceso OpenGL. OpenGL puede dibujar órdenes de magnitud (con hardware y controladores adecuados) que Swing.

26

Una síntesis de las respuestas a este post, las respuestas a Consty's, y mi propia investigación:

Lo que funciona:

  • Uso GraphicsConfiguration.createCompatibleImage para crear imágenes compatibles con lo que se vaya a dibujar. Esto es absolutamente esencial!
  • Utilice dibujo de doble amortiguamiento a través de Canvas.createBufferStrategy.
  • Use -Dsun.java2d.opengl=True donde esté disponible para acelerar el dibujo.
  • Evite utilizar transformaciones para escalar. En cambio, guarde versiones escaladas de las imágenes que va a usar.
  • ¡Evite imágenes translúcidas! Las imágenes de máscara de bits son buenas, pero la translucidez es muy costosa en Java2D.

En mis pruebas, usando estos métodos, obtuve un aumento de velocidad de 10x - 15x, haciendo posible una correcta gráfica 2D de Java.

0

Una alternativa si no quieres ir puro Java 2D es utilizar una biblioteca de juegos como GTGE o JGame (buscarlos en Google), luego ofrecer un fácil acceso a los gráficos y también ofrecer doble buffering y mucho más simple comandos de dibujo

3

Hay una importante que aún no se ha mencionado, creo que: las imágenes de caché de todo lo que se puede. Si tiene un objeto que se mueve a través de la pantalla, y su apariencia no cambia mucho, dibuje en una imagen y luego visualice la imagen en la pantalla en una nueva posición en cada cuadro. Hazlo incluso si el objeto es muy simple: te sorprenderá cuánto tiempo ahorras. La representación de un mapa de bits es mucho más rápida que la representación de primitivas.

Es posible que también desee consultar la configuración explícita de sugerencias de representación y desactivar cosas como antialiasing si las consideraciones de calidad lo permiten.