我试图制作一个乒乓球游戏,但有一个问题。当我尝试按下键时,程序使用我按下的键之前有一段延迟。我认为KeyBindings中的问题因为如果我使用计时器200ms,没有延迟
PingPong.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.ArrayList;
public class PingPong{
JFrame theFrame;//главное окно
MyPanel myPanel;//окно с игрой,в котором все рисуется
boolean drawCell=true;
int speed =90; //скорость таймера,по которому происхоит перерисовка
int width =600;//ширина и высота в пикселях
int height=400;
int wLength=20;//ширина x
int hLength=20;//длина y
int maxWidth = width/wLength;//колво квадратов ширины
int maxHeight = height/hLength; //кол-во квадратов в высоте
public static void main(String[] args){
PingPong game= new PingPong();
game.start();
}
private void start(){
buildGui();
myPanel.game();
}
private void buildGui(){
theFrame = new JFrame("PingPong");
theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theFrame.setResizable(false);
theFrame.setVisible(true);
theFrame.setBackground(Color.BLACK);
theFrame.setSize(width+6,height+29);
myPanel = new MyPanel();
theFrame.getContentPane().add(myPanel);
}
class MyPanel extends JPanel implements ActionListener{//переопределяем панель для поля сдесь рисуем и все действиея связанные с игрой
class UpAction extends AbstractAction{
Player player=new Player();
public UpAction(Player player0)
{
player = player0;
}
public void actionPerformed(ActionEvent e)
{
player.up();
}
}
class DownAction extends AbstractAction{
Player player=new Player();
public DownAction(Player player0)
{
player = player0;
}
public void actionPerformed(ActionEvent e)
{
player.down();
}
}
Timer t = new Timer(speed, this);
Ball ball = new Ball(width/2,height/2,1,1,width,height);
Player player1 = new Player(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0),
KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0),width-20,height/2);
Player player2 = new Player(KeyStroke.getKeyStroke(KeyEvent.VK_W,0),
KeyStroke.getKeyStroke(KeyEvent.VK_S,0),0,height/2) ;
public void game(){
addBindings();
t.start();
}
protected void addBindings() {//добавляем клавиши!Когда клавиша нажата вызывается инпут
InputMap im =getInputMap(WHEN_IN_FOCUSED_WINDOW);//который ишет значения в актионмапе
ActionMap am = getActionMap();
im.put(player1.keyUp,"player1Up");
UpAction player1up = new UpAction(player1);
am.put("player1Up",player1up);
im.put(player2.keyUp,"player2Up");
UpAction player2up = new UpAction(player2);
am.put("player2Up",player2up);
im.put(player1.keyDown,"player1Down");
DownAction player1down = new DownAction(player1);
am.put("player1Down",player1down);
im.put(player2.keyDown,"player2Down");
DownAction player2down = new DownAction(player2);
am.put("player2Down",player2down);
}
public void actionPerformed(ActionEvent e){//действие по тику таймера
player1.PlayerTurn();
player2.PlayerTurn();
ball.nextTurnBall();
repaint();
}
public void paintComponent(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0,0,width,height);
g.fillOval(ball.x-ball.speedx,ball.y-ball.speedy,ball.rad,ball.rad);
if (drawCell){
g.setColor(Color.GRAY);
for (int i=0; i<=maxWidth;i++){
g.drawLine(i*wLength,0,i*wLength,height);
}
for (int i=0; i<=maxHeight;i++){
g.drawLine(0,i*hLength,width,i*hLength);
}
g.setColor(Color.YELLOW);
g.fillOval(ball.x,ball.y,ball.rad,ball.rad);
}
g.setColor(Color.WHITE);
g.fillRect(player1.x,player1.y,player1.width,player1.height);
g.fillRect(player2.x,player2.y,player2.width,player2.height);
}
}
}
Player.java
import javax.swing.*;
import java.awt.event.*;
public class Player{
KeyStroke keyUp = KeyStroke.getKeyStroke(KeyEvent.VK_UP,0);
KeyStroke keyDown = KeyStroke.getKeyStroke(KeyEvent.VK_UP,0);
int x=0;
int y=0;
int width=20;
int height=80;
int speedy=0;
public Player(KeyStroke keyUp0,KeyStroke keyDown0,int x0,int y0,int width0,int height0){
keyUp=keyUp0;
keyDown=keyDown0;
x=x0;
y=y0;
width=width0;
height=height0;
}
public Player()
{
}
public Player(KeyStroke keyUp0,KeyStroke keyDown0,int x0,int y0){
keyUp=keyUp0;
keyDown=keyDown0;
x=x0;
y=y0;
}
public void up(){
speedy=-4;
}
public void down(){
speedy=4;
}
public void PlayerTurn(){
y += speedy;
speedy=0;
}
}
答案 0 :(得分:1)
我认为延迟是系统的关键重复延迟。您将UpAction和DownAction绑定到KeyStroke.getKeyStroke(keyCode, 0)
,according to the javadoc是“按键”事件。当您按下该键时,会发生按键事件,然后每次操作系统生成该键的自动重复时都会发生此事件。
每次玩家移动时,不要将speedy = 0移动,而是将该行移动到Player中的单独方法,该方法仅在释放移动键时调用。您可以使用例如KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true)
创建单独的密钥发布绑定。