当前位置: 首页 > 面试题库 >

Java KeyEvent方块运动

施昊然
2023-03-14
问题内容

我有一段代码,当按下任意箭头键时会触发KeyEvent。反过来,这会导致正方形在屏幕上移动。

现在我注意到,当我按住键时,正方形会移动,但是如果您理解我的意思,那么从初始移动到后续移动的时间就很长了?我这次将如何减少?

谢谢!

import java.awt.*;
import javax.swing.*;
import squarequest.sprites.*;
import java.awt.event.*;


public class GamePanel extends JPanel{

    private final int HEIGHT = 400;
    private final int WIDTH = 600;
    private Square square;
    private Circle circle;


    public GamePanel(){

        addKeyListener(new DirectionListener());

        setBackground (Color.white);
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setFocusable(true);

        square = new Square();


    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        square.display(g);

    }

    public class DirectionListener implements KeyListener{


        @Override
        public void keyReleased(KeyEvent event) {}

        @Override
        public void keyTyped(KeyEvent event) {}


        @Override
        public void keyPressed(KeyEvent event) {

            switch(event.getKeyCode()){

            case KeyEvent.VK_UP:

                square.moveUp();
                break;
            case KeyEvent.VK_DOWN:

                square.moveDown();
                break;
            case KeyEvent.VK_LEFT:

                square.moveLeft();
                break;
            case KeyEvent.VK_RIGHT:

                square.moveRight();
                break;
            }
            repaint();

        }
    }
}

问题答案:
  • 使用摆动计时器进行实际运动。
  • 按键启动计时器
  • 释放密钥时将其停止。
  • 更好的是,让计时器始终运行,但只能根据地图的状态移动精灵,地图的状态包含Direction枚举键和布尔值。
  • 最好使用键绑定而不是KeyListeners。

例如,

import java.awt.*;
import javax.swing.*;
//!! import squarequest.sprites.*;
import java.awt.event.*;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

public class GamePanel extends JPanel {
   private static final int ANIMATION_DELAY = 15;
   private final int HEIGHT = 400;
   private final int WIDTH = 600;
   private Square square;
   private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
   private Map<Integer, Direction> keyToDir = new HashMap<>();
   // !! private Circle circle;
   private Timer animationTimer;

   public GamePanel() {
      for (Direction dir : Direction.values()) {
         dirMap.put(dir, Boolean.FALSE);
      }
      keyToDir.put(KeyEvent.VK_UP, Direction.UP);
      keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
      keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
      keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
      // !! addKeyListener(new DirectionListener());
      setKeyBindings();
      setBackground(Color.white);
      setPreferredSize(new Dimension(WIDTH, HEIGHT));
      setFocusable(true);
      square = new Square();
      animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
      animationTimer.start();
   }

   private void setKeyBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      final InputMap inputMap = getInputMap(condition);
      final ActionMap actionMap = getActionMap();
      boolean[] keyPressed = { true, false };
      for (Integer keyCode : keyToDir.keySet()) {
         Direction dir = keyToDir.get(keyCode);
         for (boolean onKeyPress : keyPressed) {
            boolean onKeyRelease = !onKeyPress; // to make it clear how bindings work
            KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0,
                  onKeyRelease);
            Object key = keyStroke.toString();
            inputMap.put(keyStroke, key);
            actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
         }
      }
   }

   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      square.display(g);
   }

   // public class DirectionListener implements KeyListener {
   // @Override
   // public void keyReleased(KeyEvent event) {
   // int keyCode = event.getKeyCode();
   // if (keyToDir.keySet().contains(keyCode)) {
   // Direction dir = keyToDir.get(keyCode);
   // dirMap.put(dir, false);
   // }
   // }
   //
   // @Override
   // public void keyTyped(KeyEvent event) {
   // }
   //
   // @Override
   // public void keyPressed(KeyEvent event) {
   // int keyCode = event.getKeyCode();
   // if (keyToDir.keySet().contains(keyCode)) {
   // Direction dir = keyToDir.get(keyCode);
   // dirMap.put(dir, true);
   // }
   // }
   // }

   private class AnimationListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent evt) {
         boolean repaint = false;
         for (Direction dir : Direction.values()) {
            if (dirMap.get(dir)) {
               square.move(dir);
               repaint = true;
            }
         }
         if (repaint) {
            repaint();
         }
      }
   }

   private class KeyBindingsAction extends AbstractAction {
      private Direction dir;
      boolean pressed;

      public KeyBindingsAction(Direction dir, boolean pressed) {
         this.dir = dir;
         this.pressed = pressed;
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         dirMap.put(dir, pressed);
      }
   }

   private static void createAndShowGUI() {
      GamePanel gamePanel = new GamePanel();
      JFrame frame = new JFrame("GamePanel");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(gamePanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
      gamePanel.requestFocusInWindow();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGUI();
         }
      });
   }
}

