Как рисовать на JPanel из нескольких внешних классов? - PullRequest
0 голосов
/ 04 января 2019

В настоящее время я делаю игру с главным меню и миром, в который вы действительно играете.

У меня есть класс с именем Game, который наследуется от JPanel и реализует интерфейсы Runnable, MouseListener, KeyListener и ActionListener (включены только важные детали)

У меня также есть два класса InWorldHandler и OutWorldHandler для работы с механикой в ​​мире и за его пределами соответственно.

Класс Game:

public class Game extends JPanel implements Runnable, KeyListener, MouseListener, ActionListener
{
    protected JFrame frame;
    private Timer timer = new Timer(25, this);

    private World world;
    private Player player = new Player();

    private boolean draw;

    Game(World world)
    {
        frame = new JFrame("Minecraft 2D");
        this.world = world;
        player.enterWorld(world, this);
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;

        if(draw)
        {
            g2d.setColor(new Color(255, 255, 255));
            g2d.fillRect(0, 0, frame.getWidth(), frame.getHeight());

            draw = false;
            //Here, the in-game mechanics should be handled
            if(player.inWorld())
            {
                Chunk chunk = player.getLoadedChunk();
                for(int x = 0; x < 16; x++)
                {
                    for(int y = 0; y < 16; y++)
                    {
                        Block block = chunk.getBlockAt(x, y);
                        BufferedImage texture = block.getTexture();

                        g2d.drawImage(block.getTexture(), x*32, y*32, texture.getWidth()*2, texture.getHeight()*2, null);
                    }
                }
            }
            //Here, the out-game mechanics should be handled
            else
            {

            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        this.repaint();
        draw = true;
    }

    @Override
    public void run()
    {
        draw = true;

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(this);
        frame.setMinimumSize(new Dimension(518, 540));
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.addKeyListener(this);
        frame.addMouseListener(this);
        frame.setFocusable(true);
        frame.setVisible(true);
        frame.pack();
        timer.start();
    }
}

В настоящее время оба других класса имеют пустые тела. Я просто понятия не имею, как это сделать.

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

1 Ответ

0 голосов
/ 04 января 2019

Вместо одного JPanel, почему бы вам не попробовать с CardLayout и переключиться, показывать ли InnerWorld или OuterWorld в соответствии с флагом, который определяет, где в программе, в которой вы находитесь.

Поскольку вы реализуете KeyListener, я думаю, что вы можете перемещать своего персонажа, пожалуйста, взгляните на принятый ответ на этот вопрос: Keylistener не работает на JPanel и используйте KeyBindings вместо.

Также избегайте использования setMimimum/Maximum/PreferredSize() и переопределяйте эти методы: Следует ли мне избегать использования методов set (Preferred | Maximum | Minimum) Size в Java Swing?

Взять этот код в качестве примера:

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Game {
    private JFrame frame;
    private JButton button;
    private boolean status;
    private JPanel[] cards;
    private CardLayout cl;
    private JPanel gamePane;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Game().createAndShowGUI());
    }

    private void createAndShowGUI() {
        frame = new JFrame(getClass().getSimpleName());
        button = new JButton("Switch Worlds");
        status = true; //True = Inner / False = Outer

        cl = new CardLayout();

        gamePane = new JPanel(cl);
        cards = new JPanel[2];

        cards[0] = new InnerWorld();
        cards[1] = new OuterWorld();

        gamePane.add(cards[0], "innerWorld");
        gamePane.add(cards[1], "outerWorld");

        button.addActionListener(e -> {
            status = !status;
            if (status) {
                cl.show(gamePane, "innerWorld");
            } else {
                cl.show(gamePane, "outerWorld");
            }
        });

        frame.add(gamePane);
        frame.add(button, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

@SuppressWarnings("serial")
class InnerWorld extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.drawString("Inner World", 50, 50);
    }

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

@SuppressWarnings("serial")
class OuterWorld extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.drawString("Outer World", 50, 50);
    }

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

enter image description here enter image description here

...