突破游戏多键处理 [英] Breakout Game Multiple Key Handling
问题描述
我希望我的矩形在用户同时按下向左和向右键时停止.我研究了多种键处理方法,但找不到任何东西.
i want my rectangle to stop when the user press both left and right key. I researched about multiple key handlings but couldnt manage to find anything.
package View;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GamePanel extends JPanel {
private final int WIDTH = 600, HEIGHT = 500;
// PROPERTIES
private Timer timer;
int x = 0;
int y = 475;
int velX = 0; // only left or right
// CONSTRUCTOR
public GamePanel() {
setSize(WIDTH, HEIGHT);
setBackground(new Color(240, 255, 255));
timer = new Timer(5, new MyTimerListener());
addKeyListener( new MyKeyListener());
setFocusable(true); // for key listening
setFocusTraversalKeysEnabled(false);
timer.start();
}
// METHODS
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor( new Color(201, 51, 51));
g.fillRoundRect(x, y, 80, 20, 15, 15);
}
public class MyTimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if ( x < 0 )
{
velX = 0;
x = 0;
}
if ( x > 520 )
{
velX = 0;
x = 520;
}
x = x + velX;
repaint();
}
}
public class MyKeyListener implements KeyListener {
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if ( code == KeyEvent.VK_LEFT )
velX = -1;
if ( code == KeyEvent.VK_RIGHT )
velX = 1;
}
@Override
public void keyReleased(KeyEvent e) {
velX = 0;
}
@Override
public void keyTyped(KeyEvent e) {}
}
}
感谢heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeelp
thanks for heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeelp
![两个木偶]
推荐答案
因此,再次使用键绑定,而不要使用KeyListener.您可能希望对左右箭头键分别使用单独的绑定来进行键的按下和释放,并且希望让您的按键绑定操作更改程序的状态,从而影响Swing计时器如何移动桨叶.在此示例中(从我的另一个示例中借来的),我创建了一个枚举方向"以封装左右方向,并创建了一个Map<Direction, Boolean>
,它将使布尔值与左右方向相关联.向右箭头键按下将更改地图,以将RIGHT方向与true
布尔值相关联,而释放键将执行相反的操作.计时器将轮询地图以查看将操纵杆移至何处.例如:
So again, use Key Bindings and not a KeyListener. You would want to use separate bindings for key press and release for both right and left arrow keys, and will want to have your key binding actions change the state of your program that will effect how the Swing Timer moves the paddle. In this example here (borrowed from another example of mine), I've created an enum, Direction to encapsulate the right and left directions, and have created a Map<Direction, Boolean>
that will associate a boolean with both right and left directions. A right arrow key press will change the map to associate the RIGHT direction with a true
boolean, and key release would do the opposite. The Timer would poll the Map to see where to move the paddle. For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;
@SuppressWarnings("serial")
public class GamePanel2 extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 500;
private static final int PADDLE_Y = 475;
private static final int PADDLE_W = 80;
private static final int PADDLE_H = 20;
private static final int PADDLE_ARC = 15;
private static final int TIME_DELAY = 15;
public static final int VEL_X = 2;
private static final Color PADDLE_COLOR = new Color(201, 51, 51);
private int paddleX;
private Timer time = new Timer(TIME_DELAY, new TimerListener());
// key presses and releases will change the boolean values held in this Map
// When an arrow key is pressed, the direction-corresponding boolean is set true
// and likewise when the arrow key is released the direction corresponding boolean is false
private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
public GamePanel2() {
setKeyBindings();
time.start();
}
private void setKeyBindings() {
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
// iterate through all the Direction enums
for (Direction direction : Direction.values()) {
// set all values to false
dirMap.put(direction, false);
// create two key strokes, one for pressed and one for released
int keyValue = direction.getKeyValue();
KeyStroke pressedKey = KeyStroke.getKeyStroke(keyValue, 0, false);
KeyStroke releasedKey = KeyStroke.getKeyStroke(keyValue, 0, true);
// create two Actions, one for pressed, one for released
Action pressedAction = new KeyAction(direction, true);
Action releasedAction = new KeyAction(direction, false);
// add keystroke to inputMap and use keystroke's toString as binding link
inputMap.put(pressedKey, pressedKey.toString());
inputMap.put(releasedKey, releasedKey.toString());
// link binding links to our actions
actionMap.put(pressedKey.toString(), pressedAction);
actionMap.put(releasedKey.toString(), releasedAction);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(PADDLE_COLOR);
g.fillRoundRect(paddleX, PADDLE_Y, PADDLE_W, PADDLE_H, PADDLE_ARC, PADDLE_ARC);
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// if JPanel no longer displayed, stop the Timer
if (!GamePanel2.this.isDisplayable()) {
((Timer) e.getSource()).stop();
}
// here's the key: iterate through the Direction enum
for (Direction direction : Direction.values()) {
// get corresponding boolean from dirMap
// and if true, change location of x and y
if (dirMap.get(direction)) {
int possibleX = paddleX + VEL_X * direction.getDeltaX();
if (direction == direction.RIGHT && possibleX + PADDLE_W <= getWidth()) {
paddleX = possibleX;
}
if (direction == Direction.LEFT && possibleX >= 0) {
paddleX = possibleX;
}
}
}
repaint();
}
}
private class KeyAction extends AbstractAction {
private Direction direction;
private boolean pressed;
public KeyAction(Direction direction, boolean pressed) {
this.direction = direction;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
dirMap.put(direction, pressed); // key press simply changes the map, that's it.
}
}
private static void createAndShowGui() {
GamePanel2 mainPanel = new GamePanel2();
JFrame frame = new JFrame("GamePanel2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum Direction {
LEFT("Left", KeyEvent.VK_LEFT, -1),
RIGHT("Right", KeyEvent.VK_RIGHT, 1);
private String text;
private int keyValue; // KeyEvent.VK_?
private int deltaX;
Direction(String text, int keyValue, int deltaX) {
this.text = text;
this.keyValue = keyValue;
this.deltaX = deltaX;
}
public String getText() {
return text;
}
public int getKeyValue() {
return keyValue;
}
@Override
public String toString() {
return text;
}
public int getDeltaX() {
return deltaX;
}
}
这篇关于突破游戏多键处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!