Java,Steam控制器和我

您是否想过是否可以将现有的东西用于新的东西? 我看了一些所谓的“蒸汽控制器”(从现在开始为SC)的镜头,并看着我的游戏手柄。 问我自己是否有可能以类似蒸汽的方式使用它,我找到了一些Java库并创建了一个项目,今天想与您共享。

SteamController 当然,早在SC发行之前就已经有很多输入设备(尤其是游戏控制器),但是它具有一个新特性,使其与众不同。

它具有两个触摸板,它们可以模拟鼠标或键盘的输入,以便能够(实际上几乎)玩每个游戏。 如一些早期视频所示,通过使用这种兼容模式,即使像益智游戏“ Portal”之类的鼠标密集型游戏也似乎可以玩。
steamworkshop_webupload_previewfile_172072817_preview 作为游戏发烧友和Java程序员,我如何使用这样的东西(我已经拥有的XBOX控制器)来接近它?

一个名为“ StrangeCtrl”的小工具看到了世界的亮光。 与控制器对话需要一些JNI(例如,因为JVM中没有USB子系统),但是其余部分则是用纯Java编写的。 它位于系统托盘中,并且针对每个配置文件进行了手动配置,尽管也可以构建一个GUI。

它的依存关系是2.0.5版中的“ net.java.jinput.JInput”(仍适用于Windows 8.1)和我编写的一个小助手(“ com.xafero.SuperLoader” v0.1)。 现在,我将解释在此过程中采取的步骤。

第一步:我们如何让Java与我的控制器对话?

幸运的是,BSD许可的JInput项目正是这样做的。 例如,它连接到Microsoft的XInput接口,并用它获取的本机数据填充某些Java数据结构。 也涵盖Linux和Mac OS X,不用担心。

因此,我插入了游戏手柄(一个兼容XBOX的控制器),方法似乎很清楚:

  1. 得到控制器
  2. 得到他们的输入事件
  3. 并将它们转换为键盘和鼠标的虚拟事件。

三大操作系统的库的本机组件均以Java归档文件(至少每个Maven)提供。 但是,您可能已经知道,java.lang.System仅加载文件系统上直接可用的文件。

第二步:那么如何解决这个烦人的局限性呢?

快速搜索后,我发现wcmatthysen的“ mx-native-loader”似乎很有用,因为它声称可以提取JAR并加载本地内容。 但这没有用,因为JInput的库被打包到几个“ jinput-platform-***。jar”文件中,而不是像该加载器所建议的那样,被打包在META-INF / lib下的一个大块文件中。

因此,名为“ SuperLoader”的新帮助程序库可以在以下情况下工作:

  1. 为所有讨厌的本机库创建一个临时目录,例如,借助系统属性“ java.io.tmpdir”。 用户也可以直接指定它,因为它实际上并不重要。
  2. 从已经加载的JAR中获取所有讨厌的库; 遍历所有类路径的URL,并使用过滤器将其提取或排除其中的大多数。
  3. 扩展现有的库路径; 另一个库没有做的一件事,并且手动进行非常烦人,因此应扩展系统属性“ java.library.path”。
  4. 强制JVM更新系统路径; 可以通过将系统类加载器的“ sys_paths”字段重置为null来实现。 这迫使System类在您下次请求库时真正欣赏新情况。

现在,该应用程序将所有本机库预加载到一个临时文件夹中,例如,当要求JInput提供控制器列表时,不必为使用JAR文件而对其进行更改。 它完全可以像任何人一样使用System.loadLibrary。

第三步:可以模拟什么?

我们终于要阅读游戏手柄的事件了,那么我们该怎么办呢? 使用AWT的Robot类,自Java早期以来就可以模拟按键或鼠标移动等。 尽管机器人需要一个人来指定应该在其上工作的桌面,但它在多显示器系统上也可以正常工作。 唯一的区别是它生成的所有事件的偏移量–如果要单击PC屏幕的特定区域,这一点尤其重要。

到目前为止已实现的命令是:

  • MouseMoveCmd –水平或垂直移动鼠标一定量
  • MouseClickCmd –在当前屏幕位置单击给定的鼠标按钮
  • KeyComboCmd –按一些键并以相反的顺序释放它们

为了实现某种程度的可扩展性,有一个接口可以接受机器人生成虚拟事件,当前图形设备以及JInput给定的值:

public interface ICommand {void execute(Robot rbt, GraphicsDevice dev, float value);
}

它的抽象实现“ AbstractCmd”提供了一个接受一个字符串的构造函数。 作为处理的第一步,来自配置文件的原始字符串被一个空白分隔为一个字符串数组。

第四步:我们可以使用哪种配置格式?

有很多流行的格式,例如YAML,JSON等。但是Java已经为我们提供了一种简单的方法来实现这一目标。 因此,使用Java属性机制的XML变体来解析配置文件。 要使用与命令连接的字符串来构建实际地图,请使用类“ com.xafero.strangectrl.cmd.ConfigUtils”

  • 加载配置,
  • 遍历所有条目,
    • 通过每个条目的值搜索命令,
  • 并生成用于转换传入事件的实际地图。

