2017-07-03 70 views
0

我正在編寫一個類似於Gradius的簡單遊戲。我有類GameComponent,GameFrame,ShipImpl和一個名爲'Ship'的接口。簡單的Java遊戲:Key Listener/Adapter/keyPressed()不起作用

GameComponent類:

public class GameComponent extends JComponent { 

public Ship ship = new ShipImpl(10, GameFrame.HEIGHT/3); 
private final Timer timer; 

public GameComponent() { 
    requestFocusInWindow(); 
    this.addKeyListener(new ShipKeyListener()); 
    timer = new Timer(1000/60, (a) -> {update();}); 
} 

public void paintComponent(Graphics g) { 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(
       RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     paintComponent(g2); 

} 
private void paintComponent(Graphics2D g) { 
    ship.draw(g); 
} 

public void start() { 
    timer.start(); 
} 

private void update() { 
    ship.move(); 
    repaint(); 
} 

public class ShipKeyListener extends KeyAdapter { 
    public void keyPressed(KeyEvent e) { 
     switch(e.getKeyCode()) { 
      case KeyEvent.VK_UP : 
      case KeyEvent.VK_W : 
      case KeyEvent.VK_NUMPAD8 : 
       ship.setDirection(Ship.Direction.UP); //* changes ship direction 
       break; 
      case KeyEvent.VK_DOWN : 
      case KeyEvent.VK_S : 
      case KeyEvent.VK_NUMPAD2 : 
       ship.setDirection(Ship.Direction.DOWN); //* changes ship direction 
       break; 

      default: 
     } 
    } 
} 

}//end GameComponent 

ShipImpl類:

public class ShipImpl implements Ship { 

private final static Color FILL = Color.GREEN; 
private final static Color BORDER = Color.BLACK; 
private final static int HEIGHT = 20; 
private final static int WIDTH = HEIGHT; 
private final Polygon shape; 
private Direction d; 
private Rectangle2D movementBounds; 

public ShipImpl(int x, int y) { 
    shape = new Polygon(
     new int[] {0,0,WIDTH}, //top left, bottom left, front middle 
     new int[] {0,HEIGHT,HEIGHT/2}, 3); 
    shape.translate(x, y); 
    d = Direction.NONE; 
} 

public void setDirection(Direction dir) { 
    d = dir; 
} 

public void setMovementBounds(Rectangle2D movementBounds) { 
} 

public void move() { 
     if(d != Direction.NONE) { 
      if (d == Direction.UP) { 
       shape.translate(0, -1); 
      } 
      if (d == Direction.DOWN) { 
       shape.translate(0, 1); 
      } 
     } 
} 

public void draw(Graphics2D g) { 
     g.setColor(FILL); 
     g.fillPolygon(shape); 
     g.setColor(BORDER); 
     g.drawPolygon(shape); 
} 
} 

「船舶接口:

public interface Ship extends Sprite { 

    public enum Direction { 
     NONE(0), UP(-1), DOWN(1); 
     public final int dy; 
     Direction(int dy) { 
      this.dy = dy; 
     } 
    }; 

    public void setDirection(Direction d); 
    public void setMovementBounds(Rectangle2D bounds); 
} 

GameFrame類:

public class GameFrame extends JFrame { 

private final static int WIDTH = 900; 
public final static int HEIGHT = 700; 

private final GameComponent comp; 

public GameFrame() { 
    setResizable(false); 
    comp = new GameComponent(); 
    add(comp); 
} 

public static void main(String[] args) { 
    GameFrame frame = new GameFrame(); 
    frame.setSize(WIDTH, HEIGHT); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
    frame.comp.start(); 
} 
} 

程序應運行像這樣:

  1. GameComponent有一個按鍵偵聽器。任何關鍵事件都應該被檢測到。
  2. 當按下上/下鍵或w/s鍵時,應該通過setDirection方法(參見GameComponent類中的*註釋)相應地更改船的方向。
  3. ShipImpl類中的setDirection方法將相應地更改造船對象的方向。
  4. ShipImpl中的move()方法將根據船的當前方向轉換形狀(移動它)。
  5. GameComponent類中的update()方法(通過Timer)將移動船舶並重新繪製遊戲框架(參見update()方法),因此顯示船隻移動。

失敗的運行

在運行遊戲,遊戲中沒有檢測到任何按鍵事件(上/下/ W/S鍵)。我猜測問題是由於以下原因之一:

  1. 我附加了Key Listener不正確。
  2. 我如何實現ShipKeyListener類有一個錯誤。
  3. ShipKeyListener IS正常工作,但我的ShipKeyListener類的keyPressed()方法中的switch case中有錯誤。
  4. 其他

我將不勝感激,我怎麼能解決這個問題的任何建議!

+0

偵聽器添加到的組件必須處於焦點以供偵聽器觸發。 –

+0

@VinceEmigh我在我的GameComponent構造函數中有requestFocusInWindow()。這會工作嗎? – Yee

+1

使用密鑰綁定,而不是KeyListener。即使組件沒有焦點,也可以設置鍵綁定。 – camickr

回答

0

正如Vince Emigh所說的那樣,組件需要專注於傾聽關鍵事件。

在主要方法中加入frame.comp.requestFocus();以下frame.comp.start();應該修復它。

+0

剛剛測試它。仍然不工作:( – Yee

+0

嘗試添加'System.out.println(「UP」)''和'System.out.println(「DOWN」)'在相應情況下的'keyPressed'方法並查看是否獲取控制檯輸出。如果你這樣做,那麼你的問題是不是與關鍵聽衆。 – gommb

+0

你是對的,這不是關鍵聽衆的問題。謝謝你的提示!:) – Yee