如何同时收听多个键输入

我正在尝试用Java创建一个简单的乒乓球游戏,但我不知道如何让两个玩家同时使用键盘。 游戏不完整,我正在为两位玩家进行划桨运动。 问题是,当玩家按下他们的向上键并向上移动他们的牌时,但如果其他玩家击中他们的任何键,则它取消先前玩家的动作并使桨停止。 我想我需要一种方法来同时处理多个键输入。 这是我的代码,底部的KeyListeners是我需要帮助的地方。 我只是一个1年的Java程序员,所以在我的其余代码上轻松一点。

import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.HashSet; import java.util.Set; public class DrawGame extends JPanel implements ActionListener{ public static final int XPOS = 0; public static final int YPOS = 0; public boolean xFlag = true; // true means ballx is going right public boolean yFlag = true; // true means bally is going down public int ballX = 300; // Ball starting point public int ballY = 400; // Ball starting point Timer ballTimer; // Starts balls animation public int leftScore; public int rightScore; public int rightPadY; // Right players paddle position public int leftPadY; // left players paddle position // Constructor public DrawGame(){ addKeyListener(new RightListener()); addKeyListener(new LeftListener()); leftScore = 0; rightScore = 0; rightPadY = YPOS + 230; leftPadY = YPOS + 230; setBackground(Color.BLACK); setPreferredSize(new Dimension(800, 600)); setFocusable(true); ballTimer = new Timer(10, this); ballTimer.start(); } // Draws game public void paintComponent(Graphics g){ super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; //Drawing Side Boards g2d.setColor(Color.WHITE); g2d.fillRect(XPOS + 5, YPOS + 20, 775, 25); // Top Board g2d.fillRect(XPOS + 5, YPOS + 517, 775, 25); // Bottom board //Drawing the center line g2d.fillRect(XPOS + 377, YPOS + 45 * 1, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 2, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 3, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 4, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 5, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 6, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 7, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 8, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 9, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 10, 25, 25); g2d.fillRect(XPOS + 377, YPOS + 45 * 11, 25, 25); //Drawing the paddles g2d.fillRect(XPOS + 10, leftPadY, 20, 100);// Left g2d.fillRect(XPOS + 755, rightPadY, 20, 100); // Right //Drawing the ball g2d.fillRect(ballX, ballY, 23, 23); //Drawing the score switch(leftScore){ case 0: g2d.fillRect(XPOS + 305, YPOS + 50, 7, 30); g2d.fillRect(XPOS + 325, YPOS + 50, 7, 30); g2d.fillRect(XPOS + 305, YPOS + 50, 25, 7); g2d.fillRect(XPOS + 305, YPOS + 80, 27, 7); break; case 1: g2d.fillRect(XPOS + 325, YPOS + 50, 7, 30); } switch(rightScore){ case 0: g2d.fillRect(XPOS + 450, YPOS + 50, 7, 30); g2d.fillRect(XPOS + 470, YPOS + 50, 7, 30); g2d.fillRect(XPOS + 450, YPOS + 50, 25, 7); g2d.fillRect(XPOS + 450, YPOS + 80, 27, 7); break; case 1: g2d.fillRect(XPOS + 450, YPOS + 50, 7, 30); } } // Controls the animation of the ball public void actionPerformed(ActionEvent e){ if(xFlag == true && ballX >= 735){ ballX += 2; xFlag = false; } else if(xFlag == true){ ballX += 2; } if(xFlag == false && ballX = 500){ ballY += 2; yFlag = false; } else if(yFlag == true){ ballY += 2; } if(yFlag == false && ballY <= 45){ ballY -= 2; yFlag = true; } else if(yFlag == false){ ballY -= 2; } repaint(); ballTimer.restart(); } // Keylistener for right player private class RightListener implements KeyListener{ @Override public synchronized void keyPressed(KeyEvent event) { if(event.getKeyCode() == KeyEvent.VK_UP){ rightPadY -= 5; }else if(event.getKeyCode() == KeyEvent.VK_DOWN){ rightPadY += 5; } repaint(); } @Override public synchronized void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } @Override public synchronized void keyTyped(KeyEvent e) { // TODO Auto-generated method stub } } // Keylistener for left player private class LeftListener implements KeyListener{ @Override public synchronized void keyPressed(KeyEvent event) { if(event.getKeyCode() == KeyEvent.VK_W){ leftPadY -= 5; } else if(event.getKeyCode() == KeyEvent.VK_S){ leftPadY += 5; } repaint(); } @Override public synchronized void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } @Override public synchronized void keyTyped(KeyEvent e) { // TODO Auto-generated method stub } } } 

不要使用KeyListener。 您应该使用Key Bindings

有关详细信息,请参阅使用键盘进行运动

我将以下代码添加到上面链接的KeyboardAnimation示例中,这将允许您执行您想要的操作:

 JLabel label2 = new JLabel( new ColorIcon(Color.GREEN, 40, 40) ); label2.setSize( label2.getPreferredSize() ); label2.setLocation(500, 500); contentPane.add( label2 ); KeyboardAnimation animation2 = new KeyboardAnimation(label2, 24); animation2.addAction("A", -3, 0); animation2.addAction("D", 3, 0); animation2.addAction("W", 0, -3); animation2.addAction("S", 0, 3); 

最好使用线程进行动画制作。 当你按下keyPressed我们会告诉程序密钥已关闭。 在keyReleased我们将告诉程序密钥已启动。 在线程中,我们将读取此值并确定是否要移动。 这也会更顺畅。

首先,您需要在某个类中实现Runnable 。 您甚至可以在那里的主要课程中完成。 添加public void run方法。

在它将是这样的:

 while(true) { if(player1.upkeyIsDown() && player1.downKeyIsUp()) { //move Player1 Up } else if(player1.downKeyIsDown() && player1.upKeyIsUp()) { //move Player1 Down } //do similar for player 2 try{ Thread.sleep(50); } catch(InterruptedException ie) { ie.printStackTrace(); } } 

这是半伪代码,您必须实现如何保存密钥。 在KeyListeners中,您需要在主类中调用一些东西来更改这些值,然后这个线程将处理其余的。

此线程也需要启动。 在你的main / constructor中的某个地方编写new Thread(this).start();