飞道的博客

Python脚本控制鼠标键盘

271人阅读  评论(0)

  
  1. import time
  2. import pyautogui as pg
  3. from PIL import Image
  4. import random
  5. import datetime
  6. import threading
  7. import os
  8. import keyboard as kb
  9. AutoPalyFlag = True
  10. # 设置 图标 box
  11. box_settings = ( 1890, 870, 1920, 900)
  12. # 发起投降 按钮 box
  13. box_surrender = ( 700, 820, 840, 860)
  14. # 确认投降 按钮 box
  15. box_confirm = ( 720, 460, 940, 520)
  16. # 空白区域
  17. box_empty_area = ( 700, 0, 800, 10)
  18. # 再玩一次
  19. box_play_again = ( 530, 830, 780, 880)
  20. # 商店5个怪的box
  21. champ_box = [
  22. ( 480, 930, 670, 1070),
  23. ( 680, 930, 870, 1070),
  24. ( 880, 930, 1070, 1070),
  25. ( 1080, 930, 1270, 1070),
  26. ( 1290, 930, 1480, 1070),
  27. ]
  28. pg.FAILSAFE = False
  29. log_path = 'log\\%s.log'%time.strftime( '%Y_%m_%d_%H_%M_%S')
  30. log_file = open(log_path, 'w', encoding= 'utf8')
  31. def slow_click(p, button='PRIMARY', move_time = 0.2, down_time = 0.2, up_time = 0.2):
  32. pg.moveTo(p[ 0], p[ 1], duration=move_time)
  33. pg.mouseDown(p[ 0], p[ 1], button=button, duration = down_time)
  34. pg.mouseUp(p[ 0], p[ 1], button=button, duration = up_time)
  35. return True
  36. def slow_key_press(key, down_time = 0.2):
  37. kb.press(key)
  38. time.sleep(down_time)
  39. kb.release(key)
  40. return True
  41. def record_and_print_log(log):
  42. global log_file
  43. print(log)
  44. log_file.write(log)
  45. log_file.write( '\n')
  46. return True
  47. def get_time_fmt_str(t = None):
  48. if not t:
  49. t = time.localtime()
  50. return time.strftime( "%Y/%m/%d %H:%M:%S", t)
  51. def stray():
  52. # 在棋盘小范围内随机游荡,防止鼠标指针挡住关卡图片导致检测不到3-2关卡
  53. x = random.randint( 500, 1200)
  54. y = random.randint( 250, 650)
  55. slow_click((x,y), button= 'right', move_time= 0.5)
  56. return True
  57. # 买一个怪
  58. def buy_single_champ(index):
  59. global champ_box
  60. if index > 4:
  61. index = 4
  62. if index < 0:
  63. index = 0
  64. box = champ_box[index]
  65. center = get_box_center(box)
  66. slow_click(center, move_time= 0.3)
  67. return True
  68. # 刷新商店
  69. def refresh_shop():
  70. kb.press_and_release( 'd')
  71. return True
  72. def show_emoji():
  73. kb.press_and_release( 't')
  74. return True
  75. # 提升等级
  76. def upgrade_champ():
  77. kb.press_and_release( 'f')
  78. return True
  79. def get_lol_hwnd():
  80. title = 'League of Legends'
  81. w = pg.getWindowsWithTitle(title)
  82. hwnd = False
  83. for i in w:
  84. if i.title == title:
  85. hwnd = i
  86. break
  87. return hwnd
  88. def get_box_center(box):
  89. x = int((box[ 2] - box[ 0]) / 2) + box[ 0]
  90. y = int((box[ 3] - box[ 1]) / 2) + box[ 1]
  91. return (x, y)
  92. def move_to_empty_area(lol_hwnd):
  93. global box_empty_area
  94. # 客户端已经最小化,不移动鼠标
  95. if lol_hwnd.size < ( 1024, 768):
  96. return
  97. center = convert_lol_to_destop_point(get_box_center(box_empty_area), lol_hwnd)
  98. pg.moveTo(center[ 0], center[ 1], duration = 0.1)
  99. return True
  100. # 将LOL客户端相对坐标根据LOL客户端位置转换为实际桌面的绝对坐标
  101. def convert_lol_to_destop_point(p, lol_hwnd):
  102. x = lol_hwnd.topleft[ 0] + p[ 0]
  103. y = lol_hwnd.topleft[ 1] + p[ 1]
  104. return (x, y)
  105. def surrender():
  106. global box_settings, box_surrender, box_confirm
  107. # center = get_box_center(box_settings)
  108. # 点击设置
  109. # slow_click(center, move_time=0.5)
  110. slow_key_press( 'esc')
  111. center = get_box_center(box_surrender)
  112. # 发起投降
  113. slow_click(center, move_time= 0.5)
  114. center = get_box_center(box_confirm)
  115. # 确定离开
  116. slow_click(center, move_time= 0.5)
  117. return True
  118. # 卖掉候选台前三个怪,和棋盘上自动上的怪
  119. def sell_monsters():
  120. slot1 = ( 443, 758)
  121. slot2 = ( 576, 758)
  122. slot3 = ( 696, 758)
  123. slot4 = ( 975, 672)
  124. pg.moveTo(slot1)
  125. slow_key_press( 'e')
  126. time.sleep( 1)
  127. pg.moveTo(slot2)
  128. slow_key_press( 'e')
  129. time.sleep( 1)
  130. pg.moveTo(slot3)
  131. slow_key_press( 'e')
  132. time.sleep( 1)
  133. pg.moveTo(slot4)
  134. slow_key_press( 'e')
  135. game_inactive_count = 0
  136. # 切换到游戏
  137. def make_game_active(game_hwnd):
  138. global game_inactive_count
  139. while not game_hwnd.isActive:
  140. game_hwnd.activate()
  141. pg.press( 'enter')
  142. time.sleep( 2)
  143. game_inactive_count = 0
  144. # 让游戏处于活动状态
  145. def check_game_active(game_hwnd):
  146. global game_inactive_count
  147. if not game_hwnd.isActive:
  148. game_inactive_count += 1
  149. else :
  150. game_inactive_count = 0
  151. # 等待3 * 5秒,游戏还未切换回来,就主动切换回来
  152. if game_inactive_count > 3:
  153. make_game_active(game_hwnd)
  154. # 开始匹配
  155. def click_find_match(lol_hwnd):
  156. pic_find_match = Image.open( r'scs\find_match.jpg')
  157. p = pg.locateCenterOnScreen(pic_find_match, confidence= 0.9)
  158. if p:
  159. slow_click(p)
  160. move_to_empty_area(lol_hwnd)
  161. else:
  162. return False
  163. if not pg.locateCenterOnScreen(pic_find_match, confidence= 0.9):
  164. return True
  165. return False
  166. # 等待太久,重新匹配
  167. def stop_and_start_a_new_match(lol_hwnd):
  168. pic = Image.open( r'scs\stop.png')
  169. p = pg.locateCenterOnScreen(pic, confidence= 0.9)
  170. if p:
  171. slow_click(p)
  172. move_to_empty_area(lol_hwnd)
  173. else:
  174. record_and_print_log( '找不到停止按钮!')
  175. return False
  176. time.sleep( 1)
  177. return click_find_match(lol_hwnd)
  178. # 等待并接受对局
  179. def accept_match(lol_hwnd):
  180. # 5分钟未进入游戏,直接重新匹配
  181. timeout = 5 * 60
  182. start_time = time.time()
  183. pic_accept = Image.open( r'scs\accept.jpg')
  184. while time.time() - start_time < timeout * 10:
  185. while time.time() - start_time < timeout:
  186. p = pg.locateCenterOnScreen(pic_accept, confidence = 0.93)
  187. if p:
  188. slow_click(p)
  189. move_to_empty_area(lol_hwnd)
  190. # 客户端已最小化,正在启动游戏
  191. if lol_hwnd.size < ( 1024, 768):
  192. return True
  193. time.sleep( 1)
  194. # 等待太久,重新匹配
  195. if not stop_and_start_a_new_match(lol_hwnd):
  196. return False
  197. record_and_print_log( "10次超时未找到对局!")
  198. return False
  199. # 寻找对局 -> 队列中 -> 接受 -> 开始加载
  200. # 寻找对局 -> 队列中 -> 接受 -> 有人拒绝 -> 队列中
  201. def pg_find_match(lol_hwnd):
  202. click_find_match(lol_hwnd)
  203. return accept_match(lol_hwnd)
  204. def pg_wait_loading(lol_hwnd):
  205. pic = Image.open( r'scs\1_1.jpg')
  206. while True:
  207. # pyautogui 模块检测关卡
  208. box = pg.locateOnScreen(pic, confidence= 0.9)
  209. if box:
  210. return True
  211. time.sleep( 2)
  212. return True
  213. WaitStageFlag = True
  214. def change_wait_flag_callback():
  215. global WaitStageFlag
  216. record_and_print_log( "17分钟未检测到3-2回合,直接进行下一步操作")
  217. WaitStageFlag = False
  218. return True
  219. # 空城速八
  220. def pg_quick_wait_quit():
  221. global game_inactive_count
  222. print( "Start wait quit button")
  223. pic = Image.open( r'scs\quit.png')
  224. client_title = 'League of Legends (TM) Client'
  225. game_hwnd = pg.getWindowsWithTitle(client_title)[ 0]
  226. while True:
  227. # 让游戏处于活动状态
  228. check_game_active(game_hwnd)
  229. # 游戏被切换出去了,此时不操作鼠标键盘
  230. if game_inactive_count > 0:
  231. time.sleep( 5)
  232. continue
  233. box = pg.locateOnScreen(pic, confidence= 0.95)
  234. if box:
  235. slow_click(pg.center(box))
  236. break
  237. case = random.randint( 1, 100)
  238. # %50 概率游荡
  239. if case <= 50:
  240. stray()
  241. case = random.randint( 1, 100)
  242. # %50 概率发表情
  243. if case <= 50:
  244. show_emoji()
  245. # case = random.randint(1,100)
  246. # # %5 概率升级
  247. # if case >= 85 and case < 90:
  248. # upgrade_champ()
  249. sell_monsters()
  250. return True
  251. # 乱拿等死
  252. def pg_slow_wait_quit():
  253. global game_inactive_count
  254. print( "Start wait quit button")
  255. pic = Image.open( r'scs\quit.png')
  256. client_title = 'League of Legends (TM) Client'
  257. game_hwnd = pg.getWindowsWithTitle(client_title)[ 0]
  258. while True:
  259. # 让游戏处于活动状态
  260. check_game_active(game_hwnd)
  261. # 游戏被切换出去了,此时不操作鼠标键盘
  262. if game_inactive_count > 0:
  263. time.sleep( 5)
  264. continue
  265. box = pg.locateOnScreen(pic, confidence= 0.95)
  266. if box:
  267. slow_click(pg.center(box))
  268. break
  269. if game_inactive_count > 0:
  270. time.sleep( 5)
  271. continue
  272. case = random.randint( 1, 100)
  273. # %40 概率游荡
  274. if case <= 40:
  275. stray()
  276. if game_inactive_count > 0:
  277. time.sleep( 5)
  278. continue
  279. case = random.randint( 1, 100)
  280. # %25 概率买1个英雄
  281. if case >= 25 and case < 50:
  282. buy_single_champ(random.randint( 0, 4))
  283. # case = random.randint(1,100)
  284. # %0 概率刷新商店
  285. # if case == 0:
  286. # refresh_shop()
  287. if game_inactive_count > 0:
  288. time.sleep( 5)
  289. continue
  290. case = random.randint( 1, 100)
  291. # %30 概率发表情
  292. if case <= 30:
  293. show_emoji()
  294. if game_inactive_count > 0:
  295. time.sleep( 5)
  296. continue
  297. case = random.randint( 1, 100)
  298. # %5 概率升级
  299. if case >= 85 and case < 90:
  300. upgrade_champ()
  301. time.sleep( 1)
  302. return True
  303. # 速度投降
  304. def pg_wait_stage_3_2():
  305. global WaitStageFlag, game_inactive_count
  306. pic = Image.open( r'scs\3_2.jpg')
  307. WaitStageFlag = True
  308. # 启动一个Timer,17分钟未检测到3-2回合,直接进行下一步
  309. t = threading.Timer( 17 * 60, change_wait_flag_callback)
  310. t.start()
  311. client_title = 'League of Legends (TM) Client'
  312. game_hwnd = pg.getWindowsWithTitle(client_title)[ 0]
  313. while WaitStageFlag:
  314. # 让游戏处于活动状态
  315. check_game_active(game_hwnd)
  316. # 游戏被切换出去了,此时不操作鼠标键盘
  317. if game_inactive_count > 0:
  318. time.sleep( 5)
  319. continue
  320. # pyautogui 模块检测关卡
  321. box = pg.locateOnScreen(pic, confidence= 0.9)
  322. if box:
  323. # 检测到3-2,停止Timer
  324. t.cancel()
  325. return True
  326. if game_inactive_count > 0:
  327. time.sleep( 5)
  328. continue
  329. case = random.randint( 1, 100)
  330. # %40 概率游荡
  331. if case <= 40:
  332. stray()
  333. if game_inactive_count > 0:
  334. time.sleep( 5)
  335. continue
  336. case = random.randint( 1, 100)
  337. # %25 概率买1个英雄
  338. if case >= 25 and case < 50:
  339. buy_single_champ(random.randint( 0, 4))
  340. # case = random.randint(1,100)
  341. # %0 概率刷新商店
  342. # if case == 0:
  343. # refresh_shop()
  344. if game_inactive_count > 0:
  345. time.sleep( 5)
  346. continue
  347. case = random.randint( 1, 100)
  348. # %30 概率发表情
  349. if case <= 30:
  350. show_emoji()
  351. if game_inactive_count > 0:
  352. time.sleep( 5)
  353. continue
  354. case = random.randint( 1, 100)
  355. # %5 概率升级
  356. if case >= 85 and case < 90:
  357. upgrade_champ()
  358. time.sleep( 1)
  359. return True
  360. def close_award_interface(lol_hwnd):
  361. ok_box = (lol_hwnd.centerx - 100, lol_hwnd.bottom - 60, 200, 40)
  362. c = pg.center(ok_box)
  363. slow_click(c)
  364. move_to_empty_area(lol_hwnd)
  365. return True
  366. def pg_wait_surrender_finish(lol_hwnd):
  367. client_title = 'League of Legends (TM) Client'
  368. times = 0
  369. while True:
  370. time.sleep( 1)
  371. times += 1
  372. if pg.getWindowsWithTitle(client_title) == []:
  373. break
  374. if times % 10 == 0:
  375. print( "pg_wait_surrender_finish %d sec, still wait client over!"%times)
  376. # 检测结算界面是否打开
  377. while True:
  378. pic = Image.open( r'scs\end.jpg')
  379. box = pg.locateOnScreen(pic, confidence = 0.9)
  380. if box:
  381. break
  382. record_and_print_log( "Not Found end.jpg!")
  383. # 结算界面已打开,但被奖励界面遮挡
  384. if lol_hwnd.size == ( 1600, 900):
  385. record_and_print_log( "try to close_award_interface!")
  386. close_award_interface(lol_hwnd)
  387. time.sleep( 3)
  388. return True
  389. def pg_play_again(lol_hwnd):
  390. global box_play_again, box_empty_area
  391. center = convert_lol_to_destop_point(get_box_center(box_play_again), lol_hwnd)
  392. pg.click(center[ 0], center[ 1], duration = 0.3) # 点击再玩一次
  393. move_to_empty_area(lol_hwnd)
  394. time.sleep( 1)
  395. pic = Image.open( r'scs\end.jpg')
  396. pic_find_match = Image.open( r'scs\find_match.jpg')
  397. box = pg.locateOnScreen(pic_find_match, confidence= 0.9)
  398. while not box:
  399. if pg.locateOnScreen(pic, confidence = 0.9) != []:
  400. pg.click(center[ 0], center[ 1], duration = 0.3) # 点击再玩一次
  401. move_to_empty_area(lol_hwnd)
  402. else:
  403. # 奖励界面遮挡
  404. close_award_interface(lol_hwnd)
  405. time.sleep( 1)
  406. box = pg.locateOnScreen(pic_find_match, confidence= 0.9)
  407. return True
  408. def pg_stop_play():
  409. global AutoPalyFlag
  410. AutoPalyFlag = False
  411. return True
  412. # 手动结束脚本命令,按Ctrl+Alt+q即可设置停止运行标志
  413. kb.add_hotkey( 'ctrl+alt+q', pg_stop_play)
  414. def pg_main():
  415. global AutoPalyFlag, log_file
  416. w = get_lol_hwnd()
  417. if not w:
  418. print( "游戏未启动,请启动游戏后再运行脚本!")
  419. return False
  420. play_times = 0
  421. start_time = time.localtime()
  422. game_time_list = []
  423. # record_and_print_log("[%s] pg_find_match"%get_time_fmt_str())
  424. # pg_find_match(w)
  425. # record_and_print_log("[%s] pg_wait_loading"%get_time_fmt_str())
  426. # pg_wait_loading(w)
  427. # record_and_print_log("[%s] pg_quick_wait_quit"%get_time_fmt_str())
  428. # pg_quick_wait_quit()
  429. # record_and_print_log("[%s] pg_wait_surrender_finish"%get_time_fmt_str())
  430. # pg_wait_surrender_finish(w)
  431. # play_times += 1
  432. # record_and_print_log("[%s] pg_play_again"%get_time_fmt_str())
  433. # pg_play_again(w)
  434. while AutoPalyFlag:
  435. # 游戏开始时间
  436. game_start = time.time()
  437. record_and_print_log( "[%s] pg_find_match"%get_time_fmt_str())
  438. pg_find_match(w)
  439. record_and_print_log( "[%s] pg_wait_loading"%get_time_fmt_str())
  440. pg_wait_loading(w)
  441. case = random.randint( 1, 3)
  442. # case = 1
  443. if case == 1:
  444. record_and_print_log( "[%s] pg_wait_stage_3_2"%get_time_fmt_str())
  445. pg_wait_stage_3_2()
  446. record_and_print_log( "[%s] surrender"%get_time_fmt_str())
  447. surrender()
  448. record_and_print_log( "[%s] pg_wait_surrender_finish"%get_time_fmt_str())
  449. elif case == 2:
  450. record_and_print_log( "[%s] pg_quick_wait_quit"%get_time_fmt_str())
  451. pg_quick_wait_quit()
  452. elif case == 3:
  453. record_and_print_log( "[%s] pg_slow_wait_quit"%get_time_fmt_str())
  454. pg_slow_wait_quit()
  455. pg_wait_surrender_finish(w)
  456. play_times += 1
  457. record_and_print_log( "[%s] pg_play_again"%get_time_fmt_str())
  458. # 游戏结束时间
  459. game_end = time.time()
  460. game_time = int(game_end - game_start)
  461. game_time_list.append(game_time)
  462. if not AutoPalyFlag:
  463. break
  464. pg_play_again(w)
  465. # 统计每局时间,写入到文件
  466. for i in range(len(game_time_list)):
  467. seconds = game_time_list[i] % 60
  468. minutes = int(game_time_list[i] / 60)
  469. info = "第%d局用时[%d]分[%d]秒"%(i + 1, minutes, seconds)
  470. record_and_print_log(info)
  471. # 输出统计信息
  472. end_time = time.localtime()
  473. record_and_print_log( "[%s] 开始挂机"%get_time_fmt_str(start_time))
  474. record_and_print_log( "[%s] 结束挂机"%get_time_fmt_str(end_time))
  475. diff_time_sec = time.mktime(end_time) - time.mktime(start_time)
  476. t_s = int(diff_time_sec) % 60
  477. diff_time_sec /= 60
  478. # 总共所用分钟数
  479. total_minutes = diff_time_sec
  480. t_m = int(diff_time_sec) % 60
  481. diff_time_sec /= 60
  482. t_h = int(diff_time_sec)
  483. average_minutes = total_minutes / play_times
  484. t_ave_m = int(average_minutes)
  485. t_ave_s = int((average_minutes - t_ave_m) * 60)
  486. record_and_print_log( "共挂机[%d]小时[%d]分钟[%d]秒,挂机[%d]局,平均[%d]分钟[%d]秒一局"%(t_h, t_m, t_s, play_times, t_ave_m, t_ave_s))
  487. log_file.close()
  488. return True
  489. if __name__ == '__main__':
  490. pg_main()
  491. os.system( "pause")

测试程序:win10下打包好的最新程序和截图资源文件:某度网盘  提取码:lek7


转载:https://blog.csdn.net/qiximenghu/article/details/115534452
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场