Ponto V!

Home Java Java 2D Desenho direto - Active Rendering
Vinícius Godoy de Mendonça
Desenho direto - Active RenderingImprimir
Escrito por Vinícius Godoy de Mendonça

No artigo passado, vimos como fazer uma animação usando os já conhecidos paint() e repaint(). Isto é chamado de desenho passivo (passive rendering). Isto porque você pede um repaint, mas é o Swing quem efetivamente decide quando fazê-lo. De fato, algumas vezes o repaint é solenemente ignorado, o que é bom para aplicações janelas, mas não tão bom para jogos. Neste artigo, veremos como desenhar diretamente na tela, modificando o programa anterior para fazer o desenho direto (active rendering).

Estratégias de vídeo

No cinema, temos um rolo de filme fotográfico com diversas imagens, cada uma mostrando um instante de tempo diferente. Exibir uma imagem por vez nos dá a sensação de animação, pois nosso olho as interpola, dando a ilusão de movimento. No computador, usamos o mesmo princípio, mas podemos pintar uma imagem, enquanto exibimos outra.

No início da computação, os cientistas tentavam desenhar enquanto a imagem era exibida, na esperança do olho ser lento o suficiente para não perceber a pintura. Mas, nossos olhos não foram tão lentos assim, e enxergávamos uma imagem piscante, de baixa qualidade. Esse problema ficou conhecido como flickering.

Isso foi corrigido com o uso de duas áreas de memória. Uma delas é a área de vídeo, onde tudo que está desenhado é exibido na tela (front buffer). A outra, a área de desenho, que não é exibida. O Java trabalha com essa técnica, e todas as suas estratégias de vídeo se baseiam nela.

As estratégias de vídeo variam então a forma que o Java faz a troca dos dois buffers. Na verdade, quem faz essa troca é a placa de vídeo, e o Java tentará obter a melhor estratégia possível, dada as capacidades do hardware. As estratégias são:

  • Blitting: Quando é hora de exibir a tela, o conteúdo do buffer de pintura é copiado para o buffer de vídeo.
  • Page flipping: Quando é hora de exibir a tela, a placa de vídeo simplesmente atualiza dois ponteiros. Isso faz com que a área de pintura se torne a área de desenho, e vice-versa.

A figura abaixo demonstra o page flipping:

swapbuffers

A segunda estratégia é certamente mais eficiente que a primeira. Por mais que a cópia da imagem seja feita de maneira eficiente, atualizar somente quatro bytes (referentes aos ponteiros de vídeo e da área de desenho), será muito mais rápido. Entretanto, o page flipping só é possível se exibirmos a nossa aplicação em tela cheia, tema que veremos em artigos futuros.

A classe BufferStrategy

No java, temos uma classe chamada BufferStrategy. Ela é o tipo base de qualquer estratégia de pintura que iremos utilizar. Afinal, as operações básicas sobre o buffer serão sempre as mesmas: obtê-lo, pedir a troca do buffer, testar se o contexto de vídeo se perdeu, etc.

O método createBufferStrategy(), presente na classe Window, da qual JFrame deriva, permite a obtenção de uma estratégia de pintura concreta. Qual estratégia? A mais eficiente possível, para aquela configuração de vídeo. Como o método precisa determinar as configurações da janela ativa para ser chamado, só podemos chamá-lo com a janela visível. Portanto, um bom momento para criarmos nosso BufferStategy é a fase de setup() do nosso game loop. Criá-lo é bastante fácil. Basta chamar o método indicando como parâmetro o número de buffers. Esse valor geralmente será 2, pois são raríssimos os casos onde mais de 2 buffers são necessários. Nosso novo método de setup ficará:

public void setup() {
    //Criamos a estratégia de double buffering
    createBufferStrategy(2);
    //Subtrai a decoração da janela da largura e altura máximas
    //percorridas pela bola.
    ball = new Ball(getWidth() - getInsets().left - getInsets().right, 
            getHeight() - getInsets().top - getInsets().bottom);
}

Simples não? Podemos obter a BufferStrategy criada chamando o método getBufferStrategy().

