有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java突破游戏多键处理

当用户同时按下左键和右键时,我希望我的矩形停止。我研究了多个键处理,但没有找到任何东西

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) {}             
}   
}

谢谢你的帮助

a busy cat ![两个布偶]


共 (1) 个答案

  1. # 1 楼答案

    所以再次强调,使用键绑定,而不是键侦听器。您可能希望对左右箭头键的按键和释放使用单独的绑定,并且希望您的按键绑定操作更改程序的状态,从而影响摆动计时器移动拨杆的方式。在这个例子中(借用了我的另一个例子),我创建了一个enum,Direction来封装右方向和左方向,并创建了一个Map<Direction, Boolean>来将布尔值与右方向和左方向相关联。按向右箭头键将更改地图,使其将向右方向与true布尔值相关联,松开键则会执行相反的操作。计时器会对地图进行轮询,查看将划桨移动到哪里。例如:

    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;
       }
    }