Java 2D - Taxa de atualização

Olá pessoal,

Estou desenvolvendo um aplicativo que será integrado a um sistema BCI.

Mais especificamente, estou falando de SSVEP.

Gostaria de desenvolver um aplicativo onde tivesse um círculo (ou outra forma qualquer) que fosse atualizado em uma determinada frequência.

Por exemplo: um círculo que “pisca” em 12 Hz, 20 Hz, 30 Hz, dentre outras frequências.

Cheguei a implementar uma versão em Java, só que a taxa não se mantinha constante, além de ocorrer casos onde a figura “travava” e depois voltava.

Atualmente estou desenvolvendo os estímulos por meio de softwares externos de editoração e integrando a minha aplicação, mas não estou satisfeito com a solução e queria integrar tudo ao código da aplicação, até para tornar tudo mais parametrizável.

Fiz alguns testes utilizando a linguagem C# e tive o mesmo problema.

Estava pensando em tentar fazer uma implementação diretamente em OpenGL, mas antes gostaria de saber a opinião de vocês.

Já precisaram fazer algo do tipo, se sim, que solução adotaram?

Abraços.

Difícil dizer sem saber como você estava implementando.

Usou escrita direta? Fez buffer da sua imagem em memória, ou a redesenhada todas as vezes?

Já consegui rodar games inteiros no Java 2D mantendo framerate constante de 60 Hz.

[quote=ViniGodoy]Difícil dizer sem saber como você estava implementando.

Usou escrita direta? Fez buffer da sua imagem em memória, ou a redesenhada todas as vezes?

Já consegui rodar games inteiros no Java 2D mantendo framerate constante de 60 Hz.[/quote]

ViniGodoy,

Eu fiz um programa bem simples somente com a parte que interessa ao tópico.

Segue o código (Em C#):

private void panel1_Paint(object sender, PaintEventArgs e)
        {
            int quadrado = panel1.Width / 2;
            int cont = 0;

            Graphics g = panel1.CreateGraphics();
            SolidBrush sb = new SolidBrush(Color.White);
            SolidBrush sb2 = new SolidBrush(Color.Black);

            while(true)            
            {
                if (cont % 2 == 0)
                {
                    g.FillRectangle(sb, panel1.Width / 4, panel1.Height / 4, panel1.Width / 2, panel1.Height / 2);
                    cont = 1;
                }
                else
                {
                    g.FillRectangle(sb2, panel1.Width / 4, panel1.Height / 4, panel1.Width / 2, panel1.Height / 2);
                    cont = 0;
                }
                Thread.Sleep(40);
            }
        }

Eu não tenho experiência com programação gráfica, então posso estar cometendo erros grotescos.

Eu criei dois SolidBrush para tentar evitar a perda de tempo em ficar trocando a cor de um único.

Mas ainda assim noto algumas travadas quando coloco um Sleep menor que 40.

O resultado é um quadrado que fica alterando entre branco e preto em uma tela com fundo preto.

Tem alguma sugestão?

Uma outra dúvida é em relaçõ ao Sleep.

Se eu colocar 166, deveria atualizar a uma frequência de 6 Hz, ou seja, 6 vezes por segundo.

Mas isso não acontece, fica muito mais lento.

Desde já agradeço.

Sim, estude o Java 2D:
http://pontov.com.br/site/index.php/java/48-java2d

Em especial, a parte sobre desenho direto e loop de animação.

Acho que você pode melhorar seu código com uma pequena modificação no sleep, pra deixar a animação mais suave:


...
while(true)
{
    long time = System.currentTimeMillis();

    //atualiza o display...

    time = System.currentTimeMillis()-time;

    Thread.sleep(40-time);
}


Com essa modificação, cada laço no while leva exatamente 40 ms.

[quote=ViniGodoy]Sim, estude o Java 2D:
http://pontov.com.br/site/index.php/java/48-java2d

Em especial, a parte sobre desenho direto e loop de animação.[/quote]

Obrigado.

Fiz algumas alterações e funcionou.

Só que fiz em C#, que é mais interessante para o meu caso.

Agora tenho uma taxa fixa de atualização.

Agora vou testar o estímulo, se funcionar, problema resolvido.

[quote=ImpossiveI]Acho que você pode melhorar seu código com uma pequena modificação no sleep, pra deixar a animação mais suave:


...
while(true)
{
    long time = System.currentTimeMillis();

    //atualiza o display...

    time = System.currentTimeMillis()-time;

    Thread.sleep(40-time);
}


Com essa modificação, cada laço no while leva exatamente 40 ms.[/quote]

Muito obrigado pela ajuda.

Por curiosidade, caso tenha tempo tente fazer o mesmo teste com o JavaFX, que está sendo posicionado pra substituir o Java 2D.

Stacker estou com o mesmo problema. Poderia me ajudar?

Usando o Java 2D você pode fazer um loop de animação melhorado, como o do Ponto V. Mas eu achei melhor mudar a tecnologia. Eu fiz uma versão em Unity3D e agora estou fazendo em OpenGL.

E como vc definiu as frequencias? Tem algum exemplo?