【问题标题】:Moving jLabel to a different place in the jPanel (Pacman like game)将 jLabel 移动到 jPanel 中的不同位置(类似 Pacman 的游戏)
【发布时间】:2014-01-28 16:58:42
【问题描述】:

我正在制作一个像吃豆人这样的游戏,到目前为止我只是从网格开始。我启动了网格,但我需要弄清楚如何将某些东西移动到网格中的不同位置,以便当用户单击或我的幽灵移动时,它会显示在屏幕上。我如何让它动起来?我尝试了很多不同的方法,但没有一个对我有用。

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


}

}

【问题讨论】:

    标签: java swing jpanel move pacman


    【解决方案1】:

    首先查看Concurrency in SwingHow to Use Swing Timers

    您将遇到的下一个问题是容器处于LayoutManager 的控制之下。虽然可以使用它来实现移动,但它会是块状的,因为每个组件都会跳跃单元格。

    如果你想要平滑移动,你将不得不设计自己的布局逻辑,这可能非常复杂。

    不过,您的目标应该是保持游戏的“虚拟”视图。这可以让您知道迷宫的形状和角色的位置,而无需与 UI 进行大量比较。然后你应该简单地渲染这个“虚拟”视图或模型的状态

    更新了非常基本的示例

    这是一个基本示例,它使用GridLayoutsetComponentZOrder 移动到面板周围的组件...没有碰撞检测,“AI”很可怜...

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

    【讨论】:

    • 这是一个类项目,所以它不需要平滑,但我正在寻找类似 label.set(x,y);有什么办法吗?
    • 是的,但是根据您的示例,它不起作用,因为附加标签的容器受布局管理器的控制。您可以考虑使用setComponentZOrder,这将改变组件的布局顺序,但您需要将 x/y 位置转换为线性值
    • 好的。我愿意改变布局。 (今天刚开始,我有一两个星期的时间来做这个)那么通过做另一种类型的 GUI 会更容易吗?老师根本没有教 GUI 的东西,但如果你想要满分的话,他会把它作为我们期末成绩的一部分。
    • 更改布局管理器会给您带来同样的问题。一个更简单的解决方案是取消布局管理器并手动计算对象的位置,但这并不容易并且会引发更多问题。另一种解决方案是直接进行绘画,但同样不容易,还会带来更多问题......
    【解决方案2】:

    在网格中的每个位置放置标签可能更简单,然后在你的生物移动时更改与每个标签相关的图标。见Add and remove an icon on a JLabel

    【讨论】:

    • 我刚读到,我把它删除了,但它没有指定位置,它是一个标签。另外,我没有办法设置它,因为如果我做了 .add() 它会添加到最后。我该怎么做?
    • 我的想法是,您创建一个标签引用的二维数组,并在将它们添加到网格布局时将它们添加到数组中,因此当您想要更改特定位置的图标时现场,您从数组中获取标签并调用setIcon(image)setIcon(null) 来设置或清除图像。另外:在 Swing 线程中进行这些调用很重要。 (如果您不是在摇摆计时器中执行此操作,请参阅 SwingUtilities.invokeLater 或 .invokeAndWait())
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2022-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多