Duvida: metodos repaint() e paint()

2 respostas
R

Boa tarde pessoal.
Estou fazendo um joguinho que tem uma bola e uma raquete o objetivo é não deixar a bola cair na parte de baixo da frame,ela fica pingando nos outrs cantos do frame so não pode cair na parte de baixo do frame, por isso precisa da raquete para rebater a bolinha, é um joguinho classico de windows acho que todos ja viram.
Enfim a minha duvida é a seguinte: tenho a classe da bola, uma classe da raquete e um campo que é o frame principal. Estou chamando esses metodos no frame principal e passando como parametro as dimenções do frame, o que está acontecendo é que ele chama os metodos mas naum efetua as somas e tbm naum entra no metodo paint() quando dou um repaint() tanto na classe bola quanto na classe raquete.
Codigo da frame principal (campo):

public class projeto2 extends javax.swing.JFrame implements Runnable {
    int largura;

    public projeto2() {
        setUndecorated(true); //para mostrar a tela sem os botões de fechar e minimizar
        
        initComponents();
        createBufferStrategy(2);  //são usados dois buffers, enq8anto usa um para enviar pra tela o outro recebe dos metodos
        setIgnoreRepaint(true);  //para não ficar atualizando o desenho linha a linha
        
        Thread t = new Thread (this);
        t.start();
    }
        
        private void formMouseMoved(java.awt.event.MouseEvent evt){                                

        largura = evt.getX();
    }                               
    
            
    //quando a thread é disparada esse metodo que é rodado
    public void run() {
        while(true){
            Graphics g = getBufferStrategy().getDrawGraphics();
            
           //Istanciando as calsses bola e raquete
            bola ball = new bola();
            raquete raq = new raquete();
            
            //campo, cor e tipo (se é quadrado, circulo, etc)
            g.setColor(Color.BLACK);
            g.fillRect(0,0,this.getWidth(),this.getHeight());
   
            //chamo os metodos da classe bola passando os diamotros
            ball.itemX(getWidth());
            ball.itemY(getHeight());
            
            //chamo o metodo da classe raquete passando a largura do frame
            raq.mexeX(largura);
            
            g.dispose();
            getBufferStrategy().show();
            
            try{
                Thread.sleep(5);
            }catch (InterruptedException ex){
                ex.printStackTrace();
            }
        }
    }   
}
Classe bola:
public class bola extends javax.swing.JFrame {
    private int x;
    private int y;
    private int IncX;
    private int IncY;

    public bola() {
    }
    
     public void paint(Graphics g){
         System.out.println("Entrei no paint");
         g.setColor(Color.WHITE);
         g.fillOval(x,y,50,50);
         System.out.println("Ainda estou no paint");
     }
     
     public void itemX(int largura)
     {
         if(x==(largura-50))
             IncX = -1;
            
         if(x==0)
             IncX = 1;
         
         x = x + IncX;
         System.out.println("IncX = "+IncX);
         System.out.println("x = "+x);         
         repaint();
     }

     public void itemY(int altura)
     {

         if(y==(altura-50))
                IncY = -1;
            
            if(y==0)
                IncY = 1;
         
         y = y + IncY;
         System.out.println("IncY = "+IncY);
         System.out.println("y = "+y);
         repaint();
     }
}
Classe raquete:
public class raquete extends javax.swing.JFrame{
    private int mouse;  

    public raquete() {
    }
    
    public void paint(Graphics g){
         System.out.println("Entrei no paint");
         g.setColor(Color.RED);
         g.fillRect(mouse,250,60,20);
         System.out.println("Ainda estou no paint");
     }
     
     public void mexeX(int largura)
     {
         mouse = largura;
         
         System.out.println("mouse = "+mouse);         
         repaint();
     }    
}

quero saber o pq não esta funcionando o comando repaint() que chama executa o metodo paint() e pq ele não faz as somas.
Espero ter explicado direito qual é meu problema, qualquer duvida me falem
Grato

2 Respostas

ViniGodoy

É o seguinte… em primeiro lugar, não sobrescreva o paint diretamente, sobrescreva paintComponent no lugar. O método paint faz chamada a paintComponent, paintBorder e paintChildren.

Depois, nem sempre que você chamar repaint o paint será ativado. A AWT tem o direito de fazer uma coisa chamada “event coalescing”, ou seja, ignorar alguns repaints para ganhar um pouco de performance. Embora isso seja bom para a maior parte dos aplicativos swing, jogos são uma exceção a regra. É necessário usar pintura direta.

Já que você quer implementar um jogo, eu recomendo que você leia os primeiros capítulos do livro Killer Game Programming in Java, que podem ser baixados diretamente do site oficial. Ele explica como implementar a pintura direta, colocar o jogo em full screen e trabalhar com imagens e som. É uma ótima literatura. Se você estiver disposto a investir em livros desse gênero, dá uma olhada também em Developing Games in Java, do Dave Brackeen. A parte de áudio desse outro livro é simplesmente sensacional.

Eu também implementei um jogo similar ao que você está fazendo e que você pode fazer o download (com os fontes e tudo mais) aqui.

ViniGodoy

Vão aí mais algumas dicas:

  1. A classe bola não precisa ser um JFrame. Faça apenas um objeto comum, com um método draw, que recebe um Graphics2D. Chame esse método durante o paintComponent do frame principal, passando o objeto graphics do próprio frame principal (como demonstrado no próximo item);

  2. Conforme indica o Javadoc, você não deve alterar o estado do objeto Graphics. Até para deixar a programação mais simples, no início de cada método de pintura (paintComponent ou draw) faça uma cópia do seu objeto Graphics assim:

public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); //Comandos de pintura ball.draw(g2d); ... //Eliminação da cópia do graphics g2d.dispose(); }

  1. É importante que você tenha um bom gameloop, é a alma do seu jogo. O game loop é a thread que controla o fluxo do seu jogo. Há duas maneiras de se controlar esse fluxo. A primeira é manter a taxa de updates por segundo e frames por segundo a mais rápida possível e fazer todos os deslocamentos de objetos no jogo baseados numa diferença de tempos entre dois passos. Embora o algoritmo do loop fique mais simples, essa forma gera um código mais complexo no resto do jogo.

A segunda forma, que descrevo nesse artigo em que baseei no killer, é mantendo a taxa de frames alta, porém a taxa de updates constante. Não é necessário saber diferenças de tempo para atualização de movimentos, pois essa diferença será sempre a mesma.

  1. Baixe o Vikanoid e preste atenção especialmente nas classes Bat e Ball (muito similares a sua). Depois, dê no pacote JGF, dê uma olhada nas classes que controlam a thread principal e na classe ScreenManager. O código está bem documentado (pros padrões que a gente vê por aí), mas está todo em inglês (pelo menos, espero que aquilo seja um bom inglês :lol: ) mas qualquer coisa, pode me perguntar que eu te explico!

  2. Depois de pronto, deixe o jogo com os fontes no GUJ pra gente se divertir! E pra mais gente como você e eu trocarmos mais idéias! :wink:

Criado 31 de março de 2007
Ultima resposta 31 de mar. de 2007
Respostas 2
Participantes 2