Проблема с задержкой привязки ключа Java

Я использую привязки клавиш для прослушивания клавиш, программа просто слушает стрелку влево и вправо для перемещения изображения (я делаю Space Invaders). Однако есть небольшая задержка в ответе, от которой я хотел бы избавиться. Я читал об этом, но видел только много расплывчатых ответов. Кажется, многие люди говорят, что нужно установить логическое значение для нажатия или отпускания клавиши, прослушивать его в игровом цикле и действовать в соответствии с логическим значением. Я пробовал это, но я получаю те же результаты. Любые предложения или примеры того, как решить эту проблему?

Вот мой код

public class Board extends JPanel implements ActionListener{

    Timer timer;
    Tank tank;
    MoveRight moveRight;
    MoveLeft moveLeft;
    releaseMoveRight releasemoveRight;
    releaseMoveLeft releasemoveLeft;
    int tankdx = 0;
    boolean rightKeyDown;
    boolean leftKeyDown;

    boolean boardset;

    public Board(){
        setBackground(Color.BLACK);

        ImageIcon alien1ii = new ImageIcon(
            this.getClass().getResource("si_Alien1.png"));
        Image alien1 = alien1ii.getImage();
        ImageIcon alien2ii = new ImageIcon(
            this.getClass().getResource("si_Alien2.png"));
        Image alien2 = alien2ii.getImage();
        ImageIcon alien3ii = new ImageIcon(
            this.getClass().getResource("si_Alien3.png"));
        Image alien3 = alien3ii.getImage();

        timer = new Timer(5, this);
        timer.start();
        tank = new Tank();

        moveRight = new MoveRight();
        moveLeft = new MoveLeft();
        releasemoveRight = new releaseMoveRight();
        releasemoveLeft = new releaseMoveLeft();


        // keys--------------------------------------
        // Right pressed
        // panel is the JPanel, .put(define key,
        // followed by String doEnterAction, used to  
        // pair to AbstractAction
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke("RIGHT"), "moveRight");
        //pairs String pair from input map with abstract action
        getActionMap().put("moveRight", moveRight);
        //Right released
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
            KeyStroke.getKeyStroke("released RIGHT"), "releasemoveRight");
        getActionMap().put("releasemoveRight", releasemoveRight);

        //Left pressed
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                    KeyStroke.getKeyStroke("LEFT"), "moveLeft");
        getActionMap().put("moveLeft", moveLeft);
        //Left released
        getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
            KeyStroke.getKeyStroke("released LEFT"), "releasemoveLeft");
        getActionMap().put("releasemoveLeft", releasemoveLeft);

        //Button in Game----------------------------------------------
        JButton button = new JButton(new AbstractAction("hello2"){
            @Override
            public void actionPerformed(ActionEvent e){
                boardset = false;
            }
        }); 
        this.add(button);

        //actual game (kinda)-----------------------------------------
        setFocusable(true);
        setDoubleBuffered(true);
    }

    //draw stuff------------------------------------------------------
    public void paint(Graphics g){
        super.paint(g);
        g.setColor(Color.WHITE);

        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(tank.getTank(), tank.getx(), tank.getY(), this);

        g2d.drawLine(0, (tank.getY()+25), 400, (tank.getY()+25));

        Toolkit.getDefaultToolkit().sync();     
        g.dispose();
    }

    public void setBoardset(boolean x){
        boardset = x;
    }

    public boolean getBoardset(){
        return boardset;
    }

    //keybinding actions------------------------------------------
    public class MoveRight extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {    
            rightKeyDown = true;
            tankdx = 1;
        }       
    }

    public class releaseMoveRight extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {    
            rightKeyDown = false;
            tankdx = 0;
        }       
    }

    public class MoveLeft extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {
            leftKeyDown = true;
            tankdx = -1;
        }       
    }

    public class releaseMoveLeft extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {
            leftKeyDown = false;
            tankdx = 0;
        }       
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
        if(leftKeyDown || rightKeyDown){
            tank.move(tankdx);
        }
    }   
}

Вот класс танков

public class Tank {

    int x = 180;
    int y = 320;
    int dx;
    int tankSpeed;

    ImageIcon tankii = new ImageIcon(this.getClass().getResource("si_Tank.png"));
    Image tank = tankii.getImage(); 

    public Image getTank(){
        return tank;
    }

    public int getx(){
        return x;
    }

    public int getY(){
        return y;
    }

    public void move(int dx){
        x += dx;
    }   
}

Еще одна вещь, которую я должен упомянуть, я почти уверен, что задержка - это ОС, из того, что я читал, я не уверен. Задержка не происходит, когда вы нажимаете одну клавишу. Или, если вы удерживаете вправо, а затем нажимаете влево, он будет двигаться влево без задержки. Кажется, задержка возникает только тогда, когда вы удерживаете одно направление, отпускаете его и нажимаете другое направление примерно в то же время, когда возникает эта задержка.

Если у кого-то есть какие-либо предложения, это будет оценено. Спасибо


person Corey    schedule 03.08.2013    source источник
comment
На этом сайте уже был дан ответ с одним похожим вопросом здесь: Java KeyListener заикается.   -  person Hovercraft Full Of Eels    schedule 03.08.2013