Java游戏的键盘输入

Java游戏的键盘输入,第1张

Java游戏的键盘输入

为了降低依赖性,我将使用“内置”键盘处理。如果您知道自己在做什么,它就可以正常工作。我将从游戏中粘贴一些代码:

它使用自定义的重复延迟/速率来处理键重复,并且组件键盘焦点位于哪个位置都没有问题。

public class GameKeyController implements KeyEventDispatcher {    private final int MAX_REPEAT_RATE = 100; // Hz    private final LocalGame game;    private final GamingContext context;    private final Account account;    Timer keyRepeatTimer;    Map<Move, TimerTask> repeatingTasks = new EnumMap<Move, TimerTask>(Move.class);    public GameKeyController(LocalGame game, GamingContext context, Account account) {        this.game = game;        this.context = context;        this.account = account;    }    public boolean dispatchKeyEvent(KeyEvent e) {        assert EventQueue.isDispatchThread();        int kc = e.getKeyCode();        if (e.getID() == KeyEvent.KEY_PRESSED) { // If repeat is activated, ignore KEY_PRESSED events. // Should actually not occur, since KEY_RELEASED *should* have been // intercepted since last KEY_PRESSED. if (kc == account.getInt(KC_MOVE_LEFT)  && !isRepeating(LEFT))      move(LEFT); if (kc == account.getInt(KC_MOVE_RIGHT) && !isRepeating(RIGHT))     move(RIGHT); if (kc == account.getInt(KC_SOFT_DROP)  && !isRepeating(SOFT_DROP)) move(SOFT_DROP); // Regular moves if (kc == account.getInt(KC_ROT_CW))        move(ROT_CW); if (kc == account.getInt(KC_ROT_CW2))       move(ROT_CW); if (kc == account.getInt(KC_ROT_CCW))       move(ROT_CCW); if (kc == account.getInt(KC_ROT_CCW2))      move(ROT_CCW); if (kc == account.getInt(KC_HARD_DROP))     move(HARD_DROP); if (kc == account.getInt(KC_SLIDE_DROP))    move(SLIDE_DROP); if (kc == account.getInt(KC_FULL_LEFT))     move(FULL_LEFT); if (kc == account.getInt(KC_FULL_RIGHT))    move(FULL_RIGHT); if (kc == account.getInt(KC_HOLD))          move(HOLD); if (kc == account.getInt(KC_SEND_TO_ME))    useSpecial(0); if (kc == account.getInt(KC_SEND_TO_1))     useSpecial(1); if (kc == account.getInt(KC_SEND_TO_2))     useSpecial(2); if (kc == account.getInt(KC_SEND_TO_3))     useSpecial(3); if (kc == account.getInt(KC_SEND_TO_4))     useSpecial(4); if (kc == account.getInt(KC_SEND_TO_5))     useSpecial(5); if (kc == account.getInt(KC_SEND_TO_6))     useSpecial(6); if (kc == account.getInt(KC_SEND_TO_7))     useSpecial(7); if (kc == account.getInt(KC_SEND_TO_8))     useSpecial(8); if (kc == account.getInt(KC_SEND_TO_9))     useSpecial(9); // Reported bug: Key repeat "lags on releases", that is, the key // continues to repeat a few ms after it has been released. // The following two lines gives one "upper" approximation of // when someone really wants to release the key. if (kc == account.getInt(KC_MOVE_RIGHT)) stopRepeating(LEFT); if (kc == account.getInt(KC_MOVE_LEFT)) stopRepeating(RIGHT);        }        if (e.getID() == KeyEvent.KEY_RELEASED) { if (kc == account.getInt(KC_MOVE_LEFT)) stopRepeating(LEFT); if (kc == account.getInt(KC_MOVE_RIGHT)) stopRepeating(RIGHT); if (kc == account.getInt(KC_SOFT_DROP)) stopRepeating(SOFT_DROP);        }        return false;    }    private synchronized void stopRepeating(Move m) {        if (!isRepeating(m)) return;        repeatingTasks.get(m).cancel();        repeatingTasks.remove(m);    }    private synchronized boolean isRepeating(Move m) {        return repeatingTasks.get(m) != null;    }    private synchronized void move(Move move) {        assert EventQueue.isDispatchThread();        context.notIdleSinceStart();        PlayfieldEvent pfe = game.move(move);        // Fake wall kicks        if ((move == ROT_CW || move == ROT_CCW) &&     account.getBool(USE_FAKE_WALL_KICKS) && !pfe.pfChanged) { // Try RIGHT and ROT, then LEFT and ROT. Playfield pf = game.getPlayfield(); if (pf.isFakeRotPossible(true, move == ROT_CW)) {     game.move(RIGHT);     game.move(move); } else if (pf.isFakeRotPossible(false, move == ROT_CW)) {     game.move(LEFT);     game.move(move); }        }        // Initiate key repeats        int delay = account.getInt(KEY_REPEAT_DELAY);        int rate = account.getInt(KEY_REPEAT_RATE);        if (delay > 0 && rate > 0 && isRepeatable(move)) startRepeating(move);    }    private boolean isRepeatable(Move m) {        return m == LEFT || m == RIGHT || m == SOFT_DROP;    }    private synchronized void startRepeating(Move move) {        assert EventQueue.isDispatchThread();        if (isRepeating(move)) return;        long delay = account.getInt(KEY_REPEAT_DELAY);        int rate = account.getInt(KEY_REPEAT_RATE);        Move repeatMove = move;        if (rate >= MAX_REPEAT_RATE) { rate = MAX_REPEAT_RATE; repeatMove = move == LEFT      ? FULL_LEFT : move == RIGHT     ? FULL_RIGHT : move == SOFT_DROP ? SLIDE_DROP : null; // not a repeatable move!        }        long period = (long) (1000.0 / rate);        if (move == SOFT_DROP) delay = period;        final Move m = repeatMove;        TimerTask tt = new TimerTask() { // Should only be executed by keyRepeatTimer thread. public void run() {     // Remove the if-branch below and you get old school GB behavior     // With the if-branch it's more TDS-ish.     // TODO: Make this depend on an account-setting     if (m == SOFT_DROP && game.getPlayfield().isTetonSurface()) {         stopRepeating(SOFT_DROP);         return;     }     game.move(m);     // Attempt to make it more responsive to key-releases.     // Even if there are multiple this-tasks piled up (due to     // "scheduleAtFixedRate") we don't want this thread to take     // precedence over AWT thread.     Thread.yield(); }        };        repeatingTasks.put(move, tt);        keyRepeatTimer.scheduleAtFixedRate(tt, delay, period);    }    public synchronized void init() {        if (!isInited()) { keyRepeatTimer = new Timer("Key Repeat Timer"); KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);        }    }    public synchronized boolean isInited() {        return keyRepeatTimer != null;    }    public synchronized void uninit() {        if (isInited()) { KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this); keyRepeatTimer.cancel(); keyRepeatTimer = null;        }    }    private void useSpecial(int target) {        context.notIdleSinceStart();        context.useSpecial(target);    }}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5487822.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-12

发表评论

登录后才能评论

评论列表(0条)

保存