如何使用 Key Bindings 而不是 Key Listener?
How to use Key Bindings instead of Key Listener?
所以我正在制作一款破砖游戏。我使用按键侦听器让桨移动,但是我得到了一些使用按键绑定的建议。我一直在阅读和到处寻找这个,我想我有点明白了,但实施让我有点困惑。
对于我的球拍,我是用 paint 组件创建的。因此,这就是我希望能够使用箭头键左右移动的内容。但是,我发现的所有键绑定解释似乎都使用了 JComponent,而桨不是。有没有办法解决这个问题,还是我必须让我的桨变成一个 JComponent 图像图标?如果是这样,我可以将图像加载到我的 Paddle class 吗?
此外,构建我的代码以包含键绑定的最佳方式是什么?例如,我最好为它创建一个全新的 class ,还是把它放在例如我的游戏面板 class
有什么建议吗?
这是我的一些代码,您可以了解一下:
主要Class:
public class BrickBreakerGameApp {
public static void main(String[] args) {
int pw = 500;
int ph = 900;
GamePanel gPanel = new GamePanel(pw,ph);
GameFrame gFrame = new GameFrame();
gFrame.getContentPane().add(gPanel); //add game panel to frame
// gFrame.addKeyListener(gPanel); //adds the key listener for the game panel frame
gFrame.pack();
gFrame.setVisible(true); //make frame visible
}
}
游戏框架class:
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
//Global Variables
public int frameWidth = 500;
public int frameHeight = 800;
//create constructor
GameFrame () {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //so app closes properly
this.setPreferredSize(new Dimension(frameWidth, frameHeight)); //set frame size
this.setTitle("Brick Breaker Game");
ImageIcon icon = new ImageIcon("res/brick-breaker-logo.jpg"); //create image icon
this.setIconImage(icon.getImage()); //update frame icon
this.pack();
}
}
游戏面板Class
import java.awt.Color;
import java.awt.event.*;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.*;
/**
* This class handles the game panel as a whole
*/
public class GamePanel extends JPanel {
// Global Variables
private Ball ball;
private Paddle paddle;
private Bricks bricks;
private GameFrame gameFrame;
private int width;
private int height;
private int[] bArray = new int[20];
// create a constructor
GamePanel (int gamePanelWidth, int gamePanelHeight) {
this.setWidth(gamePanelWidth);
this.setHeight(gamePanelHeight);
initialiseGame();
this.isVisible();
}
private void initialiseGame() {
ball = new Ball(10, 520, 30, 30); //create the ball object
paddle = new Paddle(this, 50, 700, 100, 10); //creates paddle object
bricks = new Bricks(10, 10, 60, 30, bArray); //creates the bricks object
//for key binding initialisation
MotionAction motion = new MotionAction(paddle, 24);
}
// paint all the elements in
public void paintComponent(Graphics g) {
super.paintComponent(g);
// background
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
// paddle
// g.setColor(Color.CYAN);
// g.fillRect(paddle.getPaddleX(), paddle.getPaddleY(), paddle.getPaddleWidth(), paddle.getPaddleHeight());
// ball
g.setColor(Color.MAGENTA);
g.fillOval(ball.getBallX(), ball.getBallY(), ball.getBallWidth(), ball.getBallHeight());
// brick
g.setColor(Color.GREEN);
g.fillRect(bricks.getBrickX(), bricks.getBrickY(), bricks.getBrickWidth(), bricks.getBrickHeight());
}
//add any unimplemented methods because we are using an interface
/* @Override
public void actionPerformed(ActionEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
paddle.moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
paddle.moveRight();
}
this.repaint();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
} */
//create get and set methods for all panel attributes
public int getWidth() {
return width;
}
public void setWidth(int pWidth) {
this.width = pWidth;
}
public int getHeight() {
return height;
}
public void setHeight(int pHeight) {
this.height = pHeight;
}
}
桨 class:
import javax.swing.AbstractAction;
import java.awt.event.*;
public class Paddle extends AbstractAction implements ActionListener {
//Global Variables
private int paddleWidth;
private int paddleHeight;
private int paddleX; //paddle x position
private int paddleY;
private GamePanel gamePanel;
//create paddle constructor
Paddle() {
}
//create a paddle constructor based off parameters
Paddle(GamePanel gPanel, int pX, int pY, int pWidth, int pHeight) {
//set the values
this.setPaddleWidth(pWidth);
this.setPaddleHeight(pHeight);
this.setPaddleX(pX);
this.setPaddleY(pY);
this.setGamePanel(gPanel);
}
//create get and set methods for all paddle attributes
public int getPaddleWidth() {
return paddleWidth;
}
public void setPaddleWidth(int pWidth) {
this.paddleWidth = pWidth;
}
public int getPaddleHeight() {
return paddleHeight;
}
public void setPaddleHeight(int pHeight) {
this.paddleHeight = pHeight;
}
public int getPaddleX() {
return paddleX;
}
public void setPaddleX(int pX) {
this.paddleX = pX;
}
public int getPaddleY() {
return paddleY;
}
public void setPaddleY(int pY) {
this.paddleY = pY;
}
public GamePanel getGamePanel() {
return gamePanel;
}
public void setGamePanel(GamePanel gPanel) {
this.gamePanel = gPanel;
}
//move the paddle left if it is not already positoned at 0 (far left)
public void moveLeft() {
try {
if(getPaddleX() <= 0) {
setPaddleX(0);
System.out.println("less than 0, x: " + getPaddleX());
}
else if (getPaddleX() > 0) {
setPaddleX(getPaddleX()-10); //to move paddle left -10
// gamePanel.repaint(getPaddleX()+10, getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint old position
// gamePanel.repaint(getPaddleX(), getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint new position
System.out.println("left, x: " + getPaddleX());
}
}
catch (Exception e) {
}
}
//move the paddle right if it is not already positioned to the far right of the panel
public void moveRight() {
if(getPaddleX() >= gamePanel.getWidth() - getPaddleWidth()) { //dont move the paddle if it is on the right edge of the panel
setPaddleX(gamePanel.getWidth() - getPaddleWidth());
System.out.println("right1, x:" + getPaddleX());
}
else if ((getPaddleX()+getPaddleWidth()) <= gamePanel.getWidth()){ //if the paddle is within the panel bounds
setPaddleX(getPaddleX() + 10); //to move paddle right +10
System.out.println("right, x:" + getPaddleX());
}
}
}
以下是我尝试使用的一些主要资源:
这个我试过了,但对将它集成到我自己的代码中的最佳方式感到非常困惑 --> https://tips4java.wordpress.com/2013/06/09/motion-using-the-keyboard/
这个我试过了,直到我意识到我没有 jcomponent --> https://coderanch.com/t/606742/java/key-bindings
您可以向 GamePanel 或框架内容窗格(均从 JComponent 扩展)注册键绑定。例如:
public class DemoFrame extends JFrame {
public static void main(String[] args) throws Exception {
new DemoFrame().setVisible(true);
}
public DemoFrame() {
setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
{
String actionId = "left";
KeyStroke keyStroke = KeyStroke.getKeyStroke("LEFT");
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, actionId);
getRootPane().getActionMap().put(actionId, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
actionLeft();
}
});
}
}
private void actionLeft() {
System.out.println("left");
}
}
所以我正在制作一款破砖游戏。我使用按键侦听器让桨移动,但是我得到了一些使用按键绑定的建议。我一直在阅读和到处寻找这个,我想我有点明白了,但实施让我有点困惑。
对于我的球拍,我是用 paint 组件创建的。因此,这就是我希望能够使用箭头键左右移动的内容。但是,我发现的所有键绑定解释似乎都使用了 JComponent,而桨不是。有没有办法解决这个问题,还是我必须让我的桨变成一个 JComponent 图像图标?如果是这样,我可以将图像加载到我的 Paddle class 吗?
此外,构建我的代码以包含键绑定的最佳方式是什么?例如,我最好为它创建一个全新的 class ,还是把它放在例如我的游戏面板 class
有什么建议吗?
这是我的一些代码,您可以了解一下:
主要Class:
public class BrickBreakerGameApp {
public static void main(String[] args) {
int pw = 500;
int ph = 900;
GamePanel gPanel = new GamePanel(pw,ph);
GameFrame gFrame = new GameFrame();
gFrame.getContentPane().add(gPanel); //add game panel to frame
// gFrame.addKeyListener(gPanel); //adds the key listener for the game panel frame
gFrame.pack();
gFrame.setVisible(true); //make frame visible
}
}
游戏框架class:
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
//Global Variables
public int frameWidth = 500;
public int frameHeight = 800;
//create constructor
GameFrame () {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //so app closes properly
this.setPreferredSize(new Dimension(frameWidth, frameHeight)); //set frame size
this.setTitle("Brick Breaker Game");
ImageIcon icon = new ImageIcon("res/brick-breaker-logo.jpg"); //create image icon
this.setIconImage(icon.getImage()); //update frame icon
this.pack();
}
}
游戏面板Class
import java.awt.Color;
import java.awt.event.*;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.*;
/**
* This class handles the game panel as a whole
*/
public class GamePanel extends JPanel {
// Global Variables
private Ball ball;
private Paddle paddle;
private Bricks bricks;
private GameFrame gameFrame;
private int width;
private int height;
private int[] bArray = new int[20];
// create a constructor
GamePanel (int gamePanelWidth, int gamePanelHeight) {
this.setWidth(gamePanelWidth);
this.setHeight(gamePanelHeight);
initialiseGame();
this.isVisible();
}
private void initialiseGame() {
ball = new Ball(10, 520, 30, 30); //create the ball object
paddle = new Paddle(this, 50, 700, 100, 10); //creates paddle object
bricks = new Bricks(10, 10, 60, 30, bArray); //creates the bricks object
//for key binding initialisation
MotionAction motion = new MotionAction(paddle, 24);
}
// paint all the elements in
public void paintComponent(Graphics g) {
super.paintComponent(g);
// background
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
// paddle
// g.setColor(Color.CYAN);
// g.fillRect(paddle.getPaddleX(), paddle.getPaddleY(), paddle.getPaddleWidth(), paddle.getPaddleHeight());
// ball
g.setColor(Color.MAGENTA);
g.fillOval(ball.getBallX(), ball.getBallY(), ball.getBallWidth(), ball.getBallHeight());
// brick
g.setColor(Color.GREEN);
g.fillRect(bricks.getBrickX(), bricks.getBrickY(), bricks.getBrickWidth(), bricks.getBrickHeight());
}
//add any unimplemented methods because we are using an interface
/* @Override
public void actionPerformed(ActionEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
paddle.moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
paddle.moveRight();
}
this.repaint();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
} */
//create get and set methods for all panel attributes
public int getWidth() {
return width;
}
public void setWidth(int pWidth) {
this.width = pWidth;
}
public int getHeight() {
return height;
}
public void setHeight(int pHeight) {
this.height = pHeight;
}
}
桨 class:
import javax.swing.AbstractAction;
import java.awt.event.*;
public class Paddle extends AbstractAction implements ActionListener {
//Global Variables
private int paddleWidth;
private int paddleHeight;
private int paddleX; //paddle x position
private int paddleY;
private GamePanel gamePanel;
//create paddle constructor
Paddle() {
}
//create a paddle constructor based off parameters
Paddle(GamePanel gPanel, int pX, int pY, int pWidth, int pHeight) {
//set the values
this.setPaddleWidth(pWidth);
this.setPaddleHeight(pHeight);
this.setPaddleX(pX);
this.setPaddleY(pY);
this.setGamePanel(gPanel);
}
//create get and set methods for all paddle attributes
public int getPaddleWidth() {
return paddleWidth;
}
public void setPaddleWidth(int pWidth) {
this.paddleWidth = pWidth;
}
public int getPaddleHeight() {
return paddleHeight;
}
public void setPaddleHeight(int pHeight) {
this.paddleHeight = pHeight;
}
public int getPaddleX() {
return paddleX;
}
public void setPaddleX(int pX) {
this.paddleX = pX;
}
public int getPaddleY() {
return paddleY;
}
public void setPaddleY(int pY) {
this.paddleY = pY;
}
public GamePanel getGamePanel() {
return gamePanel;
}
public void setGamePanel(GamePanel gPanel) {
this.gamePanel = gPanel;
}
//move the paddle left if it is not already positoned at 0 (far left)
public void moveLeft() {
try {
if(getPaddleX() <= 0) {
setPaddleX(0);
System.out.println("less than 0, x: " + getPaddleX());
}
else if (getPaddleX() > 0) {
setPaddleX(getPaddleX()-10); //to move paddle left -10
// gamePanel.repaint(getPaddleX()+10, getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint old position
// gamePanel.repaint(getPaddleX(), getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint new position
System.out.println("left, x: " + getPaddleX());
}
}
catch (Exception e) {
}
}
//move the paddle right if it is not already positioned to the far right of the panel
public void moveRight() {
if(getPaddleX() >= gamePanel.getWidth() - getPaddleWidth()) { //dont move the paddle if it is on the right edge of the panel
setPaddleX(gamePanel.getWidth() - getPaddleWidth());
System.out.println("right1, x:" + getPaddleX());
}
else if ((getPaddleX()+getPaddleWidth()) <= gamePanel.getWidth()){ //if the paddle is within the panel bounds
setPaddleX(getPaddleX() + 10); //to move paddle right +10
System.out.println("right, x:" + getPaddleX());
}
}
}
以下是我尝试使用的一些主要资源: 这个我试过了,但对将它集成到我自己的代码中的最佳方式感到非常困惑 --> https://tips4java.wordpress.com/2013/06/09/motion-using-the-keyboard/
这个我试过了,直到我意识到我没有 jcomponent --> https://coderanch.com/t/606742/java/key-bindings
您可以向 GamePanel 或框架内容窗格(均从 JComponent 扩展)注册键绑定。例如:
public class DemoFrame extends JFrame {
public static void main(String[] args) throws Exception {
new DemoFrame().setVisible(true);
}
public DemoFrame() {
setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
{
String actionId = "left";
KeyStroke keyStroke = KeyStroke.getKeyStroke("LEFT");
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, actionId);
getRootPane().getActionMap().put(actionId, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
actionLeft();
}
});
}
}
private void actionLeft() {
System.out.println("left");
}
}