Pacman - Problemas com labirinto

To tentando fazer um Pacman em Java. Pra fazer o labirinto eu fiz os desenhos (só 2 ainda, pra teste), criei objetos Parede e fiz um array booleano pra ver quais são áreas de movimento. O problema é que não estou conseguindo mudar o valor das áreas com paredes. Por mais que eu marque 1, tudo continua marcando 0. Alguém poderia me ajudar?

[code]package pacman;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Jogo {

public Jogo() {
MyFrame janela = new MyFrame();
janela.setTitle("Pacman");
janela.setSize(810,900);
janela.setVisible(true);
janela.setDefaultCloseOperation(janela.EXIT_ON_CLOSE);

}

static public void run()
{
    Jogo jogo = new Jogo();
}        

}
class MyFrame extends JFrame
{
public MyFrame()
{
MyPanel painel = new MyPanel();
painel.setBackground(Color.BLACK);
getContentPane().add(painel);
addKeyListener(painel.c);
}
}

class MyPanel extends JPanel
{
private Image pacmandir = new javax.swing.ImageIcon(getClass().getResource(“Pacman1.png”)).getImage();
private Image pacmanesq = new javax.swing.ImageIcon(getClass().getResource(“Pacman1esq.png”)).getImage();
private Image pacmancima = new javax.swing.ImageIcon(getClass().getResource(“Pacman1cima.png”)).getImage();
private Image pacmanbaixo = new javax.swing.ImageIcon(getClass().getResource(“Pacman1baixo.png”)).getImage();
Comandos c = new Comandos();
Pacman pacman;
Labirinto maze;
Timer timer;
Paredes paredes[] = new Paredes[2];
private int tela[][] = new int [880][900];
private int x, y, indice;
private boolean verificaMover = false;

public MyPanel()
{
    pacman = new Pacman(400, 580, c);
    maze = new Labirinto();
    paredes[0] = new Paredes(40, 340, 40, 55);
    paredes[1] = new Paredes(40, 340, 103, 103+15);
    
    /*for(x = 0; x<880; x++)
    {
        for(y = 0; y<900; y++)
        {
            tela[x][y] = 0;
        }    
    }*/
    
    for(indice = 0; indice < paredes.length; indice++)
    {
        for(x = paredes[indice].getXmin(); x<paredes[indice].getXmax(); x++)
        {
            for(y = paredes[indice].getYmax(); y<paredes[indice].getYmax(); y++)
            {
                tela[x][y] = 1;
            }    
        }    
    }
    for(x = 0; x < 880; x++)
    {
               for(y = 0; y < 900; y++)
               {
                   if(tela[x][y] != 1)
                   {
                        verificaMover = true;
                   }
                   /*if(tela[x][y] == 1)
                   {
                       verificaMover = false;
                   }*/    
               }    
    }
    for(x = 0; x < 880; x++)
    {
               for(y = 0; y < 900; y++)
               {
                   if(tela[x][y] == 1)
                   {
                       System.out.println(tela[x][y]);
                   }
               }    
    }
    
    timer = new Timer(3, new ActionListener() {

        public void actionPerformed(ActionEvent e) {
           if(verificaMover == true) 
           {
               pacman.mover();
           }
           repaint();
        }
    });
    timer.start();
}
@Override
protected void paintComponent(Graphics g2d)
{
    super.paintComponent(g2d);
    maze.desenharLabirinto(g2d);
    if(!c.esquerda && !c.direita && !c.baixo && !c.cima)
        g2d.drawImage(pacmandir, pacman.getX(), pacman.getY(), null);
    if(c.direita)
        g2d.drawImage(pacmandir, pacman.getX(), pacman.getY(), null);
    if(c.baixo)
        g2d.drawImage(pacmanbaixo, pacman.getX(), pacman.getY(), null);
    if(c.cima)
        g2d.drawImage(pacmancima, pacman.getX(), pacman.getY(), null);
    if(c.esquerda)
        g2d.drawImage(pacmanesq, pacman.getX(), pacman.getY(), null);
    if(pacman.getY() >=736)
        pacman.setY(736);
    
       
}

} [/code]

Podem ler a partir do MyPanel. Obrigado…

lpdon, bom dia tudo bem?

Cara me desculpe eu li seu código e não entendi muito,
se estiver afim posta todo o fonte ai em um .rar pra mim ver o que tá dando errado.
Não intendi muito dessa classe parede e nem porque ela é um array com um monte de objeto igual dentro.

Não concordo com estruturação de tela com base em matriz masss porque simplismente não faz uma matriz de booleans do tamanho do mapa e onde é “true” pode andar e onde é “false”, não pode! Não intendi a ideia da parede e nem achei seu array boleano.

