首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 遊戲開發:KeyListener 實現鍵盤多鍵同時按下斜向移動

     編輯:程式設計疑難解答

需求分析

在 Java 圖形界面 (Swing/AWT) 遊戲中,實現角色移動控制:

  • 單按 W (上)、A (左)、S (下)、D (右) → 直向移動
  • 同時按下 W+A、W+D 等組合 → 斜向移動

核心難點:KeyEvent 的單一性

KeyListener 的 keyPressed/keyReleased 是**單獨**觸發的,無法直接感知「同時按下」。必須**自行維護按鍵狀態集合**。

標準解決方案:按鍵狀態集合 + 遊戲迴圈輪詢

1. 定義按鍵狀態容器

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;

public class GameKeyListener extends KeyAdapter {
    // 使用 Set 存儲當前按下的鍵碼,自動去重,查詢 O(1)
    private final Set pressedKeys = new HashSet<>();

    @Override
    public void keyPressed(KeyEvent e) {
        pressedKeys.add(e.getKeyCode());
    }

    @Override
    public void keyReleased(KeyEvent e) {
        pressedKeys.remove(e.getKeyCode());
    }

    // 提供查詢方法
    public boolean isPressed(int keyCode) {
        return pressedKeys.contains(keyCode);
    }
    
    // 獲取當前移動向量 (dx, dy)
    public Point getMoveVector() {
        int dx = 0, dy = 0;
        if (isPressed(KeyEvent.VK_A)) dx -= 1;
        if (isPressed(KeyEvent.VK_D)) dx += 1;
        if (isPressed(KeyEvent.VK_W)) dy -= 1; // Y軸通常向下為正
        if (isPressed(KeyEvent.VK_S)) dy += 1;
        return new Point(dx, dy); // 返回 (-1,-1) 表示左上斜向等
    }
}

2. 在遊戲主迴圈/定時器中應用


// 遊戲主迴圈 (如 javax.swing.Timer 每 16ms 執行一次)
Timer gameLoop = new Timer(16, e -> {
    Point move = keyListener.getMoveVector();
    
    if (move.x != 0 || move.y != 0) {
        // 歸一化斜向速度 (避免斜向比直向快 √2 倍)
        double length = Math.sqrt(move.x * move.x + move.y * move.y);
        double vx = (move.x / length) * SPEED;
        double vy = (move.y / length) * SPEED;
        
        player.x += vx;
        player.y += vy;
    }
    
    repaint(); // 觸發重繪
});
gameLoop.start();

進階優化建議

  1. 焦點問題: 確保 JPanel 或 JFrame 可獲取焦點:setFocusable(true); requestFocusInWindow();。
  2. 按鍵衝突/鬼鍵: 硬體鍵盤矩陣限制可能導致某些三鍵組合無法識別,遊戲設計應避免強制三鍵操作。
  3. 現代替代: JavaFX 使用 Scene.setOnKeyPressed 配合 KeyCodeCombination 或 InputMap/ActionMap (Swing) 可實現更解耦的命令模式綁定。

總結

「同時按下」本質是「狀態疊加」。通過 Set<Integer> 維護即時按鍵狀態,在遊戲邏輯幀中合成移動向量,是實現流暢八方向移動的標準模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved