首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >鼠标/键盘映射程序操纵杆

鼠标/键盘映射程序操纵杆
EN

Code Review用户
提问于 2017-01-07 15:42:26
回答 1查看 2.2K关注 0票数 10

我一直在做一个项目,把操纵杆(在我的例子中是Logitech极限3D)映射到鼠标和键盘上,这样我就可以在不支持游戏的网络游戏中使用它了。我的设计目标是:

  1. 灵活性-我希望能够修改这个几乎任何组合的操纵杆/游戏垫到键盘/鼠标很容易。
  2. 可读性-我希望能够发表这个,以便其他人可以使用它没有太多的麻烦。

这是我的代码:

代码语言:javascript
复制
import pygame
from pygame.locals import *
import ctypes
import math

def main():
   print('Python Slither controller is ready.')
   pygame.init()
   clock = pygame.time.Clock()
   joysticks = []
   for i in range(0, pygame.joystick.get_count()):
      joysticks.append(pygame.joystick.Joystick(i))
      joysticks[-1].init()

   while 1:
      clock.tick(60)

      updateData(pygame.joystick.Joystick(0))
      doActions()

      for event in pygame.event.get():
         if event.type == QUIT:
             print ("Received event 'Quit', exiting.")
             return


controls = {'trigger': 0, 
            'x-axis': 0,
            'y-axis': 0,
            'z-axis': 0,
            'hat-x': 0,
            'hat-y': 0,
            'slider': 0,
            'button-2': 0,
            'button-3': 0,
            'button-4': 0,
            'button-5': 0,
            'button-6': 0,
            'button-7': 0,
            'button-8': 0,
            'button-9': 0,
            'button-10': 0,
            'button-11': 0,
            'button-12': 0}

old_controls = controls.copy()

def updateData(joystick):
    global old_controls
    old_controls = controls.copy()

    controls['trigger'] = joystick.get_button(0)
    for i in range(1, 12):
        controls['button-'+str(i+1)] = joystick.get_button(i)
    controls['slider'] = joystick.get_axis(2)
    controls['x-axis'] = joystick.get_axis(0)
    controls['y-axis'] = joystick.get_axis(1)
    controls['z-axis'] = joystick.get_axis(3)
    controls['hat-x'] = joystick.get_hat(0)[0]
    controls['hat-y'] = joystick.get_hat(0)[1]


######################################################
######################################################
######################################################


def keyAction(keyChar):
    return (lambda old, new:
        keyEvent(bool(new), keyChar))

def mouseMoveAction():
    pass

def mouseScrollAction(scale):
    return (lambda old, new: 
        mouseScroll(int((old-new)*scale)))

def mousePressAction():
    return (lambda old, new:
        mouseEvent(new))

mousePos = [0,0]
def mouseMoveAction(rangeOfMotion, axis, minDist):
    def ret(old, new):
        if dist(mousePos[0], mousePos[1],
                centerOfDisplay[0], centerOfDisplay[1]) > minDist:
            mousePos[axis] = int(rangeOfMotion * new)
        mouseMoveAroundCenter(mousePos[0], mousePos[1]) 
    return ret


actions = {
    'trigger': mousePressAction(),
    'x-axis': mouseMoveAction(150, 0, 50),
    'y-axis': mouseMoveAction(150, 1, 50),
    'z-axis': lambda old, new: 0,
    'hat-x': lambda old, new: 0,
    'hat-y': lambda old, new: 0,
    'slider': mouseScrollAction(100),
    'button-2': lambda old, new: 0,
    'button-3': keyAction('.'),
    'button-4': lambda old, new: 0,
    'button-5': keyAction('f'),
    'button-6': lambda old, new: 0,
    'button-7': keyAction('w'),
    'button-8': keyAction('q'),
    'button-9': lambda old, new: 0,
    'button-10': keyAction('tab'),
    'button-11': lambda old, new: 0,
    'button-12': keyAction('esc')
}


def doActions():
    for key in controls:
        if old_controls[key] != controls[key]:
            actions[key](old_controls[key], controls[key])


######################################################
######################################################
######################################################


# https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx    
keys = {'f': 0x46,
        'esc': 0x1B,
        'q': 0x51,
        '.': 0xBE,
        'tab': 0x09,
        'w': 0x57}

def keyEvent(keyDown, keyName):
    eventConstants = {'key_down': 0, 'key_up': 0x0002}
    ctypes.windll.user32.keybd_event(keys[keyName], 0, eventConstants['key_down' if keyDown else 'key_up'], 0)


# https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
# only the required consts are shown, more can be found at the link
mouseEventConstants = {'absolute_pos': 0x8000,
                       'left_down': 0x0002,
                       'left_up': 0x0004,
                       'wheel': 0x0800}

# https://msdn.microsoft.com/en-us/library/ms724385(v=vs.85).aspx
centerOfDisplay = ( int(ctypes.windll.user32.GetSystemMetrics(0) / 2),
                    int(ctypes.windll.user32.GetSystemMetrics(1) / 2))
def mouseMoveAroundCenter(x, y):
    ctypes.windll.user32.SetCursorPos(x + centerOfDisplay[0],
                                      y + centerOfDisplay[1])

def mouseScroll(ticks):
    # https://msdn.microsoft.com/en-us/library/ms646260(v=vs.85).aspx
    amtPerTick = 120
    ctypes.windll.user32.mouse_event(
            mouseEventConstants['wheel'],
            0, 0, ticks * amtPerTick, 0)

def mouseEvent(pressed):
    ctypes.windll.user32.mouse_event(
            mouseEventConstants['left_down' if pressed else 'left_up'],
            0, 0, 0, 0)

def dist(x1, y1, x2, y2):
    return math.sqrt( (x1-x2)**2 + (y1-y2)**2 )

if __name__ == "__main__":
    main()

(如果你想运行它,你就需要玩游戏。这个程序是用python3.x编写的,但是它也可以在python2.x上工作。)

任何反馈都是有帮助的!谢谢!

EN

回答 1

Code Review用户

发布于 2023-01-03 01:29:08

我非常喜欢主循环中的这个:

代码语言:javascript
复制
      updateData(pygame.joystick.Joystick(0))
      doActions()

简明扼要。

您可以通过执行Extract生成def look_for_quit_event():来继续该主题

干的controls分配有点冗长,可能会在代码中更深入地进行。更喜欢:

代码语言:javascript
复制
controls = { key: 0
             for key in actions }

keys分配不必要地不透明:

代码语言:javascript
复制
keys = {'f': 0x46,
        'esc': 0x1B,
        'q': 0x51,
        '.': 0xBE,
        'tab': 0x09,
        'w': 0x57}

请给我这个。

代码语言:javascript
复制
keys = {ch: ord(ch) for ch in "fqw."}
keys["tab"] = 9
keys["esc"] = 0x1B

感谢您提供的各种MSDN URL,它们非常有用。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/151975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档