Posta mais coisa ai que eu te dou uma mão, ou alguem que sabe mais aqui pode te ajudar!


Att
Ricoldi

Alguns comentários:

  1. Não controle o loop principal com a classe Timer. Faça uma thread, ponha um while lá dentro. Depois, vc tem duas alternativas:
    a. Medir o intervalo de tempo entre 2 métodos draw (normalmente o preferido);
    b. Controlar a taxa de FPS, como descrito aqui no Killer;

  2. Uma das regras do Swing é não alterar o estado do contexto gráfico durante a pintura. Portanto, não use o objeto graphics diretamente no paint component.
    Faça o método assim:

    @Override  
    protected void paintComponent(Graphics g)  {         
        super.paintComponent(g);  

        //Fazemos a cópia do contexto gráfico
        Graphics g2d = (Graphics2D) g.create();

        maze.desenharLabirinto(g2d);  
        if(c.baixo)  
            g2d.drawImage(pacmanbaixo, pacman.getX(), pacman.getY(), null);  
        else if(c.cima)  
            g2d.drawImage(pacmancima, pacman.getX(), pacman.getY(), null);  
        else if(c.esquerda)  
            g2d.drawImage(pacmanesq, pacman.getX(), pacman.getY(), null);  
        else if(pacman.getY() >=736)  
            pacman.setY(736);
        else 
            g2d.drawImage(pacmandir, pacman.getX(), pacman.getY(), null);  

        g2d.dispose(); //Liberamos essa cópia                 
    }
  1. Os métodos de repintura (repaint(), validate() e invalidate()) tem um problema sério. Eles podem ser ignorados pelo swing, uma propriedade chamada "event coalescing". Você pode evitar esse efeito indesejável usando escrita direta. Para isso, controle diretamente a classe BufferStrategy do Java, como foi feito nesse post.

No mais, também acho que o trecho de código que vc postou é insuficiente para entender sua dúvida. Não vi onde vc usa a matriz de booleans e nem onde vc tenta fazer a atribuição.

As paredes servem pra marcar os retângulos que eu desenho no mapa. O array é “booleano” porque é feito em 0 e 1, não necessariamente true e false. Não fazendo essa verificação de áreas de movimento, qual é o outro jeito de delimitar o labirinto?

Ae lpdon


O que eu faço é o seguinte tenho uma super classe chamada Objeto que tem entre outros estes 2 metodos abaixo:

public class Objeto{

    public Rectangle getRetangulo(){      
        return new Rectangle(x,y,imagem.getWidth(), imagem.getHeight());
    }
    
    public boolean colisao(Objeto _objeto){
        Rectangle cxc   = getRetangulo();  //Minha caixa de colisão
        Rectangle cxcob = _objeto.getRetangulo(); //Caixa de colisão do Objeto parametro

        return cxc.intersects(cxcob); //Aqui ele verifica se os dois retangulos estão se chocando.
    }
}

Ai todas as outras classes que façam parte do cenário eu herdo desta. manja? e faço nelas uma verificação de colisão. que pode ser simples e cara onde verifica todo mundo com todo mundo. mas existem N modos de fazer esta verificação.

Creio que para seu PAC-MAN você deve fazer a verificação de colisão nos fantasmas e no proprio pac, já que são eles que se movem. afinal as paredes não vão bater com as paredes.

Fiz uma explicação simples, caso não intenda posta ai que eu tento melhor. mas o conceito é esse ai.


Att
Ricoldi

[quote=ricoldi]Ae lpdon


O que eu faço é o seguinte tenho uma super classe chamada Objeto que tem entre outros estes 2 metodos abaixo:

public class Objeto{

    public Rectangle getRetangulo(){      
        return new Rectangle(x,y,imagem.getWidth(), imagem.getHeight());
    }
    
    public boolean colisao(Objeto _objeto){
        Rectangle cxc   = getRetangulo();  //Minha caixa de colisão
        Rectangle cxcob = _objeto.getRetangulo(); //Caixa de colisão do Objeto parametro

        return cxc.intersects(cxcob); //Aqui ele verifica se os dois retangulos estão se chocando.
    }
}

Ai todas as outras classes que façam parte do cenário eu herdo desta. manja? e faço nelas uma verificação de colisão. que pode ser simples e cara onde verifica todo mundo com todo mundo. mas existem N modos de fazer esta verificação.

Creio que para seu PAC-MAN você deve fazer a verificação de colisão nos fantasmas e no proprio pac, já que são eles que se movem. afinal as paredes não vão bater com as paredes.

Fiz uma explicação simples, caso não intenda posta ai que eu tento melhor. mas o conceito é esse ai.


Att
Ricoldi

[/quote]

