2017-03-25 118 views
0

我是Java編程新手,已經開始編寫遊戲。我有一個角色隨着wasd移動,但發現時:未找到Java密鑰版本?

  1. 移動鍵被按下。
  2. JFrame點擊離開。 (所以它變得沒有重點。)
  3. 相同的密鑰被釋放。
  4. JFrame重新聚焦。

......遊戲不會撿起玩家不應該移動的東西。所以,我想通過改變所有的按鍵排列爲false來解決它:

public class KeyManager implements KeyListener { 

private Game game; 

private boolean[] keys; 
public boolean up, down, left, right; //Player class reads these variables 

public KeyManager(Game game) { 
    this.game = game; 
    keys = new boolean[256]; 
} 

public void tick() { 
    if(!game.getDisplay().getFrame().isFocused()) { //Here is the problem 
     for(int i = 0; i < keys.length; i++) { 
      keys[i] = false; //Repeats 256 x 60 times a second 
     } 
    } 
    up = keys[KeyEvent.VK_W]; //I realize that I could just change 
    down = keys[KeyEvent.VK_S]; //up, down, left, right to false but 
    left = keys[KeyEvent.VK_A]; //when the JFrame is refocused the game 
    right = keys[KeyEvent.VK_D]; //still doesn't know the key was released 
} 

@Override 
public void keyPressed(KeyEvent e) { 
    keys[e.getKeyCode()] = true; 
} 

@Override 
public void keyReleased(KeyEvent e) { 
    keys[e.getKeyCode()] = false; 
} 

@Override 
public void keyTyped(KeyEvent e) { 

} 

} 

它的工作,但想在代碼後,我意識到,由於該記號()方法被調用60次的速率和按鍵陣列長度爲256個密鑰,因此每秒只更新15,900個關鍵布爾值,只有4個重要密鑰需要更改爲false。

什麼是最有效的方法來做到這一點?我覺得我錯過了很簡單的事情。

+0

這可能是有益的:http://rahalsblogs.blogspot.com/2015/08/how-to-use-keyeventdispatcher-with.html –

+0

使用的鍵綁定的API,它不是關鍵監聽 – MadProgrammer

+0

我「可能「的做法是使用鍵綁定API來設置」鍵「標誌的狀態,然後這些標誌將獨立於遊戲循環。然後,我會在'JFrame'上使用'FocusListener'來(可能)暫停遊戲並重置鍵標誌 – MadProgrammer

回答

1

我會做的第一件事就是使用Key Bindings API而不是KeyListener。我會更新關鍵標誌(個人,我會使用Set和某種類型的Inputenum,但這就是我),而不是「遊戲循環」。

我會再上JFrame使用FocusListener和簡單的暫停/恢復「遊戲圈」丟失焦點時/上漲,可選復位鍵標誌

這樣的事情,例如...

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       TestPane tp = new TestPane(); 
       frame.addFocusListener(new FocusListener() { 
        @Override 
        public void focusGained(FocusEvent e) { 
         tp.resume(); 
        } 

        @Override 
        public void focusLost(FocusEvent e) { 
         tp.pause(true); 
        } 
       }); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(tp); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private boolean aPressed = false; 
     private Timer timer; 

     public TestPane() { 
      InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
      ActionMap actionMap = getActionMap(); 

      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "A.pressed"); 
      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "A.released"); 
      actionMap.put("A.pressed", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        aPressed = true; 
       } 
      }); 
      actionMap.put("A.released", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        aPressed = false; 
       } 
      }); 

      timer = new Timer(16, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        System.out.println("A pressed = " + aPressed); 
       } 
      }); 
     } 

     public void resume() { 
      timer.restart(); 
     } 

     public void pause(boolean reset) { 
      timer.stop(); 
      if (reset) { 
       aPressed = false; 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

    } 

}