每当我创建一个新的JFrame
屏幕时,由于某种原因,游戏不会在我的电脑上运行,我不知道为什么。我试过修复这个问题,但我认为它与按钮或屏幕的位置有关。 startStage
是我需要帮助的。如果我遗失了什么,请告诉我。
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
* This class demonstrates basic animation using a timer, an action listener,
* and a key listener
*
*
*
*/
public class GameWindow extends JPanel implements ActionListener, KeyListener {
private static final long serialVersionUID = 1L;
JLabel player = new JLabel();
int playerSpeed = 1;
int FPS = 30;
// The keys set holds the keys being pressed
private final Set<Integer> keys = new HashSet<>();
public static void main(String[] args) {
// Open the GUI window
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Create a new object and
// run its go() method
new GameWindow().go();
}
});
}
public GameWindow() {
// Run the parent class constructor
super();
// Allow the panel to get focus
setFocusable(true);
// Don't let keys change the focus
setFocusTraversalKeysEnabled(false);
//Make a new screen with a button and put it in the window
JPanel startStage = new JPanel(); // Create a new JPanel and add it to the card layout
startStage.setSize(getWidth(), getHeight()); // make the new JPanel fit the window
startStage.setBackground(Color.BLUE); // set the JPanel background to blue
startStage.setVisible(true); // show the JPanel
JButton playButton = new JButton("Play"); // Add a button to the panel
playButton.addMouseListener(new MouseAdapter() { // Set the button to switch to the game stage
@Override
public void mouseClicked(MouseEvent arg0) {
((CardLayout) getContentPane().getLayout()).show(
getContentPane(), "game");
}
});
startStage.add(playButton); // add the button to the stage
add(startStage, "start"); // add the stage to the window
}
protected void go() {
// Setup the window
JFrame jf = new JFrame();
// Add this panel to the window
jf.setContentPane(this);
// Set the window properties
jf.setTitle("Animation Demo");
jf.setSize(300, 200);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
// Setup the movable box
player.setBounds(10, 10, 10, 10);
player.setVisible(true);
player.setBackground(Color.BLUE);
// Opaque makes the background visible
player.setOpaque(true);
// Setup the key listener
addKeyListener(this);
// Null layout allows moving objects!!!
setLayout(null);
add(player);
// Set the timer
Timer tm = new Timer(1000 / FPS, this);
tm.start();
}
@Override
public void actionPerformed(ActionEvent arg0) {
// Move up if W is pressed
if (keys.contains(KeyEvent.VK_W)) {
player.setLocation(player.getX(), player.getY() - playerSpeed);
}
// Move right if D is pressed
if (keys.contains(KeyEvent.VK_D)) {
player.setLocation(player.getX() + playerSpeed, player.getY());
}
// Move down if S is pressed
if (keys.contains(KeyEvent.VK_S)) {
player.setLocation(player.getX(), player.getY() + playerSpeed);
}
// Move left if A is pressed
if (keys.contains(KeyEvent.VK_A)) {
player.setLocation(player.getX() - playerSpeed, player.getY());
}
}
@Override
public void keyPressed(KeyEvent e) {
// Add the key to the list
// of pressed keys
if (!keys.contains(e.getKeyCode())) {
keys.add(e.getKeyCode());
}
}
@Override
public void keyReleased(KeyEvent e) {
// Remove the key from the
// list of pressed keys
keys.remove((Integer) e.getKeyCode());
}
@Override
public void keyTyped(KeyEvent e) {
}
}
答案 0 :(得分:1)
您似乎对容器管理的工作方式存在问题。停下来,退后一步,重新思考你的方法。
你基本上有一个&#34;菜单&#34;和#34;游戏&#34;面板。这应该是两个单独的小组/类。
然后将这些添加到&#34; hub&#34;面板,管理它们的显示时间和方式。
MainPane
这是&#34;主要&#34;,&#34; hub&#34;面板。它负责显示菜单和游戏面板。它还负责决定&#34;如何&#34;发生这种情况,在这个例子中,我只使用了CardLayout
public class MainPane extends JPanel {
public MainPane() {
setLayout(new CardLayout());
MenuPane menu = new MenuPane();
menu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (getLayout() instanceof CardLayout) {
CardLayout layout = (CardLayout) getLayout();
layout.show(MainPane.this, "game");
}
}
});
GamePane game = new GamePane();
add(menu, "menu");
add(game, "game");
((CardLayout) getLayout()).show(this, "menu");
}
}
MenuPane
&#34;菜单&#34;很简单。它只显示可用选项,并为选择选项时通知相关方提供方法
public class MenuPane extends JPanel {
private JButton btn;
public MenuPane() {
setLayout(new GridBagLayout());
setBackground(Color.BLUE);
btn = new JButton("Start");
add(btn);
}
public void addActionListener(ActionListener listener) {
btn.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
btn.removeActionListener(listener);
}
}
我不会对此有太多了解,但您应该查看How to Use Buttons, Check Boxes, and Radio Buttons和How to Write an Action Listener了解更多详情
我很懒,将ActionListener
直接贴在按钮上。相反,您应该分别管理按钮侦听器和面板的侦听器,这将防止暴露按钮并允许您更好地控制执行特定操作时生成的内容。
GamePane
最后,#34;游戏&#34;面板。正如我在最后一天所说的那样,你应该使用custom painting route和How to Use Key Bindings。他们将共同解决我们通常不想再被问到的其他问题,
public interface Movable {
public void changeLocation(int xDelta, int yDelta);
}
public class GamePane extends JPanel implements Movable {
private Rectangle player;
public GamePane() {
String text = "X";
FontMetrics fm = getFontMetrics(getFont());
int width = fm.stringWidth(text);
int height = fm.getHeight();
player = new Rectangle(0, 0, width, height);
setupKeyBindings();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void setupKeyBindings() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");
int xDelta = player.width;
int yDelta = player.height;
am.put("up", new MoveAction(this, 0, -yDelta));
am.put("down", new MoveAction(this, 0, yDelta));
am.put("left", new MoveAction(this, -xDelta, 0));
am.put("right", new MoveAction(this, xDelta, 0));
}
@Override
public void changeLocation(int xDelta, int yDelta) {
int xPos = player.x + xDelta;
int yPos = player.y + yDelta;
if (xPos + player.width > getWidth()) {
xPos = getWidth() - player.width;
} else if (xPos < 0) {
xPos = 0;
}
if (yPos + player.height > getHeight()) {
yPos = getHeight() - player.height;
} else if (xPos < 0) {
yPos = 0;
}
player.setLocation(xPos, yPos);
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.draw(player);
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString("X", player.x, player.y + fm.getAscent());
g2d.dispose();
}
}
public class MoveAction extends AbstractAction {
private Movable movable;
private int xDelta;
private int yDelta;
public MoveAction(Movable movable, int xDelta, int yDelta) {
this.movable = movable;
this.xDelta = xDelta;
this.yDelta = yDelta;
}
@Override
public void actionPerformed(ActionEvent e) {
movable.changeLocation(xDelta, yDelta);
}
}
全部放在一起......
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game {
public static void main(String[] args) {
new Game();
}
public Game() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
setLayout(new CardLayout());
MenuPane menu = new MenuPane();
menu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (getLayout() instanceof CardLayout) {
CardLayout layout = (CardLayout) getLayout();
layout.show(MainPane.this, "game");
}
}
});
GamePane game = new GamePane();
add(menu, "menu");
add(game, "game");
((CardLayout) getLayout()).show(this, "menu");
}
}
public class MenuPane extends JPanel {
private JButton btn;
public MenuPane() {
setLayout(new GridBagLayout());
setBackground(Color.BLUE);
btn = new JButton("Start");
add(btn);
}
public void addActionListener(ActionListener listener) {
btn.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
btn.removeActionListener(listener);
}
}
public interface Movable {
public void changeLocation(int xDelta, int yDelta);
}
public class GamePane extends JPanel implements Movable {
private Rectangle player;
public GamePane() {
String text = "X";
FontMetrics fm = getFontMetrics(getFont());
int width = fm.stringWidth(text);
int height = fm.getHeight();
player = new Rectangle(0, 0, width, height);
setupKeyBindings();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void setupKeyBindings() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");
int xDelta = player.width;
int yDelta = player.height;
am.put("up", new MoveAction(this, 0, -yDelta));
am.put("down", new MoveAction(this, 0, yDelta));
am.put("left", new MoveAction(this, -xDelta, 0));
am.put("right", new MoveAction(this, xDelta, 0));
}
@Override
public void changeLocation(int xDelta, int yDelta) {
int xPos = player.x + xDelta;
int yPos = player.y + yDelta;
if (xPos + player.width > getWidth()) {
xPos = getWidth() - player.width;
} else if (xPos < 0) {
xPos = 0;
}
if (yPos + player.height > getHeight()) {
yPos = getHeight() - player.height;
} else if (xPos < 0) {
yPos = 0;
}
player.setLocation(xPos, yPos);
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.draw(player);
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString("X", player.x, player.y + fm.getAscent());
g2d.dispose();
}
}
public class MoveAction extends AbstractAction {
private Movable movable;
private int xDelta;
private int yDelta;
public MoveAction(Movable movable, int xDelta, int yDelta) {
this.movable = movable;
this.xDelta = xDelta;
this.yDelta = yDelta;
}
@Override
public void actionPerformed(ActionEvent e) {
movable.changeLocation(xDelta, yDelta);
}
}
}
请记住,您的目标之一应该是&#34;责任分离&#34;,创建完成工作并做得好的类/组件。通过这种方式,您可以将它们用作构建块来设计更复杂的解决方案