Não conhecia o intersects, valeu. Agora ficou bem mais fácil :smiley:

Tá certo!

Boa sorte e qualquer duvida posta ae.

Att
Ricoldi

Refiz o código da seguinte maneira:

[code]package pacman;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Jogo {

public Jogo() {
MyFrame janela = new MyFrame();
janela.setTitle("Pacman");
janela.setSize(810,900);
janela.setVisible(true);
janela.setDefaultCloseOperation(janela.EXIT_ON_CLOSE);

}

static public void run()
{
    Jogo jogo = new Jogo();
}        

}
class MyFrame extends JFrame
{
public MyFrame()
{
MyPanel painel = new MyPanel();
painel.setBackground(Color.BLACK);
getContentPane().add(painel);
addKeyListener(painel.c);
}
}

class MyPanel extends JPanel
{
private Image pacmandir = new javax.swing.ImageIcon(getClass().getResource(“Pacman1.png”)).getImage();
private Image pacmanesq = new javax.swing.ImageIcon(getClass().getResource(“Pacman1esq.png”)).getImage();
private Image pacmancima = new javax.swing.ImageIcon(getClass().getResource(“Pacman1cima.png”)).getImage();
private Image pacmanbaixo = new javax.swing.ImageIcon(getClass().getResource(“Pacman1baixo.png”)).getImage();
Comandos c = new Comandos();
Pacman pacman;
Labirinto maze;
Timer timer;
Paredes paredes[] = new Paredes[2];
private int indice;
private Rectangle pacmanRect;
private Rectangle paredesRect[] = new Rectangle[2];
private boolean colidiu = false;

public MyPanel()
{
    pacman = new Pacman(400, 580, c);
    maze = new Labirinto();
    paredes[0] = new Paredes(40, 340, 40, 55);
    paredes[1] = new Paredes(40, 340, 103, 103+15);
    pacmanRect = new Rectangle(pacman.getX(), pacman.getY(), pacmandir.getWidth(null), pacmandir.getHeight(null));
    
    for(indice = 0; indice<paredes.length; indice++)
    {
        paredesRect[indice] = new Rectangle(paredes[indice].getXmin(), 
                paredes[indice].getYmin(), paredes[indice].getXmax()-paredes[indice].getXmin(), 
                paredes[indice].getYmax()-paredes[indice].getYmin());
    }
    
     
    
    
    
    timer = new Timer(3, new ActionListener() {

        public void actionPerformed(ActionEvent e) {
           if(colidiu == false) 
           {
               pacman.mover();
           }
           pacmanRect.setLocation(pacman.getX(), pacman.getY());
           
           for(indice = 0; indice<paredesRect.length; indice++)
           {
                if(pacmanRect.intersects(paredesRect[indice]))
                {
                    colidiu = true;
                    System.out.println(colidiu);
                }    
            }
        repaint();
        }
    });
    timer.start();
    
    
}
@Override
protected void paintComponent(Graphics g2d)
{
    super.paintComponent(g2d);
    maze.desenharLabirinto(g2d);
    if(!c.esquerda && !c.direita && !c.baixo && !c.cima)
        g2d.drawImage(pacmandir, pacman.getX(), pacman.getY(), null);
    if(c.direita)
        g2d.drawImage(pacmandir, pacman.getX(), pacman.getY(), null);
    if(c.baixo)
        g2d.drawImage(pacmanbaixo, pacman.getX(), pacman.getY(), null);
    if(c.cima)
        g2d.drawImage(pacmancima, pacman.getX(), pacman.getY(), null);
    if(c.esquerda)
        g2d.drawImage(pacmanesq, pacman.getX(), pacman.getY(), null);
    if(pacman.getY() >=736)
        pacman.setY(736);
    
       
}

} [/code]

O problema é que se ele colide, para de se mover. Poderiam me ajudar com isso?

Deve ter algo errado no gerenciamento da thread do jogo. Alem disso seu codigo ta muito confuso. Segue um exemplo de design mais OO.

public class GameCanvas extends Canvas implements Runnable, KeyListener {
    private static final int delay = 50;
    private boolean running;
    private Game game;

    ... 

    public void start() {
        game.prepara();
        running = true;
        new Thread(this).start();
    }

    public void run() {
        long time = 0;

        while (running) {
            time = System.currentTimeMillis();

            game.update();

            Graphics g = buffer.getDrawGraphics();
            game.paint(g);
            g.dispose();
            buffer.show();

            time = System.currentTimeMillis() - time;

            if (time < delay) {
                try { Thread.sleep(delay - time); } catch(InterruptedException e) {}
            }
        }
    }
    
    public void itsOver() {
        running = false;
    }
}

então amigão, conseguiu resolver seu problema?