enum Direction {
   UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
   private int incrX;
   private int incrY;

   private Direction(int incrX, int incrY) {
      this.incrX = incrX;
      this.incrY = incrY;
   }

   public int getIncrX() {
      return incrX;
   }

   public int getIncrY() {
      return incrY;
   }
}

class Square {
   private int x = 0;
   private int y = 0;
   private int w = 20;
   private int h = w;
   private int step = 1;
   private Color color = Color.red;
   private Color fillColor = new Color(255, 150, 150);
   private Stroke stroke = new BasicStroke(3f, BasicStroke.CAP_ROUND,
         BasicStroke.JOIN_ROUND);

   public void display(Graphics g) {
      Graphics2D g2d = (Graphics2D) g.create();
      g2d.setColor(fillColor);
      g2d.fillRect(x, y, w, h);
      g2d.setStroke(stroke);
      g2d.setColor(color);
      g2d.drawRect(x, y, w, h);
      g2d.dispose();
   }

   public void setStep(int step) {
      this.step = step;
   }

   public void move(Direction dir) {
      x += step * dir.getIncrX();
      y += step * dir.getIncrY();
   }

//   public void moveRight() {
//      x++;
//   }
//
//   public void moveLeft() {
//      x--;
//   }
//
//   public void moveUp() {
//      y--;
//   }
//
//   public void moveDown() {
//      y++;
//   }
}


 类似资料:
  • 变色方块是一款休闲益智小游戏,适合所有人群,点击方块会改变方块颜色,将所有方块变为蓝色即为胜利,快快开动你的脑筋,来挑战吧,超有难度哦 >

  • 在前面,我们介绍了一个优秀的第三方库 — requests,本章再介绍两个第三方库: celery click 其中: celery 是一个强大的分布式任务队列,通常用于实现异步任务; click 是快速创建命令行的神器;

  • 本章实现一个俄罗斯方块游戏。 简介 俄罗斯方块游戏是有史以来最受欢迎的电脑游戏之一。最初的游戏是由俄罗斯程序员 Alexey Pajitnov 在1985年设计并编写的。从那时起,《俄罗斯方块》便以多种形式出现在几乎所有平台上。 俄罗斯方块被称为掉落方块拼图游戏。在这款游戏中,我们有7种不同的形状,叫做砖块(tetrminoes):S形、Z形、T形、L形、线形、反向L形和方形。每个形状都是由四个正

  • 《方块计数器》是一款填方块的增量放置游戏。

  • 本文向大家介绍node.js缺少mysql模块运行报错的解决方法,包括了node.js缺少mysql模块运行报错的解决方法的使用技巧和注意事项,需要的朋友参考一下 发现问题 在用node.js连接数据库,运行报错:cannot find module 'mysql; 然后 在管理员和用户下分别用npm安装数据库但是都是失败: 解决方法 按照错误日志应该是找不到文件夹,无法打开package.jso

  • 本文向大家介绍Python运行提示缺少模块问题解决方案,包括了Python运行提示缺少模块问题解决方案的使用技巧和注意事项,需要的朋友参考一下 背景: 在pycharm中运行正常,但是使用命令方式就提示没有模块 解决方案 在Python安装目录下的\Lib\site-packages文件夹中建立一个.pth文件,内容为自己写的 查看包是否有导入 再次运行,就成功了 以上就是本文的全部内容,希望对大