游戏(Java)的JFrame,JPanel或Canvas?

时间:2015-08-12 10:28:19

标签: java canvas jframe jpanel 2d-games

您好,目前我正在使用Java进行简单的2D游戏,现在我的问题是什么是最好的机会? JFrame,JPanel还是Canvas?我在谈论java中的每个2D游戏,所以我没有添加代码

2 个答案:

答案 0 :(得分:0)

一种流行的方法是在JPanel中覆盖paintComponent,如下所示:

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

    // put drawing code here
}

您可以通过在JPanel中的其他位置调用repaint方法来调用此方法,通常是为了响应用户提供的输入的Key事件,或者从Timer调用固定间隔更新。

以下是一些可以帮助您入门的代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;

public class GameFrame extends JFrame {
    private static final long serialVersionUID = 1L;

    public GameFrame() {
        super("Game Frame");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        getContentPane().add(new GamePanel(), BorderLayout.CENTER);
        pack();
        setResizable(false);
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {    
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new GameFrame();
                frame.setVisible(true);
            }
        });     
    }
}

class GamePanel extends JPanel implements ActionListener, KeyListener {
    private static final long serialVersionUID = 1L;
    private static final Dimension PANEL_SIZE = new Dimension(640, 480);
    private static final int REFRESH_RATE = 1000;
    private static final int CHARACTER_WIDTH = 32;
    private static final int CHARACTER_HEIGHT = 64;

    private Timer timer = new Timer(REFRESH_RATE, this);
    private int currentRow = 0;
    private int currentCol = 0;
    private int randomRow = 0;
    private int randomCol = 0;

    public GamePanel() {
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        timer.start();      
    }

    public Dimension getPreferredSize() {
        return PANEL_SIZE;
    }

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

        g.drawOval(randomCol, randomRow, CHARACTER_WIDTH, CHARACTER_HEIGHT);
        g.drawRect(currentCol, currentRow, CHARACTER_WIDTH, CHARACTER_HEIGHT);
    }

    public void actionPerformed(ActionEvent e) {
        int min = 0;
        int maxRow = (int)PANEL_SIZE.getHeight() - CHARACTER_HEIGHT;
        int maxCol =  (int)PANEL_SIZE.getWidth() - CHARACTER_WIDTH;

        Random rand = new Random();
        randomRow = rand.nextInt((maxRow - min) + 1) + min;
        randomCol = rand.nextInt((maxCol - min) + 1) + min;

        repaint();
    }

    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        int rowIncrement = 0;
        int colIncrement = 0;

        if(code == KeyEvent.VK_LEFT) {
            colIncrement--;
        }
        else if(code == KeyEvent.VK_RIGHT) {
            colIncrement++;
        }
        else if(code == KeyEvent.VK_UP) {
            rowIncrement--;
        }
        else {
            if(code == KeyEvent.VK_DOWN) {
                rowIncrement++;
            }
        }

        if(isInBounds(rowIncrement, colIncrement)) {
            currentRow += rowIncrement;
            currentCol += colIncrement;
            repaint();
        }
    }

    private boolean isInBounds(int rowIncrement, int colIncrement) {
        int top = currentRow + rowIncrement;
        int left = currentCol + colIncrement;
        int right = left + CHARACTER_WIDTH;
        int bottom = top + CHARACTER_HEIGHT;

        return (top >= 0 && left >= 0 && right <= PANEL_SIZE.getWidth() && bottom <= PANEL_SIZE.getHeight());       
    }

    public void keyTyped(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}
}

答案 1 :(得分:0)

https://github.com/jackmead515/java_game_engine

以上链接引用了我的个人游戏引擎。我使用java.awt.Canvas组件并将其添加到JFrame中。使用Canvas类很有用,因为您可以创建缓冲策略来预加载帧。您可以使用JPanel做同样的事情,但是只能调用一个名为setDoubleBuffered(true)的方法来激活双缓冲(这实际上应该是您所需要的。当然,这取决于您的游戏...)

注意:我事先表示歉意。该游戏引擎目前正在生产中,所以如果链接不起作用,请把它拿出来!此外,如果将来没有Canvas,那是因为我找到了更好的解决方案!干杯!

https://github.com/jackmead515/java_game_engine/blob/master/src/main/java/com/engine/jsm/display/Display.java

^^^将其添加到JFrame。

GameCanvas canvas = new GameCanvas();
canvas.setBounds(0, 0, Stats.getScreenWidth(), Stats.getScreenHeight());
canvas.addMouseListener(InputManager.getMouse());
canvas.addMouseMotionListener(InputManager.getMouse());
canvas.addKeyListener(InputManager.getKeyboard());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.getContentPane().setLayout(null);
this.add(gameCanvas);
this.pack();
canvas.createBufferStrategy(2);

https://github.com/jackmead515/java_game_engine/blob/master/src/main/java/com/engine/jsm/display/GameCanvas.java

^^^调用paint方法来调用您的东西!

    public void paint() {
       BufferStrategy bs = this.getBufferStrategy();
       Graphics2D g2 = (Graphics2D) bs.getDrawGraphics();
       g2.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));

       Main.world.render(g2, this);

       bs.show();
       g2.dispose();
    }