Hướng dẫn python send key to game - python gửi chìa khóa vào trò chơi

Tôi rất mới với Python nhưng có kinh nghiệm trong các ngôn ngữ khác. Gần đây tôi đã mua phiên bản PC của Final Fantasy III trên Steam và tôi muốn kiểm tra các kỹ năng Python tuần tuổi của mình để xem liệu tôi có thể tự động gửi phím phím đến trò chơi để chơi cho tôi và nghiền nát cấp độ công việc của mình khi tôi đi vắng không.

Một tìm kiếm nhanh trên internet và tôi đã tìm thấy //win32com.goermezer.de/content/view/136/254/ mà tôi hy vọng sẽ cho phép tôi làm điều đó.

Đây là mã của tôi:

import win32com.client
import time

shell = win32com.client.Dispatch["WScript.Shell"]
shell.AppActivate["Final Fantasy III"]

def actionSelect[]:
    time.sleep[1] #time between switching characters
    shell.SendKeys["s", 0] #'s' is my down key
    time.sleep[0.2]
    shell.SendKeys["s", 0]
    # so it goes down two options for each character for the 'Guard' option
    time.sleep[0.2] #slight delay between each key to compensate for processing
    shell.SendKeys["e", 0] #then it uses the 'e' key to select that option
    return

def battle[]:
    time.sleep[5]
    for rounds in range[0, 10]: #loops 10 times [due to xp gain per action] 
        for action in range[0, 4]: #loops 4 times = 4 charcaters
            actionSelect[]
        time.sleep[9] #time for all to Guard and enemy to attack

battle[]

Tôi không biết dòng mã thứ ba và thứ tư làm gì và không có số lượng nhỏ Google và quét có thể cho tôi biết theo các điều khoản của Layman. Tôi cũng không chắc chắn 0 trong SendKeys ["S", 0] làm gì. Bản thân mã hoạt động ... nhưng chỉ trong bất kỳ hộp văn bản nào tôi nhấp. Nó không chuyển sang cửa sổ trò chơi như tôi đã lên kế hoạch [làm thế nào tôi có thể làm điều này?] Và nếu tôi chuyển vào trò chơi theo cách thủ công thì nó vẫn chạy trong nền nhưng thực sự sẽ không kiểm soát bất cứ điều gì trong trò chơi.

Bất kỳ sự giúp đỡ nào trong dự án cuối tuần "vui vẻ" của tôi sẽ có nhiều bắt buộc. Cảm ơn.

Nhìn dưới đây cho giải pháp cuối cùng!

Được sao chép từ chủ đề StackoverFlow của tôi, xin lỗi nếu nó quá dài và cụ thể:

Tôi đã làm việc với Python trong môi trường Windows và tôi đã viết một kịch bản để tự động hóa một số tác vụ trong một trò chơi đã biết. Nhiệm vụ liên quan đến việc sử dụng nặng cả đầu vào chuột và bàn phím.

Tuy nhiên, tập lệnh cho biết chỉ có một vấn đề: nó không thể gửi tổ hợp phím đến ứng dụng. Tôi đã thử ít nhất 3 phương pháp khác nhau mà tôi sẽ đăng bên dưới và một số biến thể [cũng đọc một phần mười của các câu hỏi/câu trả lời tương tự, nhưng không có kết quả]

Đầu tiên, sử dụng mô -đun Win32API:

f = 0x46 # VirtualKey Code of the letter "F", see     //msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx 

win32api.keybd_event[f,0,0,0] # holds the "F" key down
time.sleep[2] # waits 2 seconds
win32api.keybd_event[f,0,win32con.KEYEVENTF_KEYUP,0] #     releases the key

Không có gì đặc biệt về nó, hoạt động hoàn hảo [A "F" được gõ] trong bất kỳ trình soạn thảo văn bản nào, trình duyệt ... Tuy nhiên, nếu tôi mở một trò chơi như, nói, Counter -Strike, sau đó KeyStroke bị "mất" - như trong, Không có gì xảy ra. Mặt khác, nếu tôi mở bảng điều khiển của Counter-Strike, thì phím kỹ thuật sẽ được đăng ký [như trong Notepad]. Được thử nghiệm trong một trò chơi khác, Liên minh huyền thoại, chính xác là hành vi tương tự. Trong trò chơi thực tế, không có tổ hợp phím được phát hiện. Tuy nhiên, nếu tôi mở cuộc trò chuyện [vẫn còn ingame] và chạy lại kịch bản thì nó sẽ được đăng ký bởi trò chuyện.

Trên phương pháp thứ hai:

shell = win32com.client.Dispatch["WScript.Shell"]
shell.SendKeys["F"]

Chính xác hành vi tương tự như trên. Hoạt động tốt trong mọi thứ trừ trò chơi, và trong đó chỉ hoạt động trong các cuộc trò chuyện.

