2

I'm making a game like pacman and so far I am just starting with the grid. I got the grid started but I need to figure out how to move something to a different place in the grid so that when the user clicks or my ghosts move, it will display on the screen. How do I make it move? I have tried a bunch of different ways but none worked for me.

import java.awt.*;

import javax.swing.*;
import javax.swing.border.BevelBorder;


public class GUI {

public static void main(String[] args) {
    final JFrame f = new JFrame("Frame Test");
    GridLayout Layout = new GridLayout(50,50);

    JPanel panel = new JPanel(new GridLayout(50, 50, 1, 1));

    //Not sure if I need this or not?
    //panel.setLayout(new GridBagLayout());

    //first set of black
    for (int i = 0; i < 1000; i++) {
        JLabel a = new JLabel(new ImageIcon("black-square.jpg"), JLabel.CENTER);
        panel.add(a);

    }

    //adds pacman
    JLabel b = new JLabel(new ImageIcon("pacman.png"), JLabel.CENTER);
    panel.add(b);

    //next set of black
    for (int i = 0; i < 1000; i++) {
        JLabel c = new JLabel(new ImageIcon("black-square.jpg"), JLabel.CENTER);
        panel.add(c);
    }


   //do the thing 
    f.setContentPane(panel);
    f.setSize(1000, 1000);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);


}

}

Caleb L
  • 139
  • 1
  • 9

2 Answers2

1

Start by taking a look at Concurrency in Swing and How to Use Swing Timers

The next problem you're going to have is the fact that the container is under the control of a LayoutManager. While it's possible to achieve movement using this, it will be blocky, as each component will jump cells.

If you want smooth movement, you're going to have to devise your own layout logic, this can be very complicated.

None the less, what you should be aiming for is maintaining the a "virtual" view of the game. This allows you to know the shape of the maze and the position of the characters without need to do a lot of comparisons with the UI. You should then simply render the state of this "virtual" view or model

Updated with VERY BASIC example

This is a basic example, which uses a GridLayout and setComponentZOrder to move to components about the panel...There is no collision detection and the "AI" is pathetic...

enter image description here

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class PacMan101 {

    public static void main(String[] args) {
        new PacMan101();
    }

    public PacMan101() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new MazePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MazePane extends JPanel {

        private JLabel pacMan;
        private JLabel ghost;

        public MazePane() {
            pacMan = new JLabel(new ImageIcon(getClass().getResource("/PacMan.png")));
            ghost = new JLabel(new ImageIcon(getClass().getResource("/Ghost.png")));

            setLayout(new GridLayout(8, 8));
            add(pacMan);

            for (int index = 1; index < (8 * 8) - 1; index++) {
                add(new JPanel() {

                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(32, 32);
                    }

                });
            }

            add(ghost);

            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    move(pacMan);
                    move(ghost);
                    revalidate();
                    repaint();
                }

                protected void move(Component obj) {
                    int order = getComponentZOrder(obj);
                    int row = order / 8;
                    int col = order - (row * 8);

                    boolean moved = false;
                    while (!moved) {
                        int direction = (int) (Math.round(Math.random() * 3));
                        int nextRow = row;
                        int nextCol = col;
                        switch (direction) {
                            case 0:
                                nextRow--;
                                break;
                            case 1:
                                nextCol++;
                                break;
                            case 2:
                                nextRow++;
                                break;
                            case 3:
                                nextCol--;
                                break;
                        }

                        if (nextRow >= 0 && nextRow < 8 && nextCol >= 0 && nextCol < 8) {
                            row = nextRow;
                            col = nextCol;
                            moved = true;
                        }
                    }

                    order = (row * 8) + col;
                    setComponentZOrder(obj, order);

                }
            });
            timer.start();
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • This is for a class project, so it doesn't need to be smooth but what I am looking for is something like label.set(x,y); Is there anything to do this? – Caleb L Jan 09 '14 at 22:18
  • Yes, but it won't work based on your example, as the container to which the labels are attached is under the control of a layout manager. You could consider using `setComponentZOrder` which will change the order in which components are laid out, but you'll need to convert the x/y position into a linear value – MadProgrammer Jan 09 '14 at 22:21
  • Ok. I am willing to change the layout. (Just started today and I have a week or two to do this) So by doing another type of GUI would it be easier? The teacher didn't teach GUI stuff at all, but he is making it part of our final grade if you want full credit. – Caleb L Jan 09 '14 at 22:25
  • Changing the layout manager leaves you with the same problem. A easier solution would be to do away with the layout manager and calculate the positions of the objects manually, but this isn't easy and raises a whole bunch more problems. Another solution would be do the painting directly, but again, isn't easy and brings a whole bunch more problems... – MadProgrammer Jan 09 '14 at 23:13
0

It might be simpler to put labels at each spot in the grid, and then just change the icons associated with each label as your creatures move. See Add and remove an icon on a JLabel

Community
  • 1
  • 1
JVMATL
  • 2,064
  • 15
  • 25
  • I just read that, I got it to remove but it wasn't specifying a position, it was a label. Also, I didn't have a way to set it, because if i did .add() it would add to the end. How would I do this? – Caleb L Jan 09 '14 at 22:20
  • what I was thinking was, you create a 2d array of label references, and you add them to your array as you add them to your grid layout, so when you want to change the icon at a specific spot, you grab the label from the array and call `setIcon(image)` or `setIcon(null)` to set or clear the image. Also: important that you make these calls within the Swing thread. (see SwingUtilities.invokeLater or .invokeAndWait() if you are not doing this from within a swing timer) – JVMATL Jan 09 '14 at 22:35