Перемещение jLabel в другое место в jPanel (игра, похожая на Pacman)

Я делаю игру типа pacman и пока только начинаю с сетки. Я запустил сетку, но мне нужно выяснить, как переместить что-то в другое место в сетке, чтобы, когда пользователь щелкает или мои призраки перемещаются, это отображалось на экране. Как заставить его двигаться? Я пробовал кучу разных способов, но ни один не работал для меня.

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);


}

}


person Caleb L    schedule 09.01.2014    source источник


Ответы (2)


Начните с изучения Параллелизм в Swing и Как использовать таймеры Swing

Следующая проблема, с которой вы столкнетесь, заключается в том, что контейнер находится под контролем LayoutManager. Хотя с его помощью можно добиться движения, оно будет блочным, так как каждый компонент будет прыгать по ячейкам.

Если вы хотите плавного движения, вам придется разработать собственную логику компоновки, это может быть очень сложно.

Тем не менее, к чему вы должны стремиться, так это к сохранению «виртуального» вида игры. Это позволяет вам узнать форму лабиринта и положение персонажей без необходимости делать много сравнений с пользовательским интерфейсом. Затем вы должны просто визуализировать состояние этого «виртуального» представления или модели.

Обновлен ОЧЕНЬ БАЗОВЫЙ пример

Это базовый пример, в котором используются GridLayout и setComponentZOrder для перемещения к компонентам на панели... Нет обнаружения столкновений, а "ИИ" выглядит жалко...

введите здесь описание изображения

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();
        }

    }

}
person MadProgrammer    schedule 09.01.2014
comment
Это для проекта класса, поэтому он не должен быть гладким, но я ищу что-то вроде label.set(x,y); Есть ли чем это сделать? - person Caleb L; 10.01.2014
comment
Да, но на вашем примере это не сработает, так как контейнер, к которому прикреплены метки, находится под управлением менеджера компоновки. Вы можете рассмотреть возможность использования setComponentZOrder, который изменит порядок расположения компонентов, но вам нужно будет преобразовать положение x/y в линейное значение. - person MadProgrammer; 10.01.2014
comment
Ok. Я готов изменить макет. (Только сегодня начал, и у меня есть неделя или две, чтобы сделать это) Так что, если сделать другой тип графического интерфейса, будет ли проще? Учитель вообще не преподавал GUI, но он делает это частью нашей итоговой оценки, если вы хотите получить полный балл. - person Caleb L; 10.01.2014
comment
Изменение менеджера компоновки оставляет вам ту же проблему. Более простым решением было бы отказаться от менеджера компоновки и рассчитать позиции объектов вручную, но это непросто и создает целую кучу проблем. Другим решением было бы рисовать напрямую, но опять же, это непросто и приносит еще кучу проблем... - person MadProgrammer; 10.01.2014

Может быть проще поставить метки в каждом месте сетки, а затем просто менять значки, связанные с каждой меткой, по мере движения ваших существ. См. раздел Добавление и удаление значка на JLabel.

person JVMATL    schedule 09.01.2014
comment
Я только что прочитал это, я удалил его, но он не указывал позицию, это был ярлык. Кроме того, у меня не было способа установить его, потому что, если бы я сделал .add(), он добавил бы в конец. Как бы я это сделал? - person Caleb L; 10.01.2014
comment
я думал, что вы создаете двумерный массив ссылок на метки и добавляете их в свой массив, когда добавляете их в свой макет сетки, поэтому, когда вы хотите изменить значок в определенном месте, вы берете метку из массив и вызовите setIcon(image) или setIcon(null), чтобы установить или очистить изображение. Также: важно, чтобы вы делали эти вызовы в потоке Swing. (см. SwingUtilities.invokeLater или .invokeAndWait(), если вы не делаете это из таймера свинга) - person JVMATL; 10.01.2014