[Reposicionando essa pergunta do stackoverflow, como foi apontado que ele se encaixa melhor aqui.]
Atualmente, estou portando meu mecanismo de jogo 2D para Java. Eu olhei para algumas das bibliotecas de jogos apontadas aqui no stackoverflow. No entanto, as que eu olhei eram bastante simplistas e nem declararam se suportavam coisas como transparência alfa, então decidi portar meu renderizador C ++ para o qual eu já havia escrito a lógica.
Este renderizador é um renderizador de software puro que usa o ladrilho para evitar a renderização desnecessária. Otimizei o desempenho de rolagem criando um "buffer fora da tela" um pouco maior que o meu painel de saída e colocando esse buffer fora da tela na minha saída em todos os quadros. Dessa forma, eu poderia evitar redesenhar os blocos desnecessariamente, apenas porque eu rolei um pixel no mapa.
Eu usei o AWT do Java para implementá-lo, usando um BufferedImage grande para o buffer fora da tela. O uso da CPU é bom (cerca de duas vezes o que eu tinha em C ++), mas há um problema estranho com a rolagem contínua, onde a cada segundo, o renderizador fica atrasado por cerca de 0,2 segundos.
Como não há nada no meu próprio código que ocorra nesses períodos, e como os picos desaparecem se eu não puxar meu buffer para fora da tela na tela principal, só posso concluir que o Java está fazendo uma otimização interna própria. No entanto, não tenho certeza do que faz, nem sei quais das minhas otimizações eu precisaria remover para me livrar dos picos. Além disso, pode ser que o java AWT não tenha sido feito com rolagem contínua e alta de FPS em mente, e isso é totalmente inutilizável para essa finalidade.
Existe alguma maneira de me livrar desses picos?
Respostas:
Embora eu não tenha certeza sem olhar para o seu código, parece que seu problema é o coletor de lixo. Em Java, você tem coletas de lixo maiores e menores de vez em quando. O menor usa um pouco do seu processador, mas não o incomoda muito. As principais coleções podem ser um problema real para aplicativos em tempo real, como jogos, pois eles realmente pausam tudo enquanto estão em execução.
Existem duas opções para resolver isso. Primeiro, você pode ajustar a JVM para garantir que menos coleções importantes ocorram. Em segundo lugar (e recomendado), você pode garantir que não deixa muito lixo. Basta verificar onde, no seu aplicativo, você cria muitos objetos (nos meus jogos, essas são geralmente as classes vector3) e certifique-se de reutilizá-las o máximo possível (especialmente em loops internos, etc.).
fonte
Sim.
Para jogos 2D baseados em sprites, o AWT pode ser usado para lidar com a renderização com grande efeito. Pode até ser acelerado por hardware , dependendo do hardware disponível.
Sem nenhum código ou snippets de perfil detalhados, é difícil dizer qual é o problema. O melhor que posso fazer é oferecer algumas dicas básicas para trabalhar com Java e AWT ao criar jogos.
Trabalhando com o coletor de lixo
O GC em Java é algo que precisamos ter em mente ao criar nossos jogos. Ele será executado periodicamente e procurará objetos que não tenham nenhuma referência a eles e os removerá da memória. Esse processo de remoção é lento e provavelmente é a causa do engate que você está enfrentando.
Minha sugestão é evitar a criação de referências a objetos que não serão mantidas por toda a vida útil da execução (ou pelo menos o máximo possível). O objetivo ideal é garantir que o GC não tenha nada para fazer sempre que for executado.
Na prática, você pode acabar com muitas variáveis estáticas que você reutiliza ao longo do jogo. Aqui está um exemplo muito bem elaborado de como eu tento lidar com isso:
Durante o carregamento das telas, é onde você pode aumentar ou diminuir suas
Map
instâncias usando anew
palavra - chave. Mas durante o jogo, você deve evitar isso o máximo que puder. Se algo for destruído durante o jogo, defina uma bandeira no objeto para que você saiba que não é algo ativo no momento. Se você precisar gerar um novo objeto, váMap
até você até encontrar um que não esteja ativo, defina suas propriedades e marque-o como ativo.Isso é algo que você deve ter em mente ao usar Java para aplicativos sensíveis ao desempenho, independentemente de estar usando AWT, JavaFX ou OpenGL para fazer a renderização.
Tela de pintura
Para o AWT em particular, eu recomendo usar a classe Canvas para renderizar tudo por vários motivos:
fonte