2017-03-25 21 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); 
     } 

    } 

}