当前位置: 首页 > 知识库问答 >
问题:

突破游戏多键处理

段哲圣
2023-03-14

当用户按下左右键时,我希望我的矩形停止。我研究了多个密钥处理,但无法找到任何东西。

package View;

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

public class GamePanel extends JPanel {

private final int WIDTH = 600, HEIGHT = 500;

// PROPERTIES

private Timer timer;
int x = 0;
int y = 475;
int velX = 0; // only left or right

// CONSTRUCTOR

public GamePanel() {

    setSize(WIDTH, HEIGHT);
    setBackground(new Color(240, 255, 255));

    timer = new Timer(5, new MyTimerListener());        
    addKeyListener( new MyKeyListener());

    setFocusable(true); // for key listening
    setFocusTraversalKeysEnabled(false); 

    timer.start();
}

// METHODS

@Override 
public void paintComponent(Graphics g) {

    super.paintComponent(g);
    g.setColor( new Color(201, 51, 51));
    g.fillRoundRect(x, y, 80, 20, 15, 15);      
}

public class MyTimerListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {

        if ( x < 0 )
        {
            velX = 0;
            x = 0;          
        }

        if ( x > 520 )
        {
            velX = 0;
            x = 520;
        }

        x = x + velX;

        repaint();
    }       
}

public class MyKeyListener implements KeyListener {

    @Override
    public void keyPressed(KeyEvent e) {

        int code = e.getKeyCode();

        if ( code == KeyEvent.VK_LEFT )
            velX = -1;

        if ( code == KeyEvent.VK_RIGHT )
            velX = 1;       
    }
    @Override
    public void keyReleased(KeyEvent e) {

        velX = 0;           
    }
    @Override
    public void keyTyped(KeyEvent e) {}             
}   
}

谢谢你的帮助

共有1个答案

文建业
2023-03-14

同样,使用键绑定,而不是KeyListener。您希望对右箭头键和左箭头键的按下和释放使用单独的绑定,并希望您的键绑定操作改变程序的状态,这将影响挥杆计时器如何移动桨叶。在这个示例中(借用自我的另一个示例),我创建了一个枚举Direction来封装右方向和左方向,并创建了一个映射 ,它将布尔值与右方向和左方向关联。按右箭头键将改变映射以将正确方向与true布尔值相关联,而释放键则相反。计时器会轮询地图,看看把桨移到哪里。例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.EnumMap;
import java.util.Map;

import javax.swing.*;

