[Reubicando esta pregunta desde stackoverflow, ya que se señaló que encaja mejor aquí.]
Actualmente estoy transfiriendo mi motor de juego 2D a Java. Miré algunas de las bibliotecas de juegos apuntadas aquí en stackoverflow. Sin embargo, los que miré eran bastante simplistas y ni siquiera indicaban si admitían cosas como la transparencia alfa, por lo que decidí portar mi renderizador C ++ para el que ya había escrito la lógica.
Este procesador es un procesador de software puro que utiliza mosaico para evitar una nueva representación innecesaria. Optimicé su rendimiento de desplazamiento creando un "búfer fuera de pantalla" un poco más grande que mi panel de salida, y colocando este búfer fuera de pantalla en mi salida en cada fotograma. De esta manera, podría evitar volver a dibujar mosaicos innecesariamente solo porque desplacé un píxel en el mapa.
Utilicé AWT de Java para implementarlo, usando una imagen Buffered grande para el búfer fuera de pantalla. El uso de la CPU está bien (alrededor del doble de lo que tenía en C ++), pero hay un extraño problema con el desplazamiento continuo, donde cada segundo más o menos, el renderizador se retrasará durante aproximadamente 0.2 segundos.
Como no hay nada en mi propio código que ocurra en estos períodos, y dado que los picos desaparecen si no dibujo mi búfer fuera de la pantalla en la vista principal, solo puedo concluir que Java está haciendo una optimización interna propia. Sin embargo, no estoy seguro de lo que hace, ni sé cuál de mis optimizaciones tendría que eliminar para deshacerme de los picos. Además, puede ser que Java AWT no se haya hecho teniendo en cuenta el desplazamiento continuo y alto FPS, y eso es completamente inutilizable para este propósito.
¿Hay alguna forma de deshacerme de estos picos?
Respuestas:
Si bien no puedo estar seguro sin mirar su código, parece que su problema es el recolector de basura. En Java, tiene recolecciones de basura mayores y menores que tienen lugar de vez en cuando. El menor usa parte de su CPU pero no lo molestará demasiado. Las principales colecciones pueden ser un problema real para aplicaciones en tiempo real, como los juegos, ya que en realidad detendrán todo mientras se ejecutan.
Hay dos opciones para resolver esto. Primero puede ajustar la JVM para asegurarse de que se realicen las colecciones menos importantes. En segundo lugar (y recomendado), puede asegurarse de no dejar demasiada basura. Simplemente comprueba en qué parte de tu aplicación creas muchos objetos (en mis juegos, por lo general, son las clases de vector3) y asegúrate de reutilizarlos tanto como sea posible (especialmente en los bucles internos, etc.).
fuente
Si.
Para juegos basados en sprites 2D, AWT se puede usar para manejar el renderizado con gran efecto. Incluso puede ser acelerado por hardware , dependiendo del hardware disponible.
Sin ningún código o fragmentos de perfiles detallados, es difícil decir cuál es el problema. Lo mejor que puedo hacer es ofrecer algunos consejos básicos para trabajar con Java y AWT al crear juegos.
Trabajando con el recolector de basura
El GC en Java es algo que realmente debemos tener en cuenta al construir nuestros juegos. Se ejecutará periódicamente y buscará objetos que no tengan referencias a ellos, y los eliminará de la memoria. Este proceso de eliminación es lento y probablemente sea la causa del enganche que está experimentando.
Mi sugerencia es evitar crear referencias de objetos que no se mantendrán durante toda la ejecución (o al menos, tanto como sea posible). El objetivo ideal es asegurarse de que el GC no tenga nada que hacer cuando se ejecute.
En la práctica, puedes terminar con muchas variables estáticas que reutilizas a lo largo del juego. Aquí hay un ejemplo muy ingenioso de cómo tiendo a lidiar con eso:
Durante la carga de pantallas es donde puede aumentar o reducir sus
Map
instancias usando lanew
palabra clave. Pero durante el juego, querrás evitar eso tanto como puedas. Si algo se destruye durante el juego, coloca una bandera en el objeto para que sepas que no es algo que esté actualmente activo. Si necesita generar un nuevo objeto, reviseMap
hasta encontrar uno que no esté activo, configure sus propiedades y márquelo como activo.Esto es algo que debe tener en cuenta al usar Java para aplicaciones sensibles al rendimiento, independientemente de si está usando AWT, JavaFX u OpenGL para hacer el renderizado.
Lona
Para AWT en particular, recomendaría usar la clase Canvas para renderizar todo por varias razones:
fuente