Phương thức thứ ba [tín dụng thuộc về bất cứ ai đã đăng nó trong một luồng StackOverflow khác], nâng cao hơn [Gọi SendInput []] với mô -đun CTYPES. Về lý thuyết, trong ba, cái này là gần nhất để mô phỏng một máy ép khóa thực tế, thực tế:

SendInput = ctypes.windll.user32.SendInput

# C struct redefinitions 
PUL = ctypes.POINTER[ctypes.c_ulong]
class KeyBdInput[ctypes.Structure]:

... [some classes are defined here]

# Actuals Functions

def PressKey[hexKeyCode]:

    extra = ctypes.c_ulong[0]
    ii_ = Input_I[]
    ii_.ki = KeyBdInput[ hexKeyCode, 0x48, 0, 0, ctypes.pointer[extra] ]
    x = Input[ ctypes.c_ulong[1], ii_ ]
    ctypes.windll.user32.SendInput[1, ctypes.pointer[x], ctypes.sizeof[x]]

def ReleaseKey[hexKeyCode]:

    extra = ctypes.c_ulong[0]
    ii_ = Input_I[]
    ii_.ki = KeyBdInput[ hexKeyCode, 0x48, 0x0002, 0, ctypes.pointer[extra] ]
    x = Input[ ctypes.c_ulong[1], ii_ ]
    ctypes.windll.user32.SendInput[1, ctypes.pointer[x], ctypes.sizeof[x]]


def KeyPress[]:
    PressKey[0x46] # press F
    time.sleep[.5]
    ReleaseKey[0x46] #release F

... nó cũng không hoạt động. Thật kỳ lạ, nó hiển thị chính xác hành vi giống như ba lần trước: hoạt động trong bất kỳ trình soạn thảo văn bản/ứng dụng đơn giản nào, bị bỏ qua bởi các trò chơi hoặc chỉ được đăng ký trong phần trò chuyện trò chơi.

Nếu tôi đoán tôi sẽ nói những trò chơi này đang nhận được các sự kiện bàn phím của họ theo một cách khác mà tôi không bao gồm bất kỳ phương pháp nào trong số 3 phương pháp này, do đó bỏ qua các phương pháp này.

Tôi đánh giá cao bất kỳ sự giúp đỡ nào. Nếu có thể, với các ví dụ cụ thể về mã hoạt động trong CS, LOL hoặc các trò chơi tương tự để tôi có điểm xuất phát.

Chỉnh sửa: Tôi "bán giải quyết" vấn đề. Cuối cùng, không sử dụng Python để gửi tổ hợp phím mà chỉ sử dụng nó để gọi một tập lệnh Autohotkey thực hiện công việc nặng nhọc cho tôi. Kiểm tra bình luận của tôi dưới đây để biết thêm chi tiết.

EDIT2: Rất nhiều người đã tìm thấy chủ đề này, và nhiều người tò mò về cách tôi giải quyết vấn đề. Vì rất nhiều người đã giúp đỡ, tôi sẽ chia sẻ với bạn một giải pháp mà tôi đã thấy rằng không liên quan đến AHK [Hurray!], Cùng với thông tin của một số phương pháp. Ở đây chúng tôi đi:

Đúng là tôi đã "khắc phục" vấn đề bằng cách sử dụng Autohotkey và nhìn lại nó là một mớ hỗn độn nóng bỏng. Lúc đầu, những gì tôi đã làm là tôi thực sự đã tải xuống AHK và viết một kịch bản cho nó chạy song song với kịch bản Python [phải tìm hiểu những điều cơ bản về AHK, vì tôi chưa bao giờ sử dụng nó trước đây]. Đúng vậy, tôi đã phải chạy hai đoạn mã riêng biệt cùng một lúc, được viết bằng các ngôn ngữ khác nhau để gửi một bàn phím đơn giản cho một trò chơi.

Cách nó hoạt động là tập lệnh AHK sẽ phát hiện các nét bàn phím cấp cao mà tập lệnh Python được tạo ra [cùng một đầu vào mà tôi đã giải thích các ứng dụng "bình thường" có thể phát hiện nhưng các trò chơi của tôi không] và tái tạo điều kiện đó ở cấp độ thấp hơn, Đủ để trò chơi phát hiện [mức thấp hơn là trực tiếp là trực tiếp và rất cần thiết để làm cho nó hoạt động]. Điều này rõ ràng là rất khó chịu, mã lộn xộn, sử dụng hai ngôn ngữ kịch bản để thực hiện một nhiệm vụ mà một mình Python nên có khả năng làm nhiều hơn.

Vì vậy, thử thách tiếp theo của tôi là hợp nhất sạch sẽ hơn AHK và kịch bản Python gốc, và vì vậy tôi đã làm khi tôi phát hiện ra Pyahk, một mô -đun bao quanh chính AHK và có thể được nhập vào tập lệnh Python gốc như bất kỳ mô -đun nào khác.

