微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

按下关键游戏后获得反应时间

如何解决按下关键游戏后获得反应时间

所以我正在制作一个游戏,在你看到屏幕上弹出的东西后记录你的反应时间,但我无法获得反应时间。我希望用户在看到蓝色球时按下向上箭头键,并且我想记录他们按下该按钮后的反应时间。

这是我的代码

public class Game extends JPanel 
{

private JLabel start,main,time;
private ImageIcon constant,react;

final int width = 600;
final int height = 600;

private Timer replace;


private Random random;
private int randTime;

private long startTime;
private long stopTime;
private long reactionTime;
private Action upAction;


public Game()
{

  setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));

  setPreferredSize(new Dimension(width,height));
  setBackground(Color.black);

  start = new JLabel("Click Up Arrow when you see a blue ball");
  start.setForeground(Color.white);
  start.setAlignmentX(Component.CENTER_ALIGNMENT);
  add(start);
 
  constant = new ImageIcon("constantCircle.png");
  main = new JLabel(constant);
  main.setAlignmentX(Component.CENTER_ALIGNMENT);


  randomTime();
  replace = new Timer(randTime,timeListener);
  startTime = System.currentTimeMillis();
  replace.setRepeats(false);
  replace.start();    
  add(main);

  time = new JLabel("0");

  time.getInputMap().put(Keystroke.getKeystroke("UP"),"upAction");
  time.getActionMap().put("upAction",upAction);


  add(time);

}


public void randomTime()
{
  random = new Random();
  int max = 8000;
  randTime = random.nextInt(max);

}


ActionListener timeListener = new ActionListener()
{
  public void actionPerformed (ActionEvent e)
  {
    react = new ImageIcon("reactCircle.png");
    main.setIcon(react);     
  }
};

public class UpAction extends AbstractAction
{
  public void actionPerformed(ActionEvent e)
  {
    stopTime = System.currentTimeMillis();
    reactionTime = stopTime - startTime;
    time.setText("" + reactionTime);
  
  }
}  
}

我使用 System.currentTimeMillis 设置了一个“startTime”来获取球变蓝后的时间,但我不确定这是否是正确的方法

我还在“UpAction”类中设置了一个“stopTime”,我想在用户按下向上箭头后获取时间,但它不起作用。

如果有什么不明白或不够清楚的地方,我会尽量详细说明

解决方法

我想出了以下 GUI。

Reaction Time Game

我想解释两个重要的原则。第一个是创建 GUI 是一个独立于更新 GUI 的过程。二是游戏过程是一个状态机。游戏分为六个不同的状态。以下是我为牢记这些状态而写的内容。

事件顺序

  1. 左键单击按钮
  2. 等待 2 - 4 秒以显示圆圈。
  3. 捕捉开始时间
  4. 左键单击按钮
  5. 捕捉结束时间。
  6. 计算并显示反应时间。
  7. 重复 1 - 6。

因此,对于 GUI,我创建了一个 JFrame 和三个 JPanels;上部 JPanel、绘图 JPanel 和按钮 JPanel

我通过调用 SwingUtilities invokeLater 方法启动了 Swing 应用程序。此方法可确保在 Event Dispatch Thread 上创建和执行 Swing 组件。

JFrame 有一个默认的 BorderLayout,我用来放置三个 JPanelsJFrame 方法调用必须按特定顺序执行。这是我用于所有 Swing 应用程序的顺序。

上方的 JPanel 包含说明和反应时间显示。 JTextArea 非常适合显示说明。我使用 JTextAreaJPanel 放在内部 FlowLayout 中,我使用 JPanel 将其放置在上部 BorderLayout 中。像这样嵌套布局是一种以逻辑方式组织 Swing 组件的好方法。

我将反应时间 Swing 组件放在另一个内部 JPanel 中,我将其放在上部 JPanel 中。

我创建了一个绘图 JPanel,这样我就不必费心处理图像了。

按钮 JPanel 包含提交 JButton

我创建了两个控制器类。一个控制器类 ButtonListener 响应 JButton 左键单击。另一个控制器类 TimerListener 为绘制圆创建延迟。

ButtonListener 状态变量允许我使用相同的 ActionListener 提供不同的功能。如果您愿意,您可以编写单独的 ActionListener 类,每个函数一个。

通过将我的代码分成视图类和控制器类,我可以将我的关注点分开,一次专注于应用程序的一个部分。

