尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

做个minecraft kiosk

做个minecraft kiosk
📅 发布时间:2026/7/17 2:51:19

水鱼拿起尘封已久的树莓派4B干了件大事。创建用户minecraft,给到需要的权限(id minecraft
uid=1001(minecraft) gid=1001(minecraft) groups=1001(minecraft),46(plugdev),100(users),102(input)),创建~/.xinitrc文件,给到以下。

#!/bin/bash xset s off xset -dpms exec /usr/bin/minecraft-pi-reborn

这个就是伪kiosk精髓了,开机默认minecraft用户,然后开游戏。

讲究点加个音效文件,记得找libminecraftpe06+08.so。其他在树莓派上是不灵光的,没有声音。

再讲究点加个70元xbox手柄,但是自己要写映射键位,据说可以不写映射直接玩,我是没试成功,游戏无响应。

#路径是/usr/local/bin/mcpi-pad #!/usr/bin/env bash set -euo pipefail ACTION="${1:-}" PID_FILE="/run/mcpi-pad.pid" LOG_FILE="/tmp/mcpi-pad.log" DAEMON="/usr/local/bin/mcpi-pad-daemon.py" is_running() { if [[ ! -f "$PID_FILE" ]]; then return 1 fi local pid pid="$(cat "$PID_FILE" 2>/dev/null || true)" [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null } start_pad() { if is_running; then echo "mcpi-pad daemon is already running" ps -fp "$(cat "$PID_FILE")" || true return 0 fi sudo pkill -9 -x xboxdrv 2>/dev/null || true nohup python3 "$DAEMON" >"$LOG_FILE" 2>&1 & echo $! | sudo tee "$PID_FILE" >/dev/null sleep 0.5 if is_running; then echo "mcpi-pad daemon started" ps -fp "$(cat "$PID_FILE")" else echo "mcpi-pad daemon failed to start" [[ -f "$LOG_FILE" ]] && tail -n 80 "$LOG_FILE" exit 1 fi } stop_pad() { if is_running; then local pid pid="$(cat "$PID_FILE")" kill "$pid" 2>/dev/null || true sleep 0.2 kill -9 "$pid" 2>/dev/null || true sudo rm -f "$PID_FILE" echo "mcpi-pad daemon stopped" else echo "mcpi-pad daemon is not running" fi } status_pad() { if is_running; then echo "mcpi-pad daemon is running" ps -fp "$(cat "$PID_FILE")" else echo "mcpi-pad daemon is not running" fi } case "$ACTION" in start) start_pad ;; stop) stop_pad ;; restart) stop_pad start_pad ;; status) status_pad ;; log) [[ -f "$LOG_FILE" ]] && tail -n 120 "$LOG_FILE" || echo "No log file: $LOG_FILE" ;; *) echo "Usage: sudo mcpi-pad {start|stop|restart|status|log}" exit 2 ;; esac

以及

