我正在編寫一個類似於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();
}
}
程序應運行像這樣:
- GameComponent有一個按鍵偵聽器。任何關鍵事件都應該被檢測到。
- 當按下上/下鍵或w/s鍵時,應該通過setDirection方法(參見GameComponent類中的*註釋)相應地更改船的方向。
- ShipImpl類中的setDirection方法將相應地更改造船對象的方向。
- ShipImpl中的move()方法將根據船的當前方向轉換形狀(移動它)。
- GameComponent類中的update()方法(通過Timer)將移動船舶並重新繪製遊戲框架(參見update()方法),因此顯示船隻移動。
失敗的運行
在運行遊戲,遊戲中沒有檢測到任何按鍵事件(上/下/ W/S鍵)。我猜測問題是由於以下原因之一:
- 我附加了Key Listener不正確。
- 我如何實現ShipKeyListener類有一個錯誤。
- ShipKeyListener IS正常工作,但我的ShipKeyListener類的keyPressed()方法中的switch case中有錯誤。
- 其他
我將不勝感激,我怎麼能解決這個問題的任何建議!
偵聽器添加到的組件必須處於焦點以供偵聽器觸發。 –
@VinceEmigh我在我的GameComponent構造函數中有requestFocusInWindow()。這會工作嗎? – Yee
使用密鑰綁定,而不是KeyListener。即使組件沒有焦點,也可以設置鍵綁定。 – camickr