马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 birctreel 于 2025-4-4 17:45 编辑
为了STEAM商店上那个“本游支持手柄”功能做的手柄模块,主要功能是在手柄插拔时提示,以及检测手柄是否插上和手柄型号等等。
【【【【【注意,本代码仍然存在一定问题,如果有大佬知道或愿意讨论如何改进就太好了!!!问题我会列在最后面】】】】】
使用方法:在你的游戏工程下新建一个joystick.rpy(或别的什么名字这个无所谓),把以下代码丢进去即可:
[RenPy] 纯文本查看 复制代码 init -85 python:
import pygame
import time as pytime
class ControllerHandler:#定义手柄插拔功能
def __init__(self):
self.joystick = None
self.right_shoulder_pressed = False
self.press_start_time = 0
self.last_joystick_count = 0
self.check_interval = 0.1
self.last_check_time = 0
def update(self):# 功能:定期检查手柄连接状态
current_time = pytime.time()
if current_time - self.last_check_time >= self.check_interval:
self.last_check_time = current_time
self._check_joystick_connection()
if self.joystick is None:
return
def _check_joystick_connection(self):
joystick_count = pygame.joystick.get_count()
if joystick_count != self.last_joystick_count:
self.last_joystick_count = joystick_count
if joystick_count > 0:
if self.joystick is None:
try:
self.joystick = pygame.joystick.Joystick(0)
self.joystick.init()
renpy.notify(f"手柄已连接: {self.joystick.get_name()}")
except Exception as e:
self.joystick = None
renpy.notify(f"手柄连接失败: {e}")
else:
if self.joystick is not None:
self.joystick = None
renpy.notify("手柄已断开")
# 创建一个用来调用以上代码块的功能
controller_handler = ControllerHandler()
# 每帧更新
def controller_update():
controller_handler.update()
#让update功能时时被检测
config.periodic_callback = controller_update
在以上代码定义了之后,你可以用以下功能来检测手柄数据:
controller_handler.joystick.get_name() #输出连接的手柄名字,比如PS5手柄会返回"PS5 Controller",Xbox手柄会返回含有Xbox的名字,方便进行不同类型手柄的按键兼容
controller_handler.joystick #判断手柄连接状态,如果没有连接手柄就会返回None
剩下来定义按键操作参考文档就行了:https://doc.renpy.cn/zh-CN/keymap.html
===============================================================
根据我的测试结果,不同手柄的按键识别对应的编号是不一样的。我另外写了一个手柄测试界面,大家可以使用这个界面,来测试自己想要调用的按键对应的参数是什么:
[RenPy] 纯文本查看 复制代码
screen joystick_test():
default show_advanced = False
add Solid('#FFF')
timer 0.1 repeat True action Function(controller_handler.update) # 实时更新按键情况
frame:
xalign 0.5
yalign 0.5
xpadding 30
ypadding 30
vbox:
spacing 20
label "手柄测试面板" xalign 0.5
if controller_handler.joystick:
text "手柄: [controller_handler.joystick.get_name()]" xalign 0.5
hbox:
spacing 40
vbox:
label "按钮状态" xalign 0.5
# 普通按键
grid 4 5:
spacing 10
for i in range(min(20, len(controller_handler.buttons))):
frame:
xsize 100
ysize 60
if controller_handler.buttons[i]:
background "#333"
else:
background "#111"
vbox:
xalign 0.5
yalign 0.5
spacing 2
text str(i):
size 16
xalign 0.5
color "#fff"
if controller_handler.buttons[i]:
text "按下":
size 14
xalign 0.5
color "#0f0"
else:
text "未按":
size 14
xalign 0.5
color "#f00"
# 有关轴的按钮(摇杆+扳机)
label "轴按钮" xalign 0.5
grid 2 4:
spacing 10
for i in range(min(8, len(controller_handler.axes))):
frame:
xsize 150
ysize 80
if controller_handler.axis_buttons[i]:
background "#336"
else:
background "#114"
vbox:
xalign 0.5
yalign 0.5
spacing 5
text "轴 {}:".format(i):
size 16
xalign 0.5
color "#fff"
# 用来显示按下轴按钮后的状态和对应编号
text "{:.2f}".format(controller_handler.axes[i]):
size 18
xalign 0.5
if controller_handler.axis_buttons[i]:
color "#0f0"
else:
color "#aaa"
if controller_handler.axis_buttons[i]:
text "激活":
size 14
xalign 0.5
color "#0f0"
else:
text "未激活":
size 14
xalign 0.5
color "#f00"
# 高级信息
vbox:
label "高级信息" xalign 0.5
textbutton "显示/隐藏高级信息" action ToggleScreenVariable("show_advanced") xalign 0.5
if show_advanced:
vbox:
spacing 10
label "摇杆状态:"
for i, axis in enumerate(controller_handler.axes):
hbox:
spacing 10
text "轴 {}:".format(i)
bar:
value axis
range 2.0
xmaximum 200
left_bar "#0f0"
right_bar "#888"
text "{:.2f}".format(axis) xalign 1.0
label "方向键状态:"
for i, hat in enumerate(controller_handler.hats):
text "方向键 {}: {}".format(i, hat)
else:
text "未检测到手柄" xalign 0.5
textbutton "重新检测" action Function(controller_handler.update) xalign 0.5
将以上代码copy到joystick.rpy后,使用
call screen joystick_test
就可以开始测试手柄了
===============================================================
目前存在的问题:
使用了以上功能之后,在存档时(尤其是你使用了renpy.save之类的强制存档功能),会报
TypeError: no default __reduce__ due to non-trivial __cinit__ (perhaps renpy.game.log.log[110].objects[7][0].joystick = <pygame_sdl2.joystick.Joystick object at 0x00000000166c2d20>)
查了一圈似乎时因为pygame中不能储存joystick的数据,所以我还尝试过在renpy.save之前把controller_handler改为None,但反而导致了更大的问题……
*顺便提,如果不用renpy.save的话似乎就不会报错,只要不使用这个功能,在游戏中autosave是没有问题的,可以放心使用。
不知道有没有大佬知道这个问题要怎么解决……!
|