第五步:实际工作

辅助类“ ControllerPoller”是一个定期执行的TimerTask,负责从任意数量的控制器中收集新的JInput事件,并将每个新内容通知调用者:

public void run() {
for (Controller controller : controllers) {
if (!controller.poll()) continue;
EventQueue queue = controller.getEventQueue();
Event event = new Event();
while (queue.getNextEvent(event))
callback.onNewEvent(this, controller, event);
}
}

调用方(在这种情况下,位于系统托盘中的所谓“ App”)仅实现回调接口,并在发生任何输入时免费获取所有信息:

public static interface IControllerCallback {
void onNewEvent(ControllerPoller p, Controller c, Event e);
}

“应用程序”的左侧是搜索与传入游戏手柄事件相关联的命令,并使用正确的参数执行这些命令。 现在我们可以用它来控制某些游戏,也许是波斯王子之类的旧游戏,或者是其他无法通过游戏手柄玩的游戏。 但是,让我们走开...

除了游戏以外的示例:如何为行动受限的人配置它?

为了仅显示另一个可能的应用领域,让我们为无法同时按下两个键的用户进行配置。 一个示例应用程序应该是Web浏览器。 在配置文件中,有以下设置:

<!-- Button A means now left mouse click -->
<entry key="Button 0">mouseClick 1</entry>
<!-- Button B will open a new tab -->
<entry key="Button 1">keyCombo CONTROL T</entry>
<!-- Button X will close an existing tab -->
<entry key="Button 2">keyCombo CONTROL W</entry>

此示例中的浏览器不必知道游戏控制器,因为操作系统将产生新的虚拟输入事件,并且将按要求运行。 通过使用Java并成为FOSS,该工具还可以进行自定义并且易于以各种方式理解(与模拟输入设备否则必须使用某些C / C ++代码相比)。

资源和链接

源代码位于https://github.com/xafero/StrangeCtrl 。 随时使用,共享或修改任何方面(根据GPL v3许可)。

有关更多信息,请参见:

  • JInput – https://java.net/projects/jinput
  • AWT机器人-http: //docs.oracle.com/javase/6/docs/api/java/awt/Robot.html

参考: Java,Steam控制器和Java,来自我们JCG合作伙伴 Xafero的Java Advent Calendar博客。

翻译自: https://www.javacodegeeks.com/2014/01/java-the-steam-controller-and-me.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365974.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unknown column in field list_tf.feature_column的特征处理探究

1. 背景tf.estimator是tensorflow的一个高级API接口&#xff0c;它最大的特点在于兼容分布式和单机两种场景&#xff0c;工程师可以在同一套代码结构下即实现单机训练也可以实现分布式训练&#xff0c;正是因为这样的特点&#xff0c;目前包括阿里在内的很多公司都在使用这一接…

jQuery clearQueue

clearQueue()方法与clearQueue()方法结合&#xff1b; .clearQueue()可用于删除通过.queue()方法添加到通用jQuery序列的任何函数。 示例&#xff1a; <!DOCTYPE html><html><head><style>div { margin:3px; width:40px; height:40px;position:absol…

Docker设置HTTP代理

参考资料&#xff1a;为docker配置HTTP代理服务器 一、注释掉namesserver的配置 [rootnvwa ~]# cat /etc/resolv.conf # Generated by NetworkManager search apa.gad.schneider-electric.com nameserver xx.xx.xx.xx nameserver xx.xx.xx.xx 改为&#xff1a; [rootnvwa ~]# c…

C语言oj中a b怎么做,【HDUOJ】第1002题 A + B Problem II 纯C语言解法

【HUDOJ-1002】1.原题&#xff1a;Problem DescriptionI have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A B.InputThe first line of the input contains an integer T(1<T<20) which means the number of tes…

截止到2013年,核心Java帖子

随着2013年即将结束&#xff0c;我最近发现了几篇与我认为“核心Java”知识有关的帖子。 该帖子列出了三个帖子&#xff0c;并提供了一个简短说明的论坛。 我这样做有两个目的&#xff1a;&#xff08;1&#xff09;帮助他人意识到这些优秀职位的存在&#xff1b;&#xff08;2…

jQuery 超屏加载

jQuery 超屏加载&#xff0c;当文档超出屏幕的高度时&#xff0c;加载最新下个列数据 $(window).scroll(function () {var height $(document).height(); //页面的高度var keheight $(window).height(); //浏览器可视的高度var sheight $(document).scrollTop(); //滚动的高…

爱是怎么产生的

怎么说你还是对你自己挺了解的 1. 你知道单身为什么最终都轮成单身狗吗&#xff1f;因为单身就是一种退化&#xff0c;连人类最基本的技能都忘干净了&#xff0c;活该你四角着地 2.你知道爱是怎么发生的吗&#xff1f;爱情这个词&#xff0c;绝对不是虚幻的&#xff0c;精神的&…

计算机二级c语言选择题范围,计算机二级C语言考点选择结构