@SuppressWarnings("serial")
public class GamePanel2 extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = 500;
   private static final int PADDLE_Y = 475;
   private static final int PADDLE_W = 80;
   private static final int PADDLE_H = 20;
   private static final int PADDLE_ARC = 15;
   private static final int TIME_DELAY = 15;
   public static final int VEL_X = 2;
   private static final Color PADDLE_COLOR = new Color(201, 51, 51);
   private int paddleX;
   private Timer time = new Timer(TIME_DELAY, new TimerListener());

   // key presses and releases will change the boolean values held in this Map
   // When an arrow key is pressed, the direction-corresponding boolean is set true
   // and likewise when the arrow key is released the direction corresponding boolean is false
   private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);


   public GamePanel2() {
      setKeyBindings();
      time.start();
   }

   private void setKeyBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      // iterate through all the Direction enums
      for (Direction direction : Direction.values()) {
         // set all values to false
         dirMap.put(direction, false);

         // create two key strokes, one for pressed and one for released
         int keyValue = direction.getKeyValue();
         KeyStroke pressedKey = KeyStroke.getKeyStroke(keyValue, 0, false);
         KeyStroke releasedKey = KeyStroke.getKeyStroke(keyValue, 0, true);

         // create two Actions, one for pressed, one for released
         Action pressedAction = new KeyAction(direction, true);
         Action releasedAction = new KeyAction(direction, false);

         // add keystroke to inputMap and use keystroke's toString as binding link
         inputMap.put(pressedKey, pressedKey.toString());
         inputMap.put(releasedKey, releasedKey.toString());

         // link binding links to our actions
         actionMap.put(pressedKey.toString(), pressedAction);
         actionMap.put(releasedKey.toString(), releasedAction);
      }

   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g.setColor(PADDLE_COLOR);
      g.fillRoundRect(paddleX, PADDLE_Y, PADDLE_W, PADDLE_H, PADDLE_ARC, PADDLE_ARC);
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         // if JPanel no longer displayed, stop the Timer
         if (!GamePanel2.this.isDisplayable()) {
            ((Timer) e.getSource()).stop();
         }
         // here's the key: iterate through the Direction enum
         for (Direction direction : Direction.values()) {
            // get corresponding boolean from dirMap
            // and if true, change location of x and y
            if (dirMap.get(direction)) {
               int possibleX = paddleX + VEL_X * direction.getDeltaX();
               if (direction == direction.RIGHT && possibleX + PADDLE_W <= getWidth()) {
                  paddleX = possibleX;
               }
               if (direction == Direction.LEFT && possibleX >= 0) {
                  paddleX = possibleX;
               }
            }
         }
         repaint();
      }
   }

   private class KeyAction extends AbstractAction {
      private Direction direction;
      private boolean pressed;

      public KeyAction(Direction direction, boolean pressed) {
         this.direction = direction;
         this.pressed = pressed;               
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         dirMap.put(direction, pressed); // key press simply changes the map, that's it.
      }
   }

   private static void createAndShowGui() {
      GamePanel2 mainPanel = new GamePanel2();

      JFrame frame = new JFrame("GamePanel2");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

enum Direction {
   LEFT("Left", KeyEvent.VK_LEFT, -1),
   RIGHT("Right", KeyEvent.VK_RIGHT, 1);

   private String text; 
   private int keyValue; // KeyEvent.VK_?
   private int deltaX; 

   Direction(String text, int keyValue, int deltaX) {
      this.text = text;
      this.keyValue = keyValue;
      this.deltaX = deltaX;
   }

   public String getText() {
      return text;
   }

   public int getKeyValue() {
      return keyValue;
   }

   @Override
   public String toString() {
      return text;
   }

   public int getDeltaX() {
      return deltaX;
   }
}
 类似资料:
  • 我的java突破游戏有问题。一切都很好,除了我的球拍在右侧离开屏幕,我的球也会这样,但现在不用担心。 //防止挡板移出屏幕 Public void update(){x=xVelocity; //根据向左或向右按设定速度 按下Public void键(KeyEvent e) //释放关键帧后设置速度 如果(e.getKeyCode()==KeyEvent.VK_LEFT){

  • 所以我正在android studio中制作一款突破性游戏。 在做了一个游戏循环和与桨和桨的基本碰撞后,我注意到我的球在提高速度后开始穿过我的桨和桨。 问题在于它在一帧中碰撞了两次,所以我的基本碰撞还不够。 我读过关于使用向量数学求解的书。但这对我来说太过分了,我的头也被它缠住了。我指的是这个问题的答案:

  • 我正在读《java的艺术与科学:计算机科学导论》一书学习java。练习程序之一是创建突破游戏的简单克隆。 我目前能够加载游戏,但球的物理问题。我正在使用最简单的物理可能,不明白为什么它不起作用。 当球撞到墙上时,它会正常反弹,但当它撞到桨或砖块时,它不会。我在碰撞检测中使用相同的代码来更改我在墙上使用的方向。检测到碰撞后,我添加了一个println并观察了控制台处理碰撞事件的过程,但方向没有发生变

  • 不知道为啥在****上投了一万个数据分析岗没回应,结果多益的hr直接找上来问我对游戏玩的多不多,对游戏策划感不感兴趣,莫名其妙的就投了简历,填完了测评(看别人都说有些都乱填,就我兢兢业业填了快一千多个字?),明天笔试不知道考啥 多益很缺策划?鼠鼠就一破打游戏的能面游戏策划吗? 8.5一面(面试官的麦经常会听不清,反问了好几次,然后回答问题的时候眼睛不由自主往左下瞄,我也不知道为啥,下次屏幕中间贴个

  • 每2个玩家,服务器将创建1个房间(我的游戏是PvP,一对一) 每个房间处理游戏逻辑 我将使用作为我的游戏循环 服务器FPS=5 每个房间都可以处理玩家的移动和一些物理操作 关于实际问题: 基于下面的点数,我应该使用什么样的游戏循环?下面每种类型的游戏循环的利弊是什么。 null

  • 我在做一个小的迷你瓷砖引擎游戏。我目前正致力于实现简单的基于块的碰撞检测,然而我遇到了实际的问题。我已经在谷歌上搜索了几个小时,查看了不同的实现,但似乎无法理解它。我目前的努力(只在玩家向右移动时检测碰撞),大部分工作,但允许玩家通过障碍物的底部。碰撞使用法线映射数组来检测碰撞,映射中的任何值2都是一个实体对象。 我明白了我需要做什么的概念--在我移动我的玩家之前,计算玩家将最终进入哪个单元格。检