这是完整的可运行代码。我把所有的类都放在了内部类中,这样我就可以将这段代码作为一个块发布。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class ReactionTimeGame implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ReactionTimeGame());
    }
    
    private long reactionTime;
    
    private DrawingPanel drawingPanel;
    
    private JTextField reactionTimeField;
    
    public ReactionTimeGame() {
        this.reactionTime = 0L;
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Reaction Time Game");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createUpperPanel(),BorderLayout.BEFORE_FIRST_LINE);
        this.drawingPanel = new DrawingPanel();
        frame.add(drawingPanel,BorderLayout.CENTER);
        frame.add(createButtonPanel(),BorderLayout.AFTER_LAST_LINE);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createUpperPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5,5,5));
        
        JPanel innerPanel = new JPanel(new FlowLayout());
        
        String instructions = "This game will test your reaction time. To play "
                + "the game,left-click on the Submit button.  After a random time "
                + "from 2 - 4 seconds,a circle will appear.  Left-click the "
                + "Submit button again.  Your reaction time will be displayed "
                + "above where the circle was.\n\n"
                + "Left-click the Submit button to start each round of the game.";
        JTextArea textArea = new JTextArea(7,40);
        textArea.setEditable(false);
        textArea.setText(instructions);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        innerPanel.add(textArea);
        
        panel.add(innerPanel,BorderLayout.BEFORE_FIRST_LINE);
        
        innerPanel = new JPanel(new FlowLayout());
        
        JLabel label = new JLabel("Reaction Time:");
        innerPanel.add(label);
        
        reactionTimeField = new JTextField(5);
        reactionTimeField.setEditable(false);
        updateReactionTime();
        innerPanel.add(reactionTimeField);
        
        label = new JLabel("seconds");
        innerPanel.add(label);
        
        panel.add(innerPanel,BorderLayout.AFTER_LAST_LINE);
        
        return panel;
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5,5));
        
        JButton button = new JButton("Submit");
        button.addActionListener(new ButtonListener());
        panel.add(button);
        
        return panel;
    }
    
    public void setReactionTime(long reactionTime) {
        this.reactionTime = reactionTime;
    }

    public void drawCircle() {
        drawingPanel.setDrawCircle(true);
        drawingPanel.repaint();
    }
    
    public void eraseCircle() {
        drawingPanel.setDrawCircle(false);
        drawingPanel.repaint();
    }
    
    public void updateReactionTime() {
        double time = 0.001 * reactionTime;
        reactionTimeField.setText(String.format("%.3f",time));
    }
    
    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        private boolean drawCircle;
        
        public DrawingPanel() {
            this.drawCircle = false;
            this.setPreferredSize(new Dimension(300,300));
        }

        public void setDrawCircle(boolean drawCircle) {
            this.drawCircle = drawCircle;
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            if (drawCircle) {
                int centerX = getWidth() / 2;
                int centerY = getHeight() / 2;
                int radius = Math.min(getWidth(),getHeight()) * 9 / 20;
                int diameter = radius + radius;
                g.setColor(Color.MAGENTA);
                g.fillOval(centerX - radius,centerY - radius,diameter,diameter);
            }
        }
        
    }
    
    public class ButtonListener implements ActionListener {
        
        private int state;
        
        private long startTime;
        
        private final Random random;
        
        private Timer timer;
        
        public ButtonListener() {
            this.state = 1;
            this.random = new Random();
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            switch (state) {
            case 1:
                int delay = random.nextInt(2000) + 2000;
                timer = new Timer(delay,new TimerListener(this));
                timer.start();
                state = 2;
                break;
            case 2:
                setEndTime(System.currentTimeMillis());
                eraseCircle();
                state = 1;
                break;
            }
        }

        public int getState() {
            return state;
        }

        public void setStartTime(long startTime) {
            this.startTime = startTime;
        }

        public void setEndTime(long endTime) {
            long elapsedTime = endTime - startTime;
            setReactionTime(elapsedTime);
            updateReactionTime();
        }
        
    }
    
    public class TimerListener implements ActionListener {
        
        private final ButtonListener listener;

        public TimerListener(ButtonListener listener) {
            this.listener = listener;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            Timer timer = (Timer) event.getSource();
            timer.stop();
            
            if (listener.getState() == 2) {
                listener.setStartTime(System.currentTimeMillis());
                drawCircle();
            }
        }
        
    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?