C语言的运算符包含的范围很广泛&#xff0c;共有34种运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。以下是关于计算机二级C语言考点选择结构&#xff0c;希望大家认真阅读!【考点1】关系运算关系运算符有6个&#xff0c;分别是>&#xff0c;>&#xff0c;…

Mac OS下面安装mysql以及mysql常用命令

使用brew安装mysql brew install mysql 安装成功后使用下面命令启动/关闭服务 brew services start mysql brew services stop mysql 为mysql.bin设置软连接 ln -s /usr/local/Cellar/mysql/5.7.21/bin/mysql /usr/bin // /usr/local/Cellar/mysql为mysql的安装目录 进入mysql …

pytorch如何定义损失函数_对比PyTorch和TensorFlow的自动差异和动态模型

使用自定义模型类从头开始训练线性回归&#xff0c;比较PyTorch 1.x和TensorFlow 2.x之间的自动差异和动态模型子类化方法&#xff0c;这篇简短的文章重点介绍如何在PyTorch 1.x和TensorFlow 2.x中分别使用带有模块/模型API的动态子类化模型&#xff0c;以及这些框架在训练循环…

Gradle命令行便利

在我的《用Gradle构建Java的gradle tasks 》一文中&#xff0c;我简要地提到了使用Gradle的“ gradle tasks ”命令来查看特定Gradle构建的可用任务。 在这篇文章中&#xff0c;我将对这一简短提及进行更多的扩展&#xff0c;并查看一些相关的Gradle命令行便利。 Gradle可以轻松…

精读《setState 做了什么》

1 引言 setState 是 React 框架最常用的命令&#xff0c;它是用来更新状态的&#xff0c;这也是 React 框架划时代的功能。 但是 setState 函数是 react 包导出的&#xff0c;他们又是如何与 react-dom react-native react-art 这些包结合的呢&#xff1f; 通过 how-does-setst…

java封装实现Excel建表读写操作

对 Excel 进行读写操作是生产环境下常见的业务&#xff0c;网上搜索的实现方式都是基于POI和JXL第三方框架&#xff0c;但都不是很全面。小编由于这两天刚好需要用到&#xff0c;于是就参考手写了一个封装操作工具&#xff0c;基本涵盖了Excel表&#xff08;分有表头和无表头&a…

c语言程序中注释的格式化,格式化C语言命令indent

indent是linux下一个能力极强的代码整理软件&#xff0c;使用他&#xff0c;可以轻松的写出代码风格十分精良的代码。但是indent的参数太多&#xff0c;使用起来不是很容易&#xff0c;怎么办呢&#xff1f;查看/usr/src/linux-headers-/scripts/Lindent文件 &#xff0c;可以看…

argmax函数_1.4 TensorFlow2.1常用函数

1.4 TF常用函数tf.cast(tensor,dtypedatatype)可以进行强制类型转换。tf.reduce_min(tensor)和tf.reduce_max(tensor)将计算出张量中所有元素的最大值和最小值。import tensorflow as tfx1 tf.constant([1., 2., 3.], dtypetf.float64)print("x1:", x1)x2 tf.cast(…

休眠:DDL模式生成

不久前&#xff0c;我必须使用内存数据库。 该活动与集成测试有关。 如您所知&#xff0c;通常将内存数据库用于集成测试。 造成这种情况的原因有很多&#xff1a;可移植性&#xff0c;完善的环境基础结构&#xff0c;高性能&#xff0c;原始数据库的一致性。 问题在于如何将生…

分析jQuery源码时记录的一点感悟

分析jQuery源码时记录的一点感悟 1. 链式写法 这是jQuery语法上的最大特色&#xff0c;也许该改改POJO里的set方法&#xff0c;和其他的非get方法什么的&#xff0c;可以把多行代码合并&#xff0c;减去每次敲打对象变量的麻烦 2. 动态参数 偶尔使用Java…

设计模式---数据结构模式之迭代器模式(Iterate)

一&#xff1a;概念 迭代模式是行为模式之一&#xff0c;它把对容器中包含的内部对象的访问委让给外部类&#xff0c;使用Iterator&#xff08;遍历&#xff09;按顺序进行遍历访问的设计模式。 在应用Iterator模式之前&#xff0c;首先应该明白Iterator模式用来解决什么问题。…

识别Gradle约定

通过约定进行配置具有许多优点&#xff0c;尤其是在简洁方面&#xff0c;因为开发人员不需要显式配置通过约定隐式配置的内容。 但是&#xff0c;在利用约定进行配置时&#xff0c;需要了解约定。 这些约定可能已经记录在案&#xff0c;但是当我可以编程方式确定约定时&#xf…

jQuery函数的等价原生函数代码示例

选择器 jQuery的核心之一就是能非常方便的取到DOM元素。我们只需输入CSS选择字符串&#xff0c;便可以得到匹配的元素。但在大多数情况下&#xff0c;我们可以用简单的原生代码达到同样的效果。 .代码如下://----得到页面的所有div--------- /* jQuery */ $("div") …