#路径/usr/local/bin/mcpi-pad-daemon.py #!/usr/bin/env python3 import signal import sys import time from collections import defaultdict from evdev import InputDevice, UInput, ecodes DEVICE_NAME = "Xbox Wireless Controller" THRESHOLD = 12000 CENTER = 32768 MOUSE_DEADZONE = 5000 MOUSE_MAX_STEP = 25 def find_event_device() -> str: with open('/proc/bus/input/devices', 'r', encoding='utf-8') as f: blocks = f.read().split('\n\n') for block in blocks: if DEVICE_NAME in block: for tok in block.split(): if tok.startswith('event') and tok[5:].isdigit(): return f'/dev/input/{tok}' raise RuntimeError('Xbox controller event device not found') pressed = defaultdict(set) def press(ui: UInput, src: str, key: int) -> None: if key in pressed[src]: return pressed[src].add(key) if not any(key in v for k, v in pressed.items() if k != src): ui.write(ecodes.EV_KEY, key, 1) def release(ui: UInput, src: str, key: int) -> None: if key not in pressed[src]: return pressed[src].remove(key) if not any(key in v for v in pressed.values()): ui.write(ecodes.EV_KEY, key, 0) def set_axis(ui: UInput, src: str, neg: int, pos: int, value: int) -> None: delta = value - CENTER if delta < -THRESHOLD: press(ui, src, neg) release(ui, src, pos) elif delta > THRESHOLD: press(ui, src, pos) release(ui, src, neg) else: release(ui, src, neg) release(ui, src, pos) def set_hat(ui: UInput, src: str, neg: int, pos: int, value: int) -> None: if value < 0: press(ui, src, neg) release(ui, src, pos) elif value > 0: press(ui, src, pos) release(ui, src, neg) else: release(ui, src, neg) release(ui, src, pos) def emit_mouse_rel(ui: UInput, rel_code: int, value: int, invert: bool = False) -> bool: delta = value - CENTER if abs(delta) <= MOUSE_DEADZONE: return False span = 32767 - MOUSE_DEADZONE magnitude = int(((abs(delta) - MOUSE_DEADZONE) / span) * MOUSE_MAX_STEP) magnitude = max(1, min(MOUSE_MAX_STEP, magnitude)) direction = -1 if delta < 0 else 1 if invert: direction *= -1 ui.write(ecodes.EV_REL, rel_code, direction * magnitude) return True def release_all(ui: UInput) -> None: keys = set() for ks in pressed.values(): keys.update(ks) for key in keys: ui.write(ecodes.EV_KEY, key, 0) ui.syn() def main() -> int: event_dev = find_event_device() pad = InputDevice(event_dev) kb_ui = UInput( { ecodes.EV_KEY: [ ecodes.KEY_W, ecodes.KEY_A, ecodes.KEY_S, ecodes.KEY_D, ecodes.KEY_SPACE, ecodes.KEY_LEFTCTRL, ecodes.KEY_ESC, ecodes.KEY_E, ] }, name='MCPI Pad Keyboard', bustype=0x03, ) mouse_ui = UInput( { ecodes.EV_KEY: [ecodes.BTN_LEFT, ecodes.BTN_RIGHT], ecodes.EV_REL: [ecodes.REL_X, ecodes.REL_Y], }, name='MCPI Pad Mouse', bustype=0x03, ) btn_map = { ecodes.BTN_SOUTH: ecodes.KEY_SPACE, ecodes.BTN_EAST: ecodes.KEY_LEFTCTRL, ecodes.BTN_C: ecodes.KEY_ESC, ecodes.BTN_Z: ecodes.KEY_E, } stop = False def _stop(_sig, _frm): nonlocal stop stop = True signal.signal(signal.SIGTERM, _stop) signal.signal(signal.SIGINT, _stop) while not stop: try: for ev in pad.read_loop(): if stop: break if ev.type == ecodes.EV_KEY and ev.code in btn_map: key = btn_map[ev.code] if ev.value: press(kb_ui, 'btn', key) else: release(kb_ui, 'btn', key) kb_ui.syn() elif ev.type == ecodes.EV_ABS: if ev.code == ecodes.ABS_X: set_axis(kb_ui, 'lx', ecodes.KEY_A, ecodes.KEY_D, ev.value) kb_ui.syn() elif ev.code == ecodes.ABS_Y: set_axis(kb_ui, 'ly', ecodes.KEY_W, ecodes.KEY_S, ev.value) kb_ui.syn() elif ev.code == ecodes.ABS_RX: if emit_mouse_rel(mouse_ui, ecodes.REL_X, ev.value): mouse_ui.syn() elif ev.code == ecodes.ABS_RY: if emit_mouse_rel(mouse_ui, ecodes.REL_Y, ev.value, invert=True): mouse_ui.syn() elif ev.code == ecodes.ABS_HAT0X: set_hat(kb_ui, 'hx', ecodes.KEY_A, ecodes.KEY_D, ev.value) kb_ui.syn() elif ev.code == ecodes.ABS_HAT0Y: set_hat(kb_ui, 'hy', ecodes.KEY_W, ecodes.KEY_S, ev.value) kb_ui.syn() except OSError: time.sleep(0.2) try: event_dev = find_event_device() pad = InputDevice(event_dev) except Exception: time.sleep(0.5) release_all(kb_ui) pad.close() kb_ui.close() mouse_ui.close() return 0 if __name__ == '__main__': sys.exit(main())

反正最后游戏柄还是很难调试,还是键鼠套餐香。

相关新闻

  • Mediapipe实时人像抠图:从原理到实战应用
  • 联想电脑杜比音效恢复与优化全攻略
  • 【远程操控 Agent 技术解析】Codex 主力 + UU 远程兜底的组合方案

最新新闻

  • 3分钟实现音乐社交:让你的网易云音乐和QQ音乐在Discord上闪耀
  • 2026年7月最新亨得利官方服务项目及价格查询|详细地址与服务电话权威信息通知 - 亨得利官方
  • C++实现RS纠错编码:从伽罗华域到高性能编解码库
  • 武汉万国回收价格查询及靠谱平台实测排行(2026年7月最新数据) - 诚收名表回收平台
  • VLA-World:具身智能中的反思式世界模型架构
  • 代码数据如何提升大模型的通用智能能力

日新闻

  • 佛山青少年训练营推荐:军博营地实力顶尖 - 秋山寄远
  • 如何快速上手PvZ2 Gardendless:免费Web版植物大战僵尸2完整指南
  • jiuwen-deepsearch核心功能详解:规划-检索-反思三合一智能工作流

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号