我是java新手,正在尝试创建一个基本游戏,现在正在尝试对玩家类进行编程。然而,当我运行游戏时,只出现 JFRame。这些是我的 thress 类,它们没有显示错误。
import java.awt.Color;
import javax.swing.JFrame;
public class Game extends JFrame {
public
final static int WIDTH = 700, HEIGHT = 450;
public
GamePanel panel;
public Game() {
setSize(WIDTH, HEIGHT);
setTitle("Game");
setBackground(Color.WHITE);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
}
public GamePanel getPanel() {
return panel;
}
public static void main(String[] args) {
new Game();
}
}
import java.awt.Color;
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 javax.swing.JPanel;
public class GamePanel extends JPanel implements ActionListener, KeyListener {
public
Game game;
public
Player player;
public GamePanel(Game game) {
setBackground(Color.GREEN);
this.game = game;
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
addKeyListener(this);
setFocusable(true);
}
public
void update() {
player.update();
}
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
public Player getPlayer(int playerNo) {
return player;
}
public void keyPressed(KeyEvent e) {
player.pressed(e.getKeyCode());
}
public void keyReleased(KeyEvent e) {
player.released(e.getKeyCode());
}
public void keyTyped(KeyEvent e) {
;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
player.paint(g);
}
}
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Color;
public class Player {
public
static final int WIDTH = 50, HEIGHT = 50;
public
Game game;
public
int left, right;
public
int y;
public
int x, xa;
public Player(Game game, int left, int right, int x) {
this.game = game;
this.x = x;
y = game.getHeight() - 20;
this.left = left;
this.right = right;
this.y = y;
x = game.getWidth() - 36;
}
public void update() {
if (x > 0 && x < game.getWidth() - WIDTH - 36)
x += xa;
else if (x == 0)
x++;
else if (x == game.getWidth() - WIDTH - 36)
x--;
}
public void pressed(int keyCode) {
if (keyCode == left)
xa = -1;
else if (keyCode == right)
xa = 1;
}
public void released(int keyCode) {
if (keyCode == left || keyCode == right)
xa = 0;
}
public Rectangle getBounds() {
return new Rectangle(x, y, WIDTH, HEIGHT);
}
public void paint(Graphics g) {
g.fillRect(x, y, WIDTH, HEIGHT);
g.setColor(Color.ORANGE);
}
}
最佳答案
获取setVisible(true);
并将其移至Game
构造函数的最后一个。此外,您还应该确保在构建 UI 时在 EDT 上下文中工作,请参阅 Initial Threads了解更多详情
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game extends JFrame {
public final static int WIDTH = 700, HEIGHT = 450;
public GamePanel panel;
public Game() {
setTitle("Game");
setBackground(Color.WHITE);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
setResizable(false);
setSize(WIDTH, HEIGHT);
setVisible(true);
}
public GamePanel getPanel() {
return panel;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new Game();
}
});
}
}
基本上,Swing 的布局管理是惰性的,它不会尝试更新容器层次结构,直到你告诉它(revalidate
)或者它被实现或调整大小,这是一件好事,因为操作可能会很昂贵。
接下来,看一下 player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
您将播放器的位置设置为比组件 width
少 36
像素,但是当调用此函数时,width
> 将是 0
。
基本上,您需要在进行此类调用之前让 UI“稳定下来”。这其实并不那么容易。您可以使用 ComponentListener
并监视 componentResized
事件,但是窗口在首次初始化时可以多次调整大小,为此,您需要“等待”直到尺寸“确定”,例如......
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
然后您需要更新 GamePanel
以提供 init
方法...
public class GamePanel extends JPanel implements ActionListener, KeyListener {
public Game game;
public Player player;
public GamePanel(Game game) {
setBackground(Color.GREEN);
this.game = game;
addKeyListener(this);
setFocusable(true);
}
public void init() {
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
repaint();
}
//...
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (player != null) {
player.paint(g);
}
}
}
您有各种各样的“神奇”数字,这些数字并不等于您实际想要做的事情,例如......
player = new Player(game, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, game.getWidth() - 36);
不应该是game.getWidth() - Player.WIDTH
吗?
然后在播放器
中...
public Player(Game game, int left, int right, int x) {
this.game = game;
this.x = x;
y = game.getHeight() - 20;
//...
this.y = y;
x = game.getWidth() - 36;
}
您将参数x
分配给字段x
,然后在构造函数末尾更改它?另外,this.y = y
毫无意义!?
现在,我们来谈谈 setSize(WIDTH, HEIGHT);
是一个多么糟糕的主意,它关系到为什么你的播放器没有出现在你想要的位置......
窗口有装饰,因此您的可视区域将始终小于实际窗口尺寸,更糟糕的是,装饰的尺寸是可变的。相反,您应该使用 JFrame#pack
将窗口打包在其内容周围,并让内容提供有关它想要的大小的提示。
看看How can I set in the midst?了解更多详情。
您应该使用pack
...而不是设置框架的大小
public class Game extends JFrame {
public GamePanel panel;
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
setTitle("Game");
setBackground(Color.WHITE);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
setResizable(false);
pack();
setVisible(true);
}
并允许 GamePanel 决定它想要多大......
public static class GamePanel extends JPanel implements ActionListener, KeyListener {
public final static int WIDTH = 700, HEIGHT = 450;
public Game game;
public Player player;
public GamePanel(Game game) {
setBackground(Color.GREEN);
this.game = game;
addKeyListener(this);
setFocusable(true);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
这也意味着您不应将 Game
传递给您的对象,而应该将 GamePanel
传递给它们并使用其尺寸,例如...
public static class Player {
//...
public Player(GamePanel game, int left, int right, int x) {
this.game = game;
this.left = left;
this.right = right;
this.x = x;
y = game.getHeight() - HEIGHT;
}
您也不应该使用 KeyListener
而应该使用 Key Bindings API相反,这将解决与焦点相关的问题并使配置击键变得更容易
基本上,您缺少对 Swing 框架如何工作的一些核心理解,这会导致无穷无尽的问题,在深入研究像游戏这样复杂的内容之前,我会花时间了解更多有关该框架一般如何工作的信息发展
可运行示例...
现在,因为我基本上已经修改了你的代码以使其正常工作......
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game extends JFrame {
public GamePanel panel;
public Game() {
addComponentListener(new ComponentAdapter() {
private boolean initalised = false;
private Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initalised = true;
panel.init();
timer.stop();
}
});
@Override
public void componentResized(ComponentEvent e) {
if (!initalised) {
timer.restart();
}
}
});
setTitle("Game");
setBackground(Color.WHITE);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new GamePanel(this);
add(panel);
setResizable(false);
pack();
setVisible(true);
}
public GamePanel getPanel() {
return panel;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new Game();
}
});
}
public static class GamePanel extends JPanel implements ActionListener, KeyListener {
public final static int WIDTH = 700, HEIGHT = 450;
public Game game;
public Player player;
public GamePanel(Game game) {
setBackground(Color.GREEN);
this.game = game;
addKeyListener(this);
setFocusable(true);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
public void init() {
System.out.println("!!");
player = new Player(this, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, getWidth() - 50);
repaint();
}
public void update() {
player.update();
}
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
public Player getPlayer(int playerNo) {
return player;
}
public void keyPressed(KeyEvent e) {
player.pressed(e.getKeyCode());
}
public void keyReleased(KeyEvent e) {
player.released(e.getKeyCode());
}
public void keyTyped(KeyEvent e) {
;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (player != null) {
player.paint(g);
}
}
}
public static class Player {
public static final int WIDTH = 50, HEIGHT = 50;
public GamePanel game;
public int left, right;
public int y;
public int x, xa;
public Player(GamePanel game, int left, int right, int x) {
this.game = game;
this.left = left;
this.right = right;
this.x = x;
y = game.getHeight() - HEIGHT;
}
public void update() {
if (x > 0 && x < game.getWidth() - WIDTH - 36) {
x += xa;
} else if (x == 0) {
x++;
} else if (x == game.getWidth() - WIDTH - 36) {
x--;
}
}
public void pressed(int keyCode) {
if (keyCode == left) {
xa = -1;
} else if (keyCode == right) {
xa = 1;
}
}
public void released(int keyCode) {
if (keyCode == left || keyCode == right) {
xa = 0;
}
}
public Rectangle getBounds() {
return new Rectangle(x, y, WIDTH, HEIGHT);
}
public void paint(Graphics g) {
System.out.println(x + "x" + y);
g.fillRect(x, y, WIDTH, HEIGHT);
g.setColor(Color.ORANGE);
}
}
}
关于java - 在 JFrame 中没有看到矩形 Player 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36191150/