如何减少击键的延迟?

时间:2013-12-09 11:14:10

标签: java swing paintcomponent

我试图制作一个乒乓球游戏,但有一个问题。当我尝试按下键时,程序使用我按下的键之前有一段延迟。我认为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;
}

}

1 个答案:

答案 0 :(得分:1)

我认为延迟是系统的关键重复延迟。您将UpAction和DownAction绑定到KeyStroke.getKeyStroke(keyCode, 0)according to the javadoc是“按键”事件。当您按下该键时,会发生按键事件,然后每次操作系统生成该键的自动重复时都会发生此事件。

每次玩家移动时,不要将speedy = 0移动,而是将该行移动到Player中的单独方法,该方法仅在释放移动键时调用。您可以使用例如KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true)创建单独的密钥发布绑定。