最近找到一个unity3d游戏《地铁跑酷pc版》非常好玩,但是在PC上用鼠标上下左右的拖动操作很不方便,于是网上找到一个按键控制台的小工具可以用键盘的操作模拟鼠标的操作非常好用,可惜试用版只能使用1分钟,正式版要花银子滴。还好功能看起来比较简单,于是自己动手写了一个Java版的按键控制台。
按键控制台的核心功能就是接收键盘事件然后模拟出鼠标动作。Java的
Toolkit.addAWTEventListener
可以注册全局事件,但是Java程序失去焦点后就失效了,看来得使用JNI了,还好找到开源项目jintellitype可以注册全局的键盘事件即使程序失去焦点也能响应键盘事件。
package com.yuan.common.swing; import java.awt.AWTEvent; import java.awt.AWTException; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Point; import java.awt.Robot; import java.awt.Toolkit; import java.awt.event.AWTEventListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.util.concurrent.TimeUnit; import javax.swing.JFrame; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.melloware.jintellitype.HotkeyListener; import com.melloware.jintellitype.JIntellitype; /** * 按键控制台 * @author yuan<cihang.yuan@happyelements.com> * */ public class KeyConsole { private JFrame frame; private GlobalKeyListener globalKeyListener; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { KeyConsole window = new KeyConsole(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public KeyConsole() { initialize(); } /** * Initialize the contents of the frame. */ private void initialize() { frame = new JFrame(); frame.setTitle("按键控制台"); frame.setBounds(100, 100, 450, 300); center(frame); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if(globalKeyListener != null){ System.out.println("globalKeyListener.destory ..."); globalKeyListener.destory(); } System.exit(0); //关闭 } }); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // registKeyListener(); globalKeyListener = new GlobalKeyListener(); globalKeyListener.init(); } private void center(JFrame frame){ double screenWidth = Toolkit.getDefaultToolkit().getScreenSize().getWidth(); double screenHeight = Toolkit.getDefaultToolkit().getScreenSize().getHeight(); frame.setLocation((int) (screenWidth - frame.getWidth()) / 2, (int) (screenHeight - frame.getHeight()) / 2); } private void registAWTKeyListener(){ Toolkit tk = Toolkit.getDefaultToolkit(); tk.addAWTEventListener(new ImplAWTEventListener(), AWTEvent.KEY_EVENT_MASK); } } /**全局键盘事件, 失去焦点则会失效*/ class ImplAWTEventListener implements AWTEventListener { private MouseRobot robot; public ImplAWTEventListener(){ robot = new MouseRobot(); } @Override public void eventDispatched(AWTEvent event) { if (event.getClass() == KeyEvent.class) { // 被处理的事件是键盘事件. KeyEvent keyEvent = (KeyEvent) event; if (keyEvent.getID() == KeyEvent.KEY_PRESSED) { //按下时你要做的事情 keyPressed(keyEvent); } else if (keyEvent.getID() == KeyEvent.KEY_RELEASED) { //放开时你要做的事情 keyReleased(keyEvent); } } } private void keyPressed(KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.VK_UP : robot.moveUp(); break; case KeyEvent.VK_DOWN : robot.moveDown(); break; case KeyEvent.VK_LEFT : robot.moveLeft(); break; case KeyEvent.VK_RIGHT : robot.moveRight(); break; } } private void keyReleased(KeyEvent event) { } } /** * 全局键盘事件监听器, 失去焦点也能响应键盘事件 * @author yuan<cihang.yuan@happyelements.com> * */ class GlobalKeyListener implements HotkeyListener{ private static final Logger LOG = LoggerFactory.getLogger(GlobalKeyListener.class); private MouseRobot robot; /** * 初始化 */ public void init(){ robot = new MouseRobot(); try { File dll = new File(new File("").getCanonicalFile(), "lib/JIntellitype64.dll"); System.out.println(dll.getAbsolutePath()); JIntellitype.setLibraryLocation(dll.getAbsolutePath()); JIntellitype.getInstance(); } catch (IOException e) { e.printStackTrace(); } if (JIntellitype.checkInstanceAlreadyRunning("按键控制台")) { LOG.error("An instance of this application is already running"); System.exit(1); } JIntellitype.getInstance().registerSwingHotKey(1, KeyEvent.VK_UNDEFINED, KeyEvent.VK_UP); JIntellitype.getInstance().registerSwingHotKey(2, KeyEvent.VK_UNDEFINED, KeyEvent.VK_DOWN); JIntellitype.getInstance().registerSwingHotKey(3, KeyEvent.VK_UNDEFINED, KeyEvent.VK_LEFT); JIntellitype.getInstance().registerSwingHotKey(4, KeyEvent.VK_UNDEFINED, KeyEvent.VK_RIGHT); JIntellitype.getInstance().addHotKeyListener(this); } /** * 注销键盘事件监听 */ public void destory(){ JIntellitype.getInstance().unregisterHotKey(1); JIntellitype.getInstance().unregisterHotKey(2); JIntellitype.getInstance().unregisterHotKey(3); JIntellitype.getInstance().unregisterHotKey(4); JIntellitype.getInstance().cleanUp(); } @Override public void onHotKey(int aIdentifier) { switch (aIdentifier) { case 1: robot.moveUp(); break; case 2: robot.moveDown(); break; case 3: robot.moveLeft(); break; case 4: robot.moveRight(); break; } } } class MouseRobot{ private Robot robot; private Point centerPoint; private Point leftPoint; private Point rightPoint; private Point upPoint; private Point downPoint; public MouseRobot(){ Toolkit tk = Toolkit.getDefaultToolkit(); Dimension dimension = tk.getScreenSize(); double screenWidth = dimension.getWidth(); double screenHeight = dimension.getHeight(); int cpX = (int) (screenWidth) / 2; int cpY = (int) (screenHeight) / 2; int xRange = 100; int yRange = 100; centerPoint = new Point(cpX, cpY); leftPoint = new Point(cpX - xRange, cpY); rightPoint = new Point(cpX + xRange, cpY); upPoint = new Point(cpX, cpY - yRange); downPoint = new Point(cpX, cpY + yRange); printPoint(centerPoint); printPoint(leftPoint); printPoint(rightPoint); printPoint(upPoint); printPoint(downPoint); try { robot = new Robot(); } catch (AWTException e) { e.printStackTrace(); } } private void printPoint(Point point){ System.out.println(point.getX() + ", " + point.getY()); } private void moveCenter(){ robot.mouseRelease(InputEvent.BUTTON1_MASK); robot.mouseMove((int)centerPoint.getX(), (int)centerPoint.getY()); } private void moveTo(Point point){ moveCenter(); robot.mousePress(InputEvent.BUTTON1_MASK); if((int)point.getX() == (int)centerPoint.getX()){ dragX(point); }else{ dragY(point); } moveCenter(); } private void dragX(Point point){ int step = ((int)point.getX() - (int)centerPoint.getX()) / 5; for(int i=1; i<=5; i++){ robot.mouseMove((int)centerPoint.getX() + step*1, (int)point.getY()); sleep(20); } } private void dragY(Point point){ int step = ((int)point.getY() - (int)centerPoint.getY()) / 5; for(int i=1; i<=5; i++){ robot.mouseMove((int)point.getX(), (int)centerPoint.getY()+ step*1); sleep(20); } } private void sleep(long millis){ try { TimeUnit.MILLISECONDS.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } } public void moveUp(){ moveTo(downPoint); } public void moveDown(){ moveTo(upPoint); } public void moveLeft(){ moveTo(rightPoint); } public void moveRight(){ moveTo(leftPoint); } }
其中:
File dll = new File(new File("").getCanonicalFile(), "lib/JIntellitype64.dll"); System.out.println(dll.getAbsolutePath()); JIntellitype.setLibraryLocation(dll.getAbsolutePath());
加载一个DLL,如果是32位系统则需要替换第一条语句为:
File dll = new File(new File("").getCanonicalFile(), "lib/JIntellitype.dll");
该代码在win7 64位系统下测试通过。
用法:
1. 运行该程序
2.打开地铁跑酷游戏
3.开始游戏,在游戏中就可以使用键盘来操作了
按下向上箭头键:跳
按下向下箭头键:滚
按下向左箭头键:向左移动
按下向右箭头键:向右移动
附件中是完整的可运行的程序!!!
相关推荐
- **面板布局**:了解控制台面板上的各个按键和指示灯的功能。 - **常用词汇**:掌握手册中列出的关键术语及其含义。 - **键盘部分**:熟悉键盘的操作方式和功能。 - **推杆部分**:了解推杆的使用方法及其与...
通过上、下、左、右按键来控制小蛇的移动方向 食物会在容器里随机生成一个位置 当小蛇吞食掉地图上的食物时下一个食物才会在容器里生成 添加了积分玩法 如果有想法可以自行添加玩法以及功能,或者私信我提出...
4. **事件处理**:在控制台版本中,事件处理可能涉及键盘输入,检测用户按键来改变蛇的方向。在GUI版本中,事件监听器用于响应用户的点击或键盘输入。 5. **循环与条件语句**:游戏循环是通过一个无限循环实现的,...
实验10 — Java Swing鼠标和按键事件 实验11 — Java Swing绘图应用程序 实验12 — Java Swing选项卡,网格布局,按钮,图标 实验13-14 — Java Swing JList MVC,SAX XML解析器 第二学期:暑期实习(老师: Гус...
5. **事件处理**:Java提供了键盘事件监听机制,开发者需要注册事件监听器来响应用户的按键操作,控制蛇的移动方向。 6. **边界值判定**:地图的边界设定是关键,初始化时,地图的四周设置为墙壁,确保蛇不会在游戏...
System.out.println("按下按键: " + ((JButton)e.getSource()).getText()); // 在这里处理按钮被点击的逻辑 } }); } ``` 以上代码添加了字母'A'到'Z'的按钮,并设置了点击事件监听器。当按钮被点击时,会在...
Java的类库提供了丰富的功能,如控制台输入输出、图形用户界面(GUI)的构建等,这些都是实现游戏的基础。 **2. Swing或JavaFX GUI框架** 贪吃蛇游戏通常需要一个图形界面来显示游戏画面。Java提供了Swing和JavaFX...
例如,可以为每个键盘按键设置一个事件处理器,当用户按下相应键时,更新蛇的移动方向。 游戏逻辑的实现涉及多个方面。首先,`Snake`类需要维护一个表示蛇身的列表,每次移动时更新这个列表。然后,当蛇吃到食物时...
9. **用户界面**:虽然描述中提到的是控制台版本的计算器,但Java还提供了图形用户界面(GUI)库,如Swing或JavaFX,可以构建一个具有按钮和文本框的交互式计算器。 10. **调试与测试**:编写代码后,需要进行调试...
3. **键盘输入处理**:使用JAVA的`java.awt.event.KeyEvent`和`KeyListener`接口来监听用户输入,根据按键方向改变蛇的移动方向。 4. **定时器**:使用`javax.swing.Timer`来控制游戏的帧率,定期更新游戏状态,如...
- Java AWT与Swing库:这个项目可能使用了Java的AWT或Swing库来构建图形用户界面(GUI)。这两个库提供了各种组件(如窗口、按钮、面板)以及布局管理器,用于创建窗口和显示游戏画面。 - 图形绘制:在Java中,`...
在这个项目中,开发者通常会使用Java Swing或JavaFX库来创建游戏界面,并通过控制台或事件监听器来处理用户输入。 首先,我们需要理解Java Swing或JavaFX的基本概念。Swing是Java的GUI工具包,提供了丰富的组件,如...
"到控制台。 此外,Java还提供了事件适配器(EventAdapter),它们是监听器接口的抽象类实现,提供默认的空方法。开发者可以继承这些适配器,只重写需要的方法,这样可以减少编写大量未使用的默认方法的代码。 总...
在我们的场景中,主要会用到`mouseMoved()`方法,因为它会在鼠标移动时被调用,而无需鼠标按键被按下。 3. **添加监听器**: 要让组件监听鼠标事件,我们需要将监听器添加到对应的组件上,例如`JFrame`或`JPanel`...
7. **图形界面**:虽然这里的描述是基于控制台实现的,但贪食蛇游戏也可以使用Java的Swing或JavaFX库来创建更直观的图形用户界面,增加游戏体验。 通过分析这个Java实现的贪食蛇游戏,我们可以看到编程的基本原理...
2. **TreeMap**:如果需要按姓名排序,可以选择TreeMap,它自动按键的自然顺序(如字符串的字典顺序)排列元素。 查询和修改操作涉及搜索算法。对于姓名查询,哈希表的查找效率很高。如果支持模糊查询,可以使用...
这涉及到对命令行参数的处理,可以使用`main`方法的`String[] args`参数来获取命令行输入,或者使用`Scanner`类来接收用户从控制台输入的数据。计算因子和需要用到循环结构和条件判断,确保遍历1到n的所有数字,并...
- **图形用户界面(GUI)**:更高级的游戏可能会使用Java Swing或JavaFX库创建窗口和控件,使用户可以通过鼠标点击或键盘按键来操作。 6. **事件监听**: 为了响应用户的暂停操作,我们需要在游戏循环中添加事件...