我正在制作一个简单的Snake游戏,除了Key Listener之外,一切似乎都在工作。基于我所看到的一切正确写入。
游戏出现但即使按下箭头键,Snake也不会移动。
提前致谢!
这是主要的:
public class SnakeFrame extends JFrame implements KeyListener{
/**
*
*/
private static final long serialVersionUID = 1L;
private int direction;
private World w;
private WorldComponant wc;
GameLoopThread glt;
public SnakeFrame(){
setSize(420,440);
setTitle("Snake");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
c.setLayout(new BorderLayout());
w = new World();
wc = new WorldComponant(w);
glt = new GameLoopThread(wc);
direction = Direction.SOUTH;
c.add(wc);
}
public static void main(String[] args){
SnakeFrame s = new SnakeFrame();
s.setVisible(true);
}
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case (KeyEvent.VK_UP):{
if(direction!=Direction.SOUTH){
direction = Direction.NORTH;
wc.move(direction);
}
break;
}
case (KeyEvent.VK_DOWN):{
if(direction!=Direction.NORTH){
direction = Direction.SOUTH;
wc.move(direction);
}
break;
}
case (KeyEvent.VK_RIGHT):{
if(direction!=Direction.WEST){
direction = Direction.EAST;
wc.move(direction);
}
break;
}
case (KeyEvent.VK_LEFT):{
if(direction!=Direction.EAST){
direction = Direction.WEST;
wc.move(direction);
}
break;
}
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
这是GameLoopThread:
public class GameLoopThread extends Thread{
private WorldComponant sc;
public GameLoopThread(WorldComponant sc){
this.sc = sc;
}
public void run(){
while(true){
sc.repaint();
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
这是移动方法。它在世界级内部并且也从WorldComponant调用:
public void move(int direction) {
Point head = snake.peekFirst();
Point newPt = head;
switch(direction){
case (Direction.NORTH):{
newPt = new Point(head.x, head.y-1);
break;
}
case (Direction.SOUTH):{
newPt = new Point(head.x, head.y+1);
break;
}
case (Direction.WEST):{
newPt = new Point(head.x-1, head.y);
break;
}
case (Direction.EAST):{
newPt = new Point(head.x+1, head.y);
break;
}
}
snake.remove(snake.peekLast());
if(newPt.equals(food)){
Point addPt = (Point) newPt.clone();
switch(direction){
case (Direction.NORTH):{
newPt = new Point(head.x, head.y-1);
break;
}
case (Direction.SOUTH):{
newPt = new Point(head.x, head.y+1);
break;
}
case (Direction.WEST):{
newPt = new Point(head.x-1, head.y);
break;
}
case (Direction.EAST):{
newPt = new Point(head.x+1, head.y);
break;
}
}
score++;
snake.add(addPt);
placeFood();
}
else if(newPt.x < 0 || newPt.x > gridw - 1){
generateDefaultSnake();
JOptionPane.showMessageDialog(null, "YOU LOST! :(", "Loser!", JOptionPane.ERROR_MESSAGE);
return;
}
else if(newPt.y < 0 || newPt.y > gridh - 1){
generateDefaultSnake();
JOptionPane.showMessageDialog(null, "YOU LOST! :(", "Loser!", JOptionPane.ERROR_MESSAGE);
return;
}
else if(snake.contains(newPt)){
generateDefaultSnake();
JOptionPane.showMessageDialog(null, "YOU LOST! :(", "Loser!", JOptionPane.ERROR_MESSAGE);
return;
}
snake.add(newPt);
}
答案 0 :(得分:0)
在setFocusable(true)
可见后,尝试在requestFocusInWindow()
上致电JFrame
和JFrame
。 (虽然,我认为setFocusable(true)对于JFrame来说并不是必需的。)
答案 1 :(得分:0)
KeyListerner
很麻烦,但在尝试将它们直接添加到JFrame
时更糟糕。 JFrame
在它与用户之间有一个JRootPane
,contentPane
,可能还有一个glassPane
,所有这些都可以窃取焦点并阻止KeyListener
接收关键事件
更好的解决方案是使用密钥绑定api并将其注册到自定义contentPane
有关详细信息,请参阅How to use key bindings