之前用python3做游戏自动化脚本,用过很多东西,然后最终有一套完整的方案。在这里随便阐述一下核心思路:
游戏辅助的窗体设计方面:
不需要pyqt这种大型软件,写小工具用自带的tkinter就行了。当然,并不是自己纯手敲代码,是通过拖拽来实现的。怎么,你还不知道tkinter可以界面拖拽生成代码就行VB一样?
呵呵,PAGE了解一下。
游戏辅助的应用发布方面:
自然是用pyinstaller打包成32位版的exe发布了,带上程序图标,版本信息,都不是事儿
游戏核心模拟方面:
当然不是通过手敲代码实现了,而是通过调用目前市场上强大的dll插件了。比如com组件如大漠插件、乐玩插件。或者说,把易语言的一些模块编译成windll来调用也行哦
辅助窗体热键注册方面:
这些需要用到底层的东西了,用win32的东西实现的,可以实现注册全局热键。原理是单独一个线程用于检测热键按下,然后热键按下后单独开辟线程执行需要的功能。鉴于原生的太难写,我自己封装了并且写了一个demo。注册全局组合键和单独的热键都是没问题的。
前面三个方面仁者见仁了。后面这个我就贴个核心源码吧,免得以后找不到了。
下面贴一段新的代码:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
import win32con
import ctypes
import ctypes.wintypes
from threading import Thread,activeCount, enumerate
from time import sleep,time
class Hotkey(Thread):
user32 = ctypes.windll.user32
hkey_list = {}
hkey_flags = {}
hkey_running = {}
_reg_list = {}
def regiskey( self , hwnd = None , flagid = 0 , fnkey = win32con.MOD_ALT, vkey = win32con.VK_F9):
return self .user32.RegisterHotKey(hwnd, flagid, fnkey, vkey)
def get_reginfo( self ):
return self ._reg_list
def get_id( self ,func):
self_id = None
for id in self .get_reginfo():
if self .get_reginfo()[ id ][ "func" ] = = func:
self_id = id
break
if self_id:
self .hkey_running[self_id] = True
return self_id
def get_running_state( self ,self_id):
if self .hkey_running.get(self_id):
return self .hkey_running[self_id]
else :
return False
def reg( self ,key,func,args = None ):
id = int ( str ( round (time() * 10 ))[ - 6 :])
fnkey = key[ 0 ]
vkey = key[ 1 ]
info = {
"fnkey" :fnkey,
"vkey" :vkey,
"func" :func,
"args" :args
}
self ._reg_list[ id ] = info
sleep( 0.1 )
return id
def fast_reg( self , id ,key = ( 0 ,win32con.VK_HOME),func = lambda : print ( '热键注册开始' )):
if not self .regiskey( None , id , key[ 0 ], key[ 1 ]):
print ( "热键注册失败" )
return None
self .hkey_list[ id ] = func
self .hkey_flags[ id ] = False
return id
def callback( self ):
def inner( self = self ):
for flag in self .hkey_flags:
self .hkey_flags[flag] = False
while True :
for id , func in self .hkey_list.items():
if self .hkey_flags[ id ]:
args = self ._reg_list[ id ][ "args" ]
if args:
thread_it(func, * args)
else :
thread_it(func)
self .hkey_flags[ id ] = False
return inner
def run( self ):
for id in self ._reg_list:
reg_info = self ._reg_list[ id ]
fnkey = reg_info[ "fnkey" ]
vkey = reg_info[ "vkey" ]
func = reg_info[ "func" ]
self .fast_reg( id ,(fnkey, vkey), func)
fn = self .callback()
thread_it(fn)
try :
msg = ctypes.wintypes.MSG()
while True :
if self .user32.GetMessageA(ctypes.byref(msg), None , 0 , 0 ) ! = 0 :
if msg.message = = win32con.WM_HOTKEY:
if msg.wParam in self .hkey_list:
self .hkey_flags[msg.wParam] = True
self .user32.TranslateMessage(ctypes.byref(msg))
self .user32.DispatchMessageA(ctypes.byref(msg))
finally :
for id in self .hkey_list:
self .user32.UnregisterHotKey( None , id )
def thread_it(func, * args):
t = Thread(target = func, args = args)
t.setDaemon( True )
t.start()
def jump(func,hotkey):
self_id = hotkey.get_id(func)
while hotkey.get_running_state(self_id):
print (f "{self_id : } 你正在1秒1次的跳动" )
sleep( 1 )
def stop_jump(start_id,hotkey):
hotkey.hkey_running[start_id] = False
print (f "{start_id} 即将停止" )
sleep( 1 )
print (f '当前线程列表:{activeCount()}' , enumerate ())
def main():
hotkey = Hotkey()
start_id = hotkey.reg(key = (win32con.MOD_ALT,win32con.VK_HOME),func = jump,args = (jump,hotkey))
hotkey.reg(key = ( 0 ,win32con.VK_END),func = stop_jump,args = (start_id,hotkey))
hotkey.start()
print (f "当前总线程数量:{activeCount()}" )
print ( '当前线程列表:' , enumerate ())
print ( '热键注册初始化完毕,尝试按组合键alt+Home 或者单键END看效果' )
if __name__ = = '__main__' :
main()
|
以下是旧的代码,用起来比较麻烦。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
import win32con
import ctypes
import ctypes.wintypes
from threading import Thread, Timer, activeCount, enumerate
from time import sleep
h_ids = [i for i in range ( 2 )]
h_keys = {i: False for i in h_ids}
h_dict = {}
class Hotkey(Thread):
user32 = ctypes.windll.user32
def regiskey( self , hwnd = None , flagid = 0 , fnkey = win32con.MOD_ALT, vkey = win32con.VK_F9):
return self .user32.RegisterHotKey(hwnd, flagid, fnkey, vkey)
def callback( self , id , func):
h_dict[ id ] = func
def inner():
for key, value in h_dict.items():
print (f '总的热键池:{h_ids},当前热键序号:{key}, 当前热键功能:{value},当前热键状态:{h_keys[h_ids[key]]}' )
while True :
for key, value in h_dict.items():
if h_keys[h_ids[key]]:
thread_it(value)
h_keys[h_ids[key]] = False
return inner
def run( self ):
if not self .regiskey( None ,h_ids[ 0 ],win32con.MOD_ALT,win32con.VK_F9):
print (f "热键注册失败! id{h_ids[0]}" )
if not self .regiskey( None ,h_ids[ 1 ], 0 ,win32con.VK_F10):
print (f "热键注册失败! id{h_ids[1]}" )
try :
msg = ctypes.wintypes.MSG()
while True :
if self .user32.GetMessageA(ctypes.byref(msg), None , 0 , 0 ) ! = 0 :
if msg.message = = win32con.WM_HOTKEY:
if msg.wParam in h_ids:
h_keys[msg.wParam] = True
self .user32.TranslateMessage(ctypes.byref(msg))
self .user32.DispatchMessageA(ctypes.byref(msg))
finally :
for i in h_ids:
self .user32.UnregisterHotKey( None , i)
def thread_it(func, * args):
t = Thread(target = func, args = args)
t.setDaemon( True )
t.start()
def settimeout(func, sec):
def inner():
func()
Timer(sec, inner).start()
thread_it(inner)
def setinterval(func, sec, tmrname, flag = True ):
global timer_dict
timer_dict[tmrname] = flag
print ( "已设置tqtimer启用状态为:{}" . format (flag))
def inner():
global timer_dict
if timer_dict[tmrname]:
func()
Timer(sec, inner).start()
thread_it(inner)
def clearinterval(timername):
global timer_dict
timer_dict[timername] = False
flag = timer_dict[timername]
print ( "已设置tqtimer启用状态为:{}" . format (flag))
def test_start():
print ( "按下了开始键...the programe is running" )
def test_stop():
print ( "按下了停止键...the programe is stopped" )
def run_ok():
hotkey = Hotkey()
hotkey.start()
fn = hotkey.callback( 0 , test_start)
fn = hotkey.callback( 1 , test_stop)
thread_it(fn)
sleep( 0.5 )
count = activeCount()
print (f "当前总线程数量:{count}" )
print ( '当前线程列表:' , enumerate ())
print ( '热键注册初始化完毕,尝试按组合键alt+F9 或者单键F10看效果' )
while True :
pass
if __name__ = = '__main__' :
run_ok()
|
这里是没弄界面的源码,所以我就把主线程死循环阻塞了。运行后按alt+F9会打印按下了开始键,按F10会打印按下了停止键。
如果你在tkinter里面跑,直接把run_ok函数后面的while True:pass删掉,然后在init函数里面加入run_ok()就行了。这里指的用PAGE设计的tkinter程序哈!
那么窗体创建完毕就会自动阻塞主线程,其他监控热键的线程随主线程结束。启动期间独立运行互不干扰。
|