Como iremos desenhar diretamente, podemos também pedir para o Swing ignorar todo e qualquer evento de repaint() na tela. Eventos de repaint ocorrem de maneira espontânea quando, por exemplo, algo que cobre a janela deixa de cobri-la, ou quando a janela é minimizada e restaurada. Para isso, basta adicionarmos ao construtor da janela o comando:

setIgnoreRepaint(true);

Vamos agora repensar no nosso método renderGraphics. No exemplo anterior ele ficou vazio, já que era o paint() que fazia seu papel. Nesse exemplo, nós iremos usá-lo para desenhar no buffer. Podemos obter o contexto gráfico associado a um BufferStrategy chamando o método getDrawGraphics(). Esse contexto já será uma cópia, portanto, precisamos chamar dispose() sobre ele.

Ele representará o buffer de pintura, assim, tudo o que fizermos nele ainda não será exibido. A exibição só ocorrerá efetivamente quando o método show() for chamado. Chamaremos o método show() na etapa paintGraphics() do nosso game loop. Isso facilita a instrumentação do nosso jogo, pois permite-nos saber quanto tempo gastamos em nossa lógica de pintura, e quanto tempo o Java gastou atualizando efetivamente o buffer.

@Override
public void renderGraphics() {        
    Graphics g = getBufferStrategy().getDrawGraphics();
    
    //Criamos um contexto gráfico que não leva em conta as bordas
    Graphics g2 = g.create(getInsets().left, 
               getInsets().top, 
               getWidth() - getInsets().right, 
               getHeight() - getInsets().bottom);
    //Limpamos a tela
    g2.setColor(Color.BLACK);        
    g2.fillRect(0, 0, getWidth(), getHeight());
    

    ball.draw((Graphics2D) g2); //Desenhamos a bola
    
    //Liberamos os contextos criados.
    g.dispose(); 
    g2.dispose();
}

@Override
public void paintScreen() {
    if (!getBufferStrategy().contentsLost())
        getBufferStrategy().show();
}

Note que no método paintScreen() tivemos que testar se o conteúdo do BufferStrategy foi ou não perdido antes de pintar a tela. Embora isso seja raro, esse teste se faz necessário pois é possível que a placa de vídeo limpe totalmente a sua área de vídeo, por exemplo, quando a resolução de tela muda (se o usuário pressionar ALT+TAB na sua aplicação de tela cheia, por exemplo). Nesse caso, não faremos a troca dos buffers, e deixaremos que o próprio loop principal pinte novamente o quadro.

Considerações finais

A classe JApplet não possui os métodos relacionados ao BufferStategy. Podemos contornar esse problema criando dentro do JApplet uma instância de JWIndow, que os possui, e fazendo-a ocupar toda a área do Applet.

Você pode baixar o código fonte da solução aqui. Nesses fontes, você encontrará também a classe BallFrame1, que é a classe do artigo anterior, para que você possa comparar as duas soluções.