Đó là những năm ánh sáng trước giải pháp ban đầu: Tôi chỉ cần chạy kịch bản Python gốc và bản thân kịch bản sẽ xử lý AHK từ đó, nhưng vẫn còn xa hoàn hảo. Một trong những khuyết điểm rõ ràng nhất là bạn dựa vào mô -đun của bên thứ ba rất nhạy cảm với phiên bản Python của bạn, ví dụ như nó chỉ hoạt động trên Python 2.7 [thật tệ vì hầu hết các dự án của tôi đang sử dụng> 3 và kịch bản ngớ ngẩn này cần được cài đặt Python 2 chỉ danh cho no thôi]. Một người khác là một mô -đun khác, vì tất cả những điều tốt đẹp của nó, cần phải được nhập và xử lý cho một cái gì đó mà bạn chỉ cảm thấy Python có thể làm, chắc chắn nếu không có những mánh lới quảng cáo này!

Nhưng thời gian là điều cốt yếu, đặc biệt là vì tôi có các vấn đề khác với mã của mình, vì vậy tôi đã thực dụng về nó và nó hoạt động theo cách đó trong một thời gian dài.

Cuối cùng, một ngày nào đó tôi quyết định tìm một giải pháp quyết định, một điều mà ít nhất sẽ cho phép tôi làm việc với các phiên bản Python mới hơn, và vì vậy tôi đã tìm kiếm như trước đây, và vì vậy nó đã xảy ra! Tôi tình cờ thấy một giải pháp thanh lịch hoạt động chỉ với mô -đun CTYPES và tôi đã sử dụng nó kể từ đó!

import ctypes, time
# Bunch of stuff so that the script can send keystrokes to game #

SendInput = ctypes.windll.user32.SendInput

# C struct redefinitions 
PUL = ctypes.POINTER[ctypes.c_ulong]
class KeyBdInput[ctypes.Structure]:
    _fields_ = [["wVk", ctypes.c_ushort],
                ["wScan", ctypes.c_ushort],
                ["dwFlags", ctypes.c_ulong],
                ["time", ctypes.c_ulong],
                ["dwExtraInfo", PUL]]

class HardwareInput[ctypes.Structure]:
    _fields_ = [["uMsg", ctypes.c_ulong],
                ["wParamL", ctypes.c_short],
                ["wParamH", ctypes.c_ushort]]

class MouseInput[ctypes.Structure]:
    _fields_ = [["dx", ctypes.c_long],
                ["dy", ctypes.c_long],
                ["mouseData", ctypes.c_ulong],
                ["dwFlags", ctypes.c_ulong],
                ["time",ctypes.c_ulong],
                ["dwExtraInfo", PUL]]

class Input_I[ctypes.Union]:
    _fields_ = [["ki", KeyBdInput],
                 ["mi", MouseInput],
                 ["hi", HardwareInput]]

class Input[ctypes.Structure]:
    _fields_ = [["type", ctypes.c_ulong],
                ["ii", Input_I]]

# Actuals Functions

def PressKey[hexKeyCode]:
    extra = ctypes.c_ulong[0]
    ii_ = Input_I[]
    ii_.ki = KeyBdInput[ 0, hexKeyCode, 0x0008, 0, ctypes.pointer[extra] ]
    x = Input[ ctypes.c_ulong[1], ii_ ]
    ctypes.windll.user32.SendInput[1, ctypes.pointer[x], ctypes.sizeof[x]]

def ReleaseKey[hexKeyCode]:
    extra = ctypes.c_ulong[0]
    ii_ = Input_I[]
    ii_.ki = KeyBdInput[ 0, hexKeyCode, 0x0008 | 0x0002, 0, ctypes.pointer[extra] ]
    x = Input[ ctypes.c_ulong[1], ii_ ]
    ctypes.windll.user32.SendInput[1, ctypes.pointer[x], ctypes.sizeof[x]]

def KeyPress[]:
    time.sleep[3]
    PressKey[0x10] # press Q
    time.sleep[.05]
    ReleaseKey[0x10] #release Q

Mã này sẽ hoạt động tốt, hãy thử nó. Không cần Autohotkey hoặc bất kỳ mô -đun nào khác. Tôi không biết Python của bạn tiến bộ như thế nào nhưng nó không phức tạp, hoạt động như sau:

Khi bạn gọi hàm keypress [], tập lệnh sẽ, sau 3 giây, sẽ gửi "Q" nhấn đến bất cứ điều gì được lấy nét. Tôi đã sử dụng "Q" vì mã ban đầu của tôi sử dụng nó, nhưng bạn có thể tìm thấy danh sách đầy đủ các mã cho bất kỳ khoản phím nào bạn cần ở đây: //www.flint.jp/misc/?q=dik&lang=en

Tôi mong rằng nó giúp ích được cho bạn :]

Bài Viết Liên Quan

Chủ Đề