突破游戏多键处理 [英] Breakout Game Multiple Key Handling

查看:89
本文介绍了突破游戏多键处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望我的矩形在用户同时按下向左和向右键时停止.我研究了多种键处理方法,但找不到任何东西.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