Comentários (54)
  • Mikhas
    avatar

    Existe outra maneira de desenhar graficos 2D com java?

    Todos os exemplos que eu vejo são utilizando swing. Gostaria de saber se existe outra maneira/biblioteca que seja melhor/pior, mais rapida ou lenta.

    Grato

  • Vinícius  - Outras bibliotecas
    avatar

    Na verdade, ninguém perde tempo implementando outras bibliotecas sendo que a API padrão é muito completa, e de boa performance.

    A alternativa clássica ao Swing é o SWT:
    http://www.eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html

    Não conheço a performance dele para gráficos 2D. Para dispositivos móveis, outra alternativa é a API do Android.


    Você também pode usar uma API 3D, como a JOGL, e fazer jogos 2D nela, especialmente os vetoriais.

  • Mateus PL  - Muito bom.
    avatar

    Estou na espera do próximo tutorial.

    Só para acrescentar o que você disse sobre o JOGL, me parece que o exemplo do Space Invader do site http://www.cokeandcode.com/spaceinvaderstutorial usa esse esquema de fazer jogos 2D na API 3D.

  • Kauê Alves de Oliveira  -  Cala a boca
    avatar

    não quero saber de nada :evil:

  • raghy  - applets, ou web mesmo
    avatar

    é possível usar em applets.

    hoje também existe o webstart (?)
    launch (?)

  • Vinícius Godoy de Mendonça
    avatar

    Isso foi uma dúvida ou uma afirmação?

  • Moises
    avatar

    Primeiramente, Quero Parabenizá-lo pelos artigos. São bem didáticos e com conteúdo interessante. Estou começando a desenvolver alguma coisa na parte de animação, mas estou tendo um problema que não estou conseguindo resolver.
    Já consultei a API do java e seu código, mas mesmo assim a dúvida persiste.

    Estou "setando" true para 'setIgnoredRepaint()' no construtor de um JFrame.
    Mas ainda assim o formulário continua sendo repintado.
    Criei um metodo paint( Graphics ), com uma mensagem de saída pra confirmar.
    E ele realmente executa o metodo. No seu exemplo Ball testei a mesma coisa e não executou o método.

    Gostaria que pudesse me ajudar a contornar o problema. Grato pela atenção.

    (Abaixo o link com um simples exemplo) - toda vez que a janela é redimensionada paint() é chamado.

    http://pastebin.com/iUcmQx8R

  • Vinícius Godoy de Mendonça
    avatar

    O repaint irá ignorar apenas as mensagens de repaint que vierem do sistema operacional. Ou seja, se sua janela for parcialmente encoberta e depois exibida novamente.

    O redimensionamento provoca um repaint do próprio Swing, aí o método será chamado mesmo.

    Para evitar totalmente, use o BufferStrategy como explicado no artigo. 100% vc não evitará, mas seu método paint também não terá quase nada e isso deixa de ser um problema.

    As chamadas ao paint também reduzem se você usar a tela em full screen exclusive mode (FSEM).

  • Gilles Paiva  - Dúvidas iniciais...
    avatar

    Boa tarde,

    Gostaria de saber se os seus tutorias podem ser baixados com o código completo. Tipo... Estou vendo teus métodos, mas onde consigo a classe completa para poder entender tudo o que está acontecendo?

  • Vinícius Godoy de Mendonça
    avatar

    Olá, sempre olhe no final dos artigos. Ali, em "considerações finais" geralmente coloco um link para os fontes. Nesse artigo, está na última frase, bem na palavra aqui.

  • Nerd
    avatar

    Previsão para o próximo tutorial?

  • Clovis Rocha  - Duvidas sobre eliminar efeito de cintilamento
    avatar

    Sempre pensei comigo mesmo, porque as pessoas escrevem tão rebuscado quando tentam passar alguma coisa a outros? Lendo seus artigos reforçou ainda mais minha pergunta. Seus artigos são claros como uma folha de papel e extremamente objetivos (dá impressão que vc perguntou a cada um de nós o que gostaríamos de saber. Apesar de tudo isso estou com um problema. Só tenho ~ 1 mês de Java, embora já programe a vários anos em ASPNET. NÃO SOU PROGRAMADOR, sou um engenheiro que usa programação como ferramenta de trabalho, e procuro disponibilizar meu trabalho a todos interessados na Intranet da Empresa (ex cálculos elétricos, entre outros). Em contato com o java deparei com um ambiente de programação muito mais estimulante e poderoso. No entanto, o Java é para valentes que necessariamente têm que dominar perfeitamente os conceitos desta linguagem OO. No ASPNET o IDE do Visual Studio já entrega muita coisa pronta.
    Estou fazendo um programa, para o qual escolhi que fosse um Applet ou JApplet, para disponibilizar no browser de cada computador interessado na nossa intranet. Em resumo a tela tem dezenas de retas em coordenadas. Em cima deste gráfico estático, o movimento do mouse leva com ele uma reta vertical e uma horizontal, que o acompanham conforme a posição do mouse. Já fiz o código e está funcionando. Porém estou com o maldito “flickering” (no ASPNET a gente conta com a ajuda do AJAX). Li seu ótimo artigo (e todos os outros) sobre as estratégias de vídeo(BufferStrategy). Devido a minha (ainda) falta de conceitos me enrolei para implementação em Applet. (???JWindow...JApplet...etc).
    Se não for abuso, poderia me fornecer um cógigo fonte bem simples (só com 1 reta e o mouse passeando por cima dela)? Grato antecipadamente.... e desculpe a cara de pau!
    Clovis Rocha

  • Clovis Rocha  - Eliminasr Flickering
    avatar

    Achei exemplos ótimos para minha dúvida.
    http://www.realapplets.com/tutorial/DoubleBuffering.html

    Never mind...

  • Vinícius Godoy de Mendonça
    avatar

    Você chegou a usar o Double Buffering através da BufferStrategy como propus no artigo? Achei estranho vc perguntar de flickering, pois os artigos do gameloop e esse justamente eliminam esse problema.

  • DAVI LIMA  - GAMES
    avatar

    Prezados Senhores,

    Parabéns pela iniciativa, sou desenvolvedor experiente em java(SE,ME e EE) e sempre vi que faltava algo na minha profissão - A PARTE GRÁFICA.
    Com os posts do site Pontov estou melhorando a construção de telas amigáveis e dinâmicas.

    Grato
    Davi Lima

  • Vinícius Godoy de Mendonça
    avatar

    Obrigado! :)

  • Luiz Paulo de Vasoncellos  - Ótimo tutorial!
    avatar

    Um ótimo tutorial, de grande ajuda. Estou desenvolvendo um jogo 2D como passa-tempo e esse site me salvou de muita dor de cabeça :cheer:

    Só uma dúvida, as vezes quando eu rodo o jogo usando o ActiveRendergin(BufferStrategy), ele simplesmente falha ao iniciar, diz que não foi possível criar os buffers e trava a aplicação.
    Testei várias vezes, e de umas 50 vezes que rodei deu 2 duas vezes esse erro. Se puder me ajudar com isso, muito obrigado!

  • Vinícius Godoy de Mendonça
    avatar

    Geralmente ele faz isso se você tenta criar os buffers antes do JFrame estar visível.

    Quando ocorrer a próxima vez, mande-nos o texto da exception.

  • Luiz Paulo
    avatar

    Entendi. Realmente, se eu tento criar o Buffer antes de setVisible ele dá esse erro. Só que ele ocorre ocasionalmente mesmo depois do setVisible (tive que rodar umas 30 vezes pra conseguir que ele aparecesse :P ).

    ----

    Exception in thread "main" java.lang.IllegalStateException: Buffers have not been created
    ...

  • Vinícius Godoy de Mendonça
    avatar

    É um bug do Java mesmo:
    http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=520b5db156ed822 48f98f175d90fe?bug_id=6933331

    Existe um workaround que é desabilitar o Direct 3D, adicionando a opção -Dsun.java2d.d3d=false na linha de comando do java:
    java -Dsun.java2d.d3d=false -jar seuGame.jar

    Não tem previsão para ser corrigido. É por essas e outras que tenho recomendado o uso de C# e XNA no lugar do Java.

    Não só é muito mais poderoso, como é oficialmente suportado e você vai poder rodar seus jogos no X-Box (ou até publica-los na Live).

  • Luiz Paulo de Vasconcellos
    avatar

    Vish, um bug do java?
    Que pena, mas acho que vou continuar meu projeto mesmo assim.

    Quanto a usar C# e XNA, não sei... Não gosto do fato de rodar só em Windows (embora eu saiba que mesmo em java a grande maioria vai rodar no Windows).

    Eu tava pesquisando, conhece a biblioteca LWJGL? Parece ser muito boa e estável, foi usada em alguns projetos importantes, parece. Estava pensando em aprender ela em seguida, o que acha?

  • Vinícius Godoy de Mendonça
    avatar

    O Java Desktop hoje é suportado em duas plataformas, Windows e Linux. Sendo que na segunda, o número de jogadores e extremamente pequeno, insignificante. Se você quer mesmo apostar em games em Java, use o Android.

    Adicionalmente, o Java não dá suporte a diversas coisas necessárias em jogos:
    1. Não tem suporte para controles: Você deverá recorrer a bindings, como a JInput, que estão um tanto abandonados;
    2. Não tem boas classes para reproduzir sons: Você terá que recorrer a Java Zoom ou a classes feitas por indies;
    3. Não tem suporte a APIs gráficas 3D. Novamente, somente através de projetos terceiros.

    Parte desses bindings não são totalmente multiplataforma. É o caso do JInput, que hoje não roda bem no Linux e não tem suporte para o Mac (bom, nem o Java tem).


    Agora, em desktop, o XNA é oficialmente suportado também em duas plataformas. Windows e X-Box (além do Windows Phone 7, que não é representativo no Brasil). O Windows domina 96% do mercado de games para Desktop, enquanto o X-Box domina em torno de 30% do mercado para consoles. Se você quer atingir um público maior, não use Java.

    Também é possível rodar o XNA em Linux e Mac através do projeto Mono. Sem falar que a MS tem interesse e incentiva o mercado de games, do contrário da Sun e Oracle, que se fecham para esse mercado.


    Quanto à LWJGL. Ela é apenas um binding entre o Java, a OpenGL, a OpenAL e o JInput. Mas não vai muito mais longe que isso. Temos tutoriais de OpenGL aqui no portal (são em C++, mas vc vai ver que é praticamente a mesma coisa, já que OpenGL é OpenGL em qualquer lugar).


    Se quer usar uma API para desenvolver em 2D, e quer insistir com o Java, dê uma olhada na Slick2D, que roda sobre LWJGL e é portável para Android.

    Usar a LWJGL direto é uma boa se você quiser apenas estudar OpenGL, usando o Java, que é uma linguagem que você já conhece. Para games 3D, há APIs com maior suporte como a Unity3D e a JMonkeyEngine.

  • Luiz Paulo
    avatar

    ...
    ...
    Conseguiu me convencer :silly:
    Estou indo para o segundo ano de Sistemas de Informação e "pretendo" trabalhar com programação para jogos. Melhor me adequar para uma ferramenta melhor.

    Depois de terminar esse projeto, pretendo aprender OpenGL sim, embora o que eu tenha visto até agora tenha me desanimado um pouco. Código de openGL parece mandarim :shock:

  • Vinícius Godoy de Mendonça
    avatar

    O que pega em computação gráfica 3D não é tanto as APIs gráficas. A OpenGL é bem fácil de mexer. Mas sim, a matemática.

    Você precisa necessariamente saber como funcionam os vetores matemáticos na ponta da língua, assim como as matrizes de transformação. Felizmente, temos artigos sobre todos esses assuntos aqui no Portal. :side:


    Quanto ao Java, como vc deve saber, sou moderador do GUJ e sempre fui um grande fã do Java. Quando comecei os artigos, o Java ainda se apresentava uma promessa, mas tecnologias melhores foram surgindo ou se consolidando ao longo dos anos (XNA, Unity, etc.), ao mesmo tempo que o Java deixava de lado o suporte ao Mac, o J2ME morria e o JavaFX nunca se tornou uma alternativa realmente viável. :(

    Se quer apostar em Java para jogos hoje, a única alternativa industrialmente viável é o Android.

  • Vinícius Godoy de Mendonça
    avatar

    Esqueci de dizer no post anterior. A Sony também anunciou que o C# será a linguagem de desenvolvimento do Playstation Suite.

  • Roberto  - quando um JLabel fica sobre o outro, como definir
    avatar

    Eu tenho um projetinho que utilizei JLabel colocando figuras na propriedade icon. Também coloquei eventos que o usuário pode fazer drag and drop destes JLabels.

    Mas acontece o seguinte, quando o usuário dropa um JLabel sobre um outro JLabel, nem sempre o JLabel dropado fica por cima do outro. Permanece por baixo aquele que já estava por baixo em tempo de design. Como eu faço para definir qual eu quero em tempo de execução, que fique sobre o outro ?

  • Vinícius Godoy de Mendonça
    avatar

    Como sua dúvida não se refere a jogos ou Java2D, poste-a por favor no GUJ: http://www.guj.com.br

  • Fernando  - Como o BufferedStrategy sabe o nome da imagem
    avatar

    Como vc passa o nome da Imagem como parametro em BufferStrategy ou as imagens são carregadas quando vc cria a estratégia?!

  • Vinícius Godoy de Mendonça
    avatar

    O BufferStrategy não sabe. O que ele tem é um objeto Graphics, que aponta para o buffer de pintura.

    Leia nossos tutoriais desde o começo, e você vai entender como o Java 2D funciona.

  • Fernando  - BufferStrategy
    avatar

    mas vc cria ele antes de carregar as imagens na memória ou depois?!

  • Vinícius Godoy de Mendonça
    avatar

    Você cria ele no momento que torna a área de pintura visível. Isso é geralmente depois de carregar as imagens na memória.

  • Carlos
    avatar

    :) Vinícius qualquer hora pode fazer um tutorial de como usar JBox2D eu não consigo fazer nada naquilo :woohoo:

    :3 Desde já obrigado

  • Vinícius Godoy de Mendonça
    avatar

    Pensei em fazer da Box2D, mas na parte de C++.

  • Anônimo
    avatar

    :pinch: ah não C++ é chato (eu gosto, mas...) é que eu estou mexendo com o AndEnginer e o GDX (vc com certeza os conhece) eles tem uma extensão também usa ele e a biblioteca Slick2D e Lwjgl 3D agora Box2D com C++ só vai usar no Allegro :whistle: rs

    :cheer: acho que em java vai ser muito mais aproveitável, agora se você entende mais dele em C++ então blz o principio deve ser o mesmo. Só acho que java pegaria as tecnologia mais usadas na criação de jogos para telefonia móvel e desktop eu ajudaria muito eu que venho esperando por isso ansiosamente rs. C++ tb tem isso, mas é mais complicado usar rs :D

    Flw obrigado pelo tuto independente da linguagem o/

  • Vinícius Godoy de Mendonça
    avatar

    No C++, você poderia usar ele com SDL+OpenGL, Direct X, Allegro, Chien2D, Cocos-x, GameSpaceLib e até com o QT. Em mobile, vai ficar parecido para iPhone.

    Sem falar que a biblioteca é originalmente desenvolvida em C++. As versões mais atualizadas estão nessa linguagem.


    Agora, desde quando Java é uma tecnologia "mais usada para criação de jogos"? Em mobile, a linguagem cobre apenas o Android. Em Desktop, ele não é usado por nenhum tipo de estúdio, não é suportado por nenhum console, tem pouquíssimos games de sucesso e tem diversas limitações técnicas (como a obrigatoriedade de usar bindings em JNI, como a LWJGL).

  • Carlos
    avatar

    :pinch: ta ta ta vc ganhou kkkkkkkkkkkkk :woohoo:

  • Anônimo  - Dúvida
    avatar

    Como sempre o PontoV com ótimos artigos sobre desenvolvimento de jogos, parabens xD

    Li todos os artigos até esse aqui sobre Java2D, mas algo ainda me deixa um pouco desconfortável. Eu sei desenhar na tela e tal, mas e quando eu quiser mover um circulo com o teclado eu acho que vou ter que criar uns listeners a janela e tal. Até aí tudo bem, mas pelo que eu lembro, o tratamento dos eventos é numa thread separada, isso pode resultar num problema não? algo como o evento ser tratado enquanto o método update está sendo executado ou entre o update e o render, acho que isso pode modificar a posição do circulo e gerar resultados indesejáveis.
    Isso pode ser paranoia minha, ou não.
    Entretanto na sua opinião, quando um evento ocorre, mesmo que seja numa dessas situações acima, poderá ocorrer algum problema como esses que eu falei?

  • Vinícius Godoy de Mendonça
    avatar

    Sim. É verdade.

    Você terá que criar uma fila de mensagens entre a thread do game e a thread do Swing.

    Para isso, use a classe SynchronizedQueue do pacote java.util.concurrent. O chato é só ter que criar uma classe de mensagem para cada evento.

  • Anônimo
    avatar

    Como faço para usar o BufferStrategy no JPanel?
    Já tentei criar o buffer no JFrame e pegá-lo por um get no método paint do JPanel, mas só dá null.

  • bwolf
    avatar

    O link do BufferStrategy está quebrado? :(

  • ViniGodoy
    avatar

    Segue o novo link:
    http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferStrategy .html

    Quando puder, atualizaremos no artigo oficial.

  • Márcio oliveira
    avatar

    Olá Vini, parabéns pelo artigo.

    Muito interessante a organização das etapas do jogo.
    Seria interessante colocar a lógica de interação do usuário (clique do mouse, tecla pressionada, etc) no método processLogic? Tem algum artigo para indicar ou algum conselho e tal.

    Obrigado.

  • Anônimo
    avatar

    Já tentei de tudo mas não consigo tirar o flickering do meu game. Já tentei desenhando diretamente em um Canvas, em JFrame, e atualmente (o que já era antes) em um JPanel que pega o BufferStrategy do JFrame o qual tem o JPanel adicionado, fazendo o mesmo procedimento. Exemplo:

    render() {
    Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
    g2d.setColor(Color.BLACK);
    g2d.fillRect(0, 0, getWidth(), getHeight());
    g2d.drawImage(..., null);
    g2d.dispose();
    paintScreen();
    }

    public void paintScreen() {
    if (!strategy.contentsLost())
    strategy.show();
    }

    ...
    Já até tentei setar a prioridade da Thread, mas não dá jeito. rsrs

  • Delano Lima
    avatar

    Olá Viny!!

    Me diga uma coisa, quanto a parte de pegar o contexto gráfico sem levar em conta as bordas, não seria o certo passar o valor da borda esquerda como argumento para o parâmetro x? No caso das bordas direita e esquerda terem larguras iguais não importa, mas caso tenham larguras diferentes não ficaria certo da forma que foi feito. Estou certo?

    No caso, ao meu ver deveria ser feito assim:

    Código:
    Graphics g2 = g.create(getInsets().left,
    getInsets().top,
    getWidth() - getInsets().right,
    getHeight() - getInsets().bottom);

    Um abraço!

  • Vinícius Godoy de Mendonça
    avatar

    Sim, é exatamente isso. Obrigado pela correção.

  • Junior Guedes  - Dúvida JButton
    avatar

    Usando como base os códigos desdes artigo, como adicionar um JButton no BallFrame??

    Abraços...

  • Vinícius Godoy
    avatar

    Não há nada que te impeça de colocar um JButton no JFrame. Mas se for combinar Java 2D com Swing, o ideal seria sobrescrever o método paintComponent de um JComponent no lugar do JFrame, para poder posiciona-lo normalmente com os layout managers.

  • Rômulo
    avatar

    Negócio mesmo era tu escrever um livro de desenvolvimento de games em java.

  • Gleison
    avatar

    Muito obrigado pelas dicas.
    Ajudou muito!
    :cheer:

  • Kauê Alves de Oliveira  - re: Cala a boca
    avatar
    Kauê Alves de Oliveira Escreveu:
    n :woohoo: :whistle: :S ão quero saber de nada :evil:
  • Kauê Alves de Oliveira
    avatar

    Papai e mamãe ops discupa ai galera :woohoo: :whistle: :S

  • Kauê Alves de Oliveira  -  Cala a Boca
    avatar

    :woohoo: :whistle: :S Ahhh papai e mamãe ops discupa ai galera

  • Thiago F.  - Tutorial horrível.
    avatar

    public void setup() {
    //Criamos a estratégia de double buffering
    createBufferStrategy(2);
    //Subtrai a decoração da janela da largura e altura máximas
    //percorridas pela bola.
    ball = new Ball(getWidth() - getInsets().left - getInsets().right,
    getHeight() - getInsets().top - getInsets().bottom);
    }

    ... e da onde você tira esse "Ball"?
    E se você o título do arquivo é "Desenho direto" faz tanto mal assim colocar de maneira/ou com o método "setPixel"?

    Qual é o mal do setPixel? Ninguém quer ficar desenhando shapes, queremos manipular o array de cores.

    Vou eu ter que abrir um site e fazer um tutorial que ensine só:

    G2D.setPixel(x, y, cor)
    //... do something render

  • Leão
    avatar

    Ele deixa um código de exemplo para download, mas é bem superficial.

Escrever um comentário
Your Contact Details:
Gravatar enabled
Comentário:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):S:!::?::idea::arrow:
Security
Por favor coloque o código anti-spam que você lê na imagem.
LAST_UPDATED2  

Busca

Linguagens

Twitter