如何让python让用户输入整数模拟按键脚本能输入到游戏

Python 做游戏脚本可以做得比按键精灵更快更好吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
已注册用户请 &
推荐学习书目
Python Sites
值得关注的项目
Python 编程
Python 做游戏脚本可以做得比按键精灵更快更好吗?
15:37:57 +08:00 · 6395 次点击
平时偶尔会玩某个 Windows 客户端游戏,后来嫌没时间赚金币打不过人民币玩家就很少玩了。某天心血来潮学了按键精灵,写个简单的脚本赚了好多金币,一下子就激活了我的兴趣,兴冲冲列了好多需求(我不知道我是对打游戏感兴趣还是对写代码感兴趣哈哈),结果发现按键论坛很多插件找起来很麻烦,有些要收费,文档也不清晰,在官方社区发帖问了几个问题没什么人回答,热情一下子被浇灭了。
最近我在学 Python 写服务器脚本,觉得 Python 真是无所不能,我想既然按键精灵可以做到的那 Python 应该也可以吧,而且按键精灵的运行进程太明显了,想封我应该挺简单。我分析了一下,我想要实现的功能无非是:
1 、让游戏客户端在后台运行,不影响我使用键鼠和软件,学习娱乐两不误。
2 、识别、提取文字和识别区域内的图片。
3 、简单的鼠标模拟输入,都是点点点。
4 、最复杂就是做个小窗口,实时输出日志,显示现在脚本跑到那一步了和现在赚了多少金币等游戏状态。
有没有人用 Python 做过这种游戏脚本?最好也了解按键精灵的知识,客观分析下用哪种语言做脚本会更快更好?
第 1 条附言 &·&
12:09:42 +08:00
评论好乱,很多评论都不知道答主支持哪个,希望大家尽量按这个格式回答:
一、我选 Python /我选按键 /我知道更好的语言;
二、我做过 /我知道 Python 或按键脚本可以做到原题目的 1/2/3/4 点;
三、最后就是吐槽啦。
第 2 条附言 &·&
12:35:37 +08:00
很多人没有回答我第四点,第四点很难做啊,我完全不知道脚本精灵能不能做到这一点 @@
这个窗口就是拿来滚动输出字符串的,就像 shell 或 console 一样,我自己能够 print 我预设的字符串出来。
我习惯写日志,那样我就不用手动打开 *.log ,也能实时看到脚本的输出信息。
比方说就是在 Windows 的桌面上,除了游戏窗口,还有一个 200*200 的小窗口,能够滚动输出 “现在已经匹配到对手了” “已经结束战斗” “正在等待对手” 这些文字。
第 3 条附言 &·&
11:27:32 +08:00
@@ 难道就没人来回答一下需求四那个实时输出框吗?
就像控制台一样滚动显示代码就行,不知道怎么实现,求思路方案
44 回复 &| &直到
15:19:43 +08:00
& & 16:25:33 +08:00
易语言专门做这个的
& & 16:29:36 +08:00
& & 16:30:13 +08:00
这不就是外挂了吗......
一般来说..外挂这种功利性东西...不要指望有啥人会分享这方面经验..
闷声发大财才是最吼的.
& & 16:40:10 +08:00
用 大漠插件
或者 天使插件
天使的主要功能都是免费的
最早用按键精灵调用天使,后来用 python 调用他来写过
& & 16:51:45 +08:00
我只会写 python 的黑窗口程序~~~
& & 17:09:40 +08:00
@ 我问的是二选一,你这样我就更纠结了:)
& & 17:10:37 +08:00
@ 看了一下,感觉不错,你是意思是 AutoHotKey 比那两个都要好?我先了解下
& & 17:11:42 +08:00
@ 虽然这不是作弊,但的确外挂了呢,你说的我也考虑过,难道只能摸着石头走路?但是我的功能都好简单的啊
& & 17:12:26 +08:00
@ 大漠插件 和 天使插件 都可以被 Python 调用?这两个插件没了解过呢,能简单说一下怎么调用吗
& & 17:12:43 +08:00
@ 那就帮我顶一下呗:)
& & 17:14:26 +08:00
窗口句柄 鼠标键盘消息 等等
& & 17:53:43 +08:00
按键精灵做的工作比你想象的要多得多, 模拟输入不单是发个 windows 消息就完了的,现在的客户端游戏都有反外挂机制, 很可能需要在驱动层模拟输入,甚至在驱动层反复 hook 纠缠。
另外如果要最小化后还能获取游戏数据, 你需要直接读取游戏进程的内存,或调用其函数。这就不是模拟输入了。
& & 19:18:51 +08:00
@ 可以看看这个文件,以前双十一写的。
项目的其他文件也可以参考,这个比较简单。我用的天使,天使的函数可以查看他的 chm 文档。
& & 20:09:36 +08:00
按键精灵现在的功能简直要逆天了。在游戏脚本方面,不得不服。以前粗略学过一段时间。
写这个东西,最主要的是思路。它的生态系统已经很强大了,谁更快更好不知道。但是没有必要再在 python 下面造轮子了,而且按键的学习成本也不高,好多小学没毕业的人都写游戏脚本来赚钱。
& & 20:39:00 +08:00
& & 20:56:05 +08:00
Python 有 bi 格.
按键精灵上手比较容易.
& & 21:23:48 +08:00
听说 lua 比较厉害
& & 21:28:38 +08:00 via Android
我在想一个问题,有没有这种按键精灵,因为有反外挂的机制,为了模拟输入各种纠结,为何不用 MCU 如 arhuino micro 等做成真正的受控键盘,主机通过串口等发送键位数据,然后像真正的键盘一样发按键,反外挂对这种硬件级的模拟没办法吧
& & 21:45:42 +08:00
@ 按键精灵有硬件版 叫按键盒子
& & 22:39:25 +08:00
了解下 UI 自动化测试,说简单点其实做的这是这种代替手来点点点的工作, python 下有相关的库来支撑 windows 程序的对象识别,或者实现 ocr 。
& & 09:18:58 +08:00 via Android
234 能做到,之前做过 fifaol3 自动买卡的,就是图像文字识别还是做不好。
& & 09:36:31 +08:00
& & 09:57:05 +08:00
第一次接触的代码就是按键精灵!!!!!
& & 10:20:59 +08:00
那你改写手机的吧 。。。。。。。手机端 触动精灵 体验要比按键精灵体验好 N 倍
& & 10:29:55 +08:00 via Android
@ 第二条,第三条,第四条。我是用 winapi 撸的,网上有现成的 python 做外挂的教程
& & 11:14:03 +08:00
1 和 2,3 有冲突吧?后台运行如何实现 2,3 中的功能?
& & 11:49:28 +08:00
按键精灵的大漠插件可以实现大部分的后台操作 原来写过类似的游戏脚本
大漠有免费版的, 应该够你用的了
& & 14:16:54 +08:00
@ @ 好,那我还是选择按键精灵了,但是我想问我的第四点,小窗口怎么做好呢
& & 14:26:58 +08:00
@ @ @ 那小窗口怎么实现,这个不知道怎么做好
& & 15:02:38 +08:00 via Android
我记得按键精灵里面可以做界面 直接拖控件 更新控件数值
& & 15:03:30 +08:00 via Android
@ 我也写了半自动的买卡,最后合卡炸了超大一个礼花,太棒了!
& & 16:38:08 +08:00
@ @ 哈哈我说的游戏就是 FIFA OL3 ,我看现成的辅助很多功能都满足不了我,所以就想自己弄一个了,我说的需求 4 有什么建议嚒
& & 17:34:15 +08:00 via Android
@ 那就好说了。。
弃坑吧。。贬值太快,要么烧钱要么被人玩。。
歪楼了
& & 00:15:47 +08:00
python 做不了,涉及到很底层的东西,调试以及反调试,系统驱动相关的东西 py 没法做。现在能用 winapi 投递消息的游戏没几个了。
& & 22:04:00 +08:00
@ 你说得很对,这游戏贬值太快,幸亏没充过钱
但是我迷上了用脚本打游戏怎么办:-)
& & 21:07:46 +08:00 via Android
@ 我用的是图像识别,但是太费劲了。老实说还是抓包分析比较靠谱。或者你可以先输入自己拥有的金额,然后仅仅判断购买成功的次数(同一个球员购买成功的包应该是一样的吧,一个猜想不一定对),再自己算一个大概的价格咯
& & 10:31:36 +08:00
@ 我的需求四是原题目里:
4 、最复杂就是做个小窗口,实时输出日志,显示现在脚本跑到那一步了和现在赚了多少金币等游戏状态。
& & 11:01:58 +08:00 via Android
@ 那金币数量(脚本执行结果)你是怎么知道的。有可能网络延时,或者你的笔记本没电了,直接强退了。怎么知道脚本执行一次的确达到了预期的效果
& & 12:26:16 +08:00
@ 看来重点说错了,我的关注点是做一个小窗口,这个窗口能输出字符串就好了,字符是什么没关系
就有点像 shell 一样,自己能够 print 字符串出来,我习惯写日志,那样我就不用总是手动打开 *.log 这样子
就比如说现在我匹配到了对手, Windows10 的桌面上除了游戏窗口还有一个 200*200 的小窗口,能够滚动输出“现在已经匹配到对手了”这样。
& & 12:36:35 +08:00
@ 貌似是模拟输入
& & 11:29:08 +08:00
@ 但我是 PC 端游
& &326 天前
有大兄弟回答一下我第四个问题嚒
求帮顶
& &133 天前 via Android
autopy 是控制鼠标的,不是控制窗体的,你游戏做多强的防护也白搭。
另外如果你用了模拟点击,你的图像分析算法一定要好。你的程序质量完全取决于你的算法。
& &84 天前
@ 我最近也在纠结这个问题。这过去好几个月了,想知道题主现在如何选择的?能留个联系方式吗?互相学习
& · & 1608 人在线 & 最高记录 3541 & · &
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.0 · 52ms · UTC 05:07 · PVG 13:07 · LAX 22:07 · JFK 01:07? Do have faith in what you're doing.Python的自动操作(挂机)脚本相关(一) - CSDN博客
Python的自动操作(挂机)脚本相关(一)
之前用了数个月VBS,受不了啦。听闻.py好使就试试看。
这是用Py的第五天。
爱搬码,非coder。
工具:Python3.4.0 + PyCharm + PyQt5.4.1
工具:Notepad++
环境:Win7
注:Notepad++写VBS时,防止代码中的中文乱码,必须设置“格式”—“以XXXX Little Endian 格式编码”。
1. 鼠标/键盘操作
从VBS过来的,先说用过的思路:
——————————————.VBS
请参考Demon的:
创建Excel对象,在VBA模块中调用WIN的API:
SetCursorPos / GetCursorPos / mouse_event
keybd_event
若要修改VBA模块中的代码,不够方便(人懒)
——————————————.Py
Python这边,安装对应版本的pywin32,就可调用win32api:
(对应Python3.4.0,windows要先安装Python3.4 pywin32-2XX) 本机219
import win32api
def LeftClick(x, y):
win32api.SetCursorPos((x, y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)
def PressOnce(x):
win32api.keybd_event(x, 0, 0, 0)
LeftClick(30, 30)
PressOnce(13)
PressOnce(9)
keycode/组合键等:
附:Python获取屏幕分辨率
import win32api
from win32api import GetSystemMetrics
def DisplaySize():
return GetSystemMetrics(0), GetSystemMetrics(1)
a, b = DisplaySize()
———————————————PyUserInput
搜到PyUserInput,好家伙,GitHub:
(安装PyUserInput之前必须先安装对应版本的pywin32和pyHook)
2. 屏蔽鼠标键盘输入
知道了能在VBS里调用api,于是听说可以弄到死机。
依样画葫芦,把这句塞到VBA模块代码里去,注意换行符:
——————————————.VBS
"Public Declare Function BlockInput Lib ""user32""
(Byval fBlock As Long) As Long " & vbCrLf & _
也该注意到了,用了user32.dll,哦也就是win的api这样。在VBS中使用:
oExcel.Run "BlockInput", True
wscript.Sleep 1000
oExcel.Run "BlockInput", False
——————————————.Py
Python3.4用user32.dll,就是windll,直接在ctypes里
from ctypes import *
user32 = windll.LoadLibrary('user32.dll')
user32.BlockInput(True)
time.sleep(1)
user32.BlockInput(False)
3. 检测/结束进程
——————————————.VBS
On Error Resume Next
for each ps in getobject("winmgmts:\\.\root\cimv2:win32_process").instances_
if Ucase(ps.name)=Ucase("123.exe") then
ps.terminate
WScript.Echo "死了没"
——————————————.Py
def process_exit(process_name):
p_checkresp = os.popen('tasklist /fo csv | find "' + process_name + '"').readlines()
return len(p_checkresp)
if process_exit(123.exe) == 0:
print("=0")
elif process_exit(123.exe) &= 1:
command = 'taskkill /F /IM 123.exe'
os.popen(command)
print("=1")
win32api.MessageBox(0, "用api弹出窗口消息")
4. 启动外部程序
Py和VBS都有几种方式启动外部的程序(.exe等)这里不列出了。
而某些软件启动的时候会挂上其他东西…
(非CS专业,不知道啊。是否环境变量不对、起始目录不对之类)
wshell普通的run启动后登陆报错,用Exec也登陆后报错,各种改参数没有效果。
最后搜到个命令行用start,微软界面
——————————————.VBS
如:C:\Program Files\12345\我是中文名的程序来砍我吖.exe
WshShell.run("%comspec% /k c: & cd \Program Files\12345 & start 我是中文名的程序来砍我吖.exe&")
命令行:”%comspec% /k
切换到程序所在盘(c:);
打开所在目录(cd
\Program Files\12345),最后start,登陆再也没有报错!
注意用“&”连接每条命令,也用“&”结束。
——————————————.Py
CreateProcess等方法不提,本例不适用。
Python的cmd不认cd
\Program Files\12345 里边的单个反斜杠换成转义“\\\\”(四条杠)也不行。
路径有中英文符号等等,要对字符进行判断。
def is_alphabet(uchar):
if (uchar &= u'\u0041' and uchar&=u'\u005a') or (uchar &= u'\u0061' and uchar&=u'\u007a'):
return True
return False
def is_number(uchar):
if uchar &= u'\u0030' and uchar&=u'\u0039':
return True
return False
def is_chinese(uchar):
if uchar &= u'\u4e00' and uchar&=u'\u9fa5':
return True
return False
def is_other(uchar):
if not (is_chinese(uchar) or is_number(uchar) or is_alphabet(uchar)):
return True
return False
根据以上弄了个拆文件路径的玩意:
def part_path(path):
if len(path) & 0:
gang_arr = []
gang_num = 0
for i in range(0, len(path)):
if is_other(path[i]):
if path[i] == "/":
gang_arr.append(i)
gang_num += 1
elif path[i] == ".":
sub_arr = []
for j in range(0, gang_num-1):
sub_arr.append(path[gang_arr[j] + 1: gang_arr[j+1]])
exe_name = path[gang_arr[gang_num-1] + 1:]
return path[0], exe_name, sub_arr
win32api.MessageBox(0, "请选择文件!")
disk_name, exe_name, dir_arr = part_path("C:\Program Files\12345\砍吖.exe")
(path不是随便输入的,用了PyQt中的QFileDialog获得文件路径。后面会讲)
学着VBS用start:
cmd = "cd/ & " + disk_name + ": &"
for i in range(0, len(dir_arr)):
cmd += "cd " + dir_arr[i] + " & "
cmd += "start " + exe_name
os.popen(cmd)
哦,用pyInstaller3.0打包成EXE(-w -F)调试的时候,发现前面有关检测/结束/启动进程用的所有os.popen(cmd)均没反应,不执行动作,搞不清原因,于是换subprocess.Popen(),顺带发现了”cwd=”这玩意,可以指定子进程工作路径了。参考:
先用个QPushbutton挂着QFileDialog来获取文件完整路径+文件名,内容放到LineEdit(类似文本框TextBox)里:
self.tb_line1 = QLineEdit()
self.btn_fileDiaLog = self.createButton("选择客户端文件", self.showDialog)
def showDialog(self):
filename = QFileDialog.getOpenFileName(self, "选取文件","F:/","EXE Files (*.exe);;All Files (*)")
self.tb_line1.setText(filename[0])
def createButton(self, text, member):
button = QPushButton(text)
button.clicked.connect(member)
return button
exe_dir = os.path.dirname(os.path.abspath(self.tb_line1.displayText()))
cmd = 'start '+ exe_name
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,cwd = exe_dir)
proc.stdin.write(cmd.encode())
proc.stdin.close()
os.path.dirname(os.path.abspath(“文件名”)): 表示获取当前文件夹的所在的目录。
比如完整文件路径:C:\Program Files\12345\砍吖.exe
abs_path就得到:C:\Program Files\12345
这样就不会报错啦,不用去拆文件路径的各个文件夹名。
本文已收录于以下专栏:
相关文章推荐
http://mp./s/dm8uXjHYJK1L6bNc8HmEXw
使用 Python 实现鼠标键盘自动化
本文演示了如何使用 Python 的 pyauto...
玩QQ桌球游戏时,有时候用鼠标控制鼠标指针的微小移动比较费劲儿,所以想写个程序,可以用键盘的上下左右键来控制鼠标的移动,每次只移动一个像素。
本脚本依赖pywin32、pyHook和pymouse这...
到Python的官网去下载并安装pip,下载地址是:https://pypi.python.org/pypi/pip#downloads
解压再解压,直到看到有setup.py文件了。
目前有两个模块:一个类似按键精灵的脚本,一个用aircv实现的图片位置定位脚本,利用这两个脚本可以在Windows上实现大部分的自动操作,比如点击图标等。来自我的github:https://gith...
第1 章 : 建站前的准备工作
课时1:阿里云ECS服务器建站概述07:37
课时2:快速建站流程12:37
课时3:安装Linux服务器管理工具WDCP11:26
第2 章 : 快速搭建个人...
Python 2.7.x
注意:pip升级后下载依赖包会报certificate verifyfailed
      解决办法是加入--trusted-host...
最近两天闲来无事,无聊在自己笔记本安装了虚拟机,用来挂lol刷金币。亲测成功。放一张运行的图片
首先我的笔记本比较渣,是联想的Y470,下图是我笔记本的配置(因为在虚拟机运行3d游戏与自己的本机的...
import win32api
import win32con
import win32gui
from ctypes import *
import time
VK_CODE = {
'back...
一、Python键盘输入模拟:
import win32api
import win32con
win32api.keybd_event(17,0,0,0)  #ctrl键位码是17
win32api...
LOL是一款非常火热的网游,但是不少玩家还是通过隔墙插真眼挂机人机刷金币,但是还是经常被判挂机,所以构思能不能搞个小程序控制鼠标和键盘的命令,每隔一段时间触发一次,从而避开系统的挂机检测。
本文通过...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)如何让python模拟按键脚本能输入到游戏? - 知乎10被浏览2334分享邀请回答13 条评论分享收藏感谢收起写回答1 个回答被折叠()python-sendkeys
模拟键盘事件的模块 - CSDN博客
python-sendkeys
模拟键盘事件的模块
因为特殊需要, 想找一套能简单发送键盘消息,模拟键盘操作的模块。& 类似于 C#.net& 或 VB& 的& sendKeys& 函数。
找了很久没有合适的。 参考了一些网上的资料,使用windows API&& SendInput 自已重新写了一个。
SendKeys2.py
8 from ctypes import *
9 import time
10 import win32con
11 import win32api
12 import win32ui
15 class KeyBdInput(Structure):
_fields_ = [
(&wVk&,c_ushort),
(&wScan&,c_ushort),
(&dwFlags&,c_ulong),
(&time&,c_ulong),
(&dwExtraInfo&,POINTER(c_ulong))
24 KEYEVENTF_EXTENDEDKEY = 0x0001
25 KEYEVENTF_KEYUP = 0x0002
26 KEYEVENTF_SCANCODE = 0x0008
27 KEYEVENTF_UNICODE = 0x0004
36 class HardwareInput(Structure):
_fields_ = [(&uMsg&, c_ulong),(&wParamL&, c_short),(&wParamH&, c_ushort)]
39 class MouseInput(Structure):
_fields_ = [(&dx&, c_long),(&dy&, c_long),(&mouseData&, c_ulong),(&dwFlags&, c_ulong),(&time&,c_ulong),(&dwExtraInfo&, POINTER(c_ulong))]
42 class Union_Input(Union):
_fields_ = [(&ki&, KeyBdInput),(&mi&, MouseInput),(&hi&, HardwareInput)]
45 class Input(Structure):
_fields_=[
(&type&,c_ulong),
(&ui&,Union_Input)
51 INPUT_MOUSE = 0
52 INPUT_KEYBOARD = 1
53 INPUT_HARDWARE = 2
58 def send_key_event(keyCode,isKeyup):
Inputs = Input * 1
inputs = Inputs()
inputs[0].type = INPUT_KEYBOARD
inputs[0].ui.ki.wVk = keyCode
if isKeyup == True:
inputs[0].ui.ki.dwFlags = KEYEVENTF_KEYUP
windll.user32.SendInput(1, pointer(inputs), sizeof(inputs[0]))
win32api.Sleep(3)
70 def KeyDown(keyCode):
send_key_event(keyCode,False)
73 def KeyUp(keyCode):
send_key_event(keyCode,True)
78 def KeyPress(keyCode,isShift):
if isShift == True:
send_key_event(win32con.VK_SHIFT,False)
send_key_event(keyCode,False)
send_key_event(keyCode,True)
if isShift == True:
send_key_event(win32con.VK_SHIFT,True)
88 def UniKeyPress(keyCode):
Inputs = Input * 2
inputs = Inputs()
inputs[0].type = INPUT_KEYBOARD
inputs[0].ui.ki.wVk = 0
inputs[0].ui.ki.wScan = keyCode
inputs[0].ui.ki.dwFlags = KEYEVENTF_UNICODE
inputs[1].type = INPUT_KEYBOARD
inputs[1].ui.ki.wVk = 0
inputs[1].ui.ki.wScan = keyCode
inputs[1].ui.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP
windll.user32.SendInput(2, pointer(inputs), sizeof(inputs[0]))
win32api.Sleep(5)
104 def SendString(Keys):
for c in Keys:
cC = ord(c)
if cC&=0 and cC&256:
vk = win32api.VkKeyScan(c)
if vk == -1:
UniKeyPress(cC)
if vk & 0:
vk = ~vk + 0x1
shift = ( vk && 8 & 0x1
if win32api.GetKeyState(win32con.VK_CAPITAL) & 0x1 == 0x1:
if ( c &= 'a' and c &= 'z' ) or ( c &= 'A' and c &= 'Z' ):
shift = not shift
KeyPress(vk & 0xFF , shift)
UniKeyPress(cC)
130 if __name__ == '__main__':
本文已收录于以下专栏:
相关文章推荐
最近需要模拟键盘鼠标的输入,一番查找之后,得到的一些结果
******************************************************************...
python小爬虫SendKey自动刷博刷视频
SendKeys简介
sendkeys是python的一个扩展包,其中有一些常用的符号来表示键盘的快捷键或者输入的字符,对于pywinauto来说,非常...
一、PyUserInput安装python3.5的PyMouse和PyKeyboard模块都集成到了PyUserInput模块中。在python3.5中,直接安装PyUserInput模块即可PyUs...
pywin安装模块:http://sourceforge.net/projects/pywin32/files/
import win32api
import win32con
之前在做自动化测试中需要用Python在linux中模拟Ctrl+V 进行路径粘贴,试了很多种方法,起初用了xerox和pyperclip这两个python库,但打开对话框后调用粘贴API无法进行粘贴...
Python 模拟键盘输入,留着备用。
#coding=utf-8
import win32gui,win32api,win32con
import time
import threading
资料在我们进行用python开发的时候我们可能需要模拟键盘操作,比如ppt自动翻页的功能。那么在这里就介绍python的模拟键盘。准备python_win32api。大概会用到win32gui,...
这段代码 driver.findElement(By.id(&kw&)).sendKeys(&123&);
出现的这个问题:
Exception in thread &main& java.lang....
一、Python键盘输入模拟:
import win32api
import win32con
win32api.keybd_event(17,0,0,0)  #ctrl键位码是17
win32api...
Python是一种容易入门的编程语言,对于已经掌握C/C++或Java等任意一门编程语言的程序员来说,通过Python官网的Tutorial文档,可以在较短时间内掌握基本语法。 
Ctypes是我喜欢...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)一步步用python制作游戏外挂 - blueel - 博客园
玩过电脑游戏的同学对于外挂肯定不陌生,但是你在用外挂的时候有没有想过如何做一个外挂呢?(当然用外挂不是那么道义哈,呵呵),那我们就来看一下如何用python来制作一个外挂。。。。
我打开了4399小游戏网,点开了一个不知名的游戏,唔,做寿司的,有材料在一边,客人过来后说出他们的要求,你按照菜单做好端给他便好~ 为啥这么有难度?8种菜单记不清,点点就点错,鼠标还不好使肌肉劳损啥的伤不起啊&&
首先要声明,这里的游戏外挂的概念,和那些大型网游里的外挂可不同,不能自动打怪,不能喝药不能躲避GM&& 那做这个外挂有啥用?问的好,没用,除了可以浪费你一点时间,提高一下编程技术,增加一点点点点点点的做外挂的基础以外,毫无用处,如果您是以制作一个惊天地泣鬼神不开则已一开立刻超神的外挂为目标过来的话,恐怕要让您失望了,请及早绕道。我的目的很简单,就是自动玩这款小游戏而已。
工具的准备
需要安装autopy和PIL以及pywin32包。autopy是一个自动化操作的python库,可以模拟一些鼠标、键盘事件,还能对屏幕进行访问,本来我想用win32api来模拟输入事件的,发现这个用起来比较简单,最厉害的是它是跨平台的,请搜索安装;而PIL那是大名鼎鼎了,Python图像处理的No.1,下面会说明用它来做什么;pywin32其实不是必须的,但是为了方便(鼠标它在自己动着呢,如何结束它呢),还是建议安装一下,哦对了,我是在win平台上做的,外挂大概只有windows用户需要吧?截屏和图像处理工具截屏是获取游戏图像以供分析游戏提示,其实没有专门的工具直接Print Screen粘贴到图像处理工具里也可以。我用的是PicPick,相当好用,而且个人用户是免费的;而图像处理则是为了获取各种信息的,我们要用它得到点菜图像后保存起来,供外挂分析判断。我用的是PhotoShop& 不要告诉Adobe,其实PicPick中自带的图像编辑器也足够了,只要能查看图像坐标和剪贴图片就好饿了,只不过我习惯PS了~编辑器这个我就不用说了吧,写代码得要个编辑器啊!俺用VIM,您若愿意用写字板也可以&&原理分析
外挂的历史啥的我不想说啦,有兴趣请谷歌或度娘(注:非技术问题尽可以百度)。
看这个游戏,有8种菜,每种菜都有固定的做法,顾客一旦坐下来,头顶上就会有一个图片,看图片就知道他想要点什么菜,点击左边原料区域,然后点击一下&&不知道叫什么,像个竹简一样的东西,菜就做完了,然后把做好的食物拖拽到客户面前就好了。
顾客头上显示图片的位置是固定的,总共也只有四个位置,我们可以逐一分析,而原料的位置也是固定的,每种菜的做法更是清清楚楚,这样一来我们完全可以判断,程序可以很好的帮我们做出一份一份的佳肴并奉上,于是钱滚滚的来:)
autopy介绍
github上有一篇很不错的入门文章,虽然是英文但是很简单,不过我还是摘几个这次用得到的说明一下,以显示我很勤劳。
1 import autopy
2 autopy.mouse.move(100, 100) # 移动鼠标
3 autopy.mouse.smooth_move(400, 400) # 平滑移动鼠标(上面那个是瞬间的)
这个命令会让鼠标迅速移动到指定屏幕坐标,你知道什么是屏幕坐标的吧,左上角是(0,0),然后向右向下递增,所以屏幕的右下角坐标是&&你猜对了,是()。
不过有些不幸的,如果你实际用一下这个命令,然后用autopy.mouse.get_pos()获得一下当前坐标,发现它并不在(100,100)上,而是更小一些,比如我的机器上是(97,99),和分辨率有关。这个移动是用户了和windows中mouse_event函数,若不清楚api的,知道这回事就好了,就是这个坐标不是很精确的。像我一样很好奇的,可以去读一下autopy的源码,我发现他计算绝对坐标算法有问题:
point.x *= 0xFFFF / GetSystemMetrics(SM_CXSCREEN);这里先做除法再做乘法,学过一点计算方法的就应该知道对于整数运算,应该先乘再除的,否则就会产生比较大的误差,如果他写成:
point.x = point.x * 0xffff / GetSystemMetrics(SM_CXSCREEN);就会准多了,虽然理论上会慢一点点,不过我也懒得改代码重新编译了,差几个像素,这里对我们影响不大~咱要吸取教训呀。
1 #引入autopy模块
3 import autopy
4 autopy.mouse.click() # 单击
5 autopy.mouse.toggle(True) # 按下左键
6 autopy.mouse.toggle(False) # 松开左键
这个比较简单,不过记得这里的操作都是非常非常快的,有可能游戏还没反应过来呢,你就完成了,于是失败了&& 所以必要的时候,请sleep一小会儿。
我们这次没用到键盘,所以我就不说了。怎么做?分析顾客头上的图像就可以,来,从获取图像开始吧~
打开你钟爱的图像编辑器,开始丈量吧~ 我们得知道图像在屏幕的具体位置,可以用标尺量出来,本来直接量也是可以的,但是我这里使用了画面左上角的位置(也就是点1)来当做参考位置,这样一旦画面有变动,我们只需要修改一个点坐标就好了,否则每一个点都需要重新写一遍可不是一件快乐的事情。
看最左边的顾客头像上面的图像,我们需要两个点才可确定这个范围,分别是图像的左上角和右下角,也就是点2和点3,。后面还有三个顾客的位置,只需要简单的加上一个增量就好了,for循环就是为此而生!
同样的,我们原料的位置,&竹席&的位置等等,都可以用这种方法获得。注意获得的都是相对游戏画面左上角的相对位置。至于抓图的方法,PIL的ImageGrab就很好用,autopy也可以抓图,为什么不用,我下面就会说到。
我们这个外挂里相当有难度的一个问题出现了,如何知道我们获得的图像到底是哪一个菜?对人眼&&甚至狗眼来说,这都是一个相当easy的问题,&一看就知道&!对的,这就是人比机器高明的地方,我们做起来很简单的事情,电脑却傻傻分不清楚。autopy图像局限
如果你看过autopy的api,会发现它有一个bitmap包,里面有find_bitmap方法,就是在一个大图像里寻找样品小图像的。聪明的你一定可以想到,我们可以截下整个游戏画面,然后准备所有的菜的小图像用这个方法一找就明白哪个菜被叫到了。确实,一开始我也有这样做的冲动,不过立刻就放弃了&&这个方法查找图像,速度先不说,它有个条件是&精确匹配&,图像上有一个像素的RGB值差了1,它就查不出来了。我们知道flash是矢量绘图,它把一个点阵图片显示在屏幕上是经过了缩放的,这里变数就很大,理论上相同的输入相同的算法得出的结果肯定是一致的,但是因为绘图背景等的关系,总会有一点点的差距,就是这点差距使得这个美妙的函数不可使用了&&
好吧,不能用也是好事,否则我怎么引出我们高明的图像分析算法呢?
相似图像查找原理
相信你一定用过Google的&按图搜图&功能,如果没有,你就落伍啦,快去试试!当你输入一张图片时,它会把与这张图相似的图像都给你呈现出来,所以当你找到一张中意的图想做壁纸又觉得太小的时候,基本可以用这个方法找到合适的~
我们就要利用和这个相似的原理来判断用户的点餐,当然我们的算法不可能和Google那般复杂,知乎上有一篇很不错的文章描述了这个问题,有兴趣的可以看看,我直接给出实现:
1 def get_hash(self, img):
#使用PIL模块缩放图片,***
image = img.resize((18, 13), Image.ANTIALIAS).convert("L")
pixels = list(image.getdata())
avg = sum(pixels) / len(pixels)
return "".join(map(lambda p : "1" if p & avg else "0", pixels))
因为这是类的一个方法,所以有个self参数,无视它。这里的img应该传入一个Image对象,可以使读入图像文件后的结果,也可以是截屏后的结果。而缩放的尺寸(18,13)是我根据实际情况定的,因为顾客头像上的菜的图像基本就是这个比例。事实证明这个比例还是挺重要的,因为我们的菜有点儿相似,如果比例不合适压缩后就失真了,容易误判(我之前就吃亏了)。
得到一个图片的&指纹&后,我们就可以与标准的图片指纹比较,怎么比较呢,应该使用&汉明距离&,也就是两个字符串对应位置的不同字符的个数。实现也很简单&&
def hamming_dist(self, hash1, hash2):
return sum(itertools.imap(operator.ne, hash1, hash2))好了,我们可以用准备好的标准图像,然后预先读取计算特征码存储起来,然后再截图与它们比较就好了,距离最小的那个就是对应的菜,代码如下:
def order(self, i):
l, t = self.left + i * self.step, self.top
r, b = l + self.width, t + self.height
hash2 = self.get_hash(ImageGrab.grab((l, t, r, b)))
(mi, dist) = None, 50
for i, hash1 in enumerate(self.maps):
if hash1 is None:
this_dist = self.hamming_dist(hash1, hash2)
if this_dist & dist:
dist = this_dist
这里有一个50的初始距离,如果截取图像与任何菜单相比都大于50,说明什么?说明现在那个位置的图像不是菜,也就是说顾客还没坐那位置上呢,或者我们把游戏最小化了(老板来了),这样处理很重要,免得它随意找一个最相近但又完全不搭边的菜进行处理。
这个问题很简单,我们只需要把菜单的原料记录在案,然后点击相应位置便可,我把它写成了一个类来调用:
1 class Menu:
def __init__(self):
self.stuff_pos = []
self.recipes = [None] * 8
self.init_stuff()
self.init_recipe()
def init_stuff(self):
for i in range(9):
self.stuff_pos.append( (L + 102 + (i % 3) * 42, T + 303 + (i / 3) * 42) )
def init_recipe(self):
self.recipes[0] = (1, 2)
self.recipes[1] = (0, 1, 2)
self.recipes[2] = (5, 1, 2)
self.recipes[3] = (3, 0, 1, 2)
self.recipes[4] = (4, 1, 2)
self.recipes[5] = (7, 1, 2)
self.recipes[6] = (6, 1, 2)
self.recipes[7] = (8, 1, 2)
def click(self, i):
autopy.mouse.move(self.stuff_pos[i][0] + 20, self.stuff_pos[i][1] + 20)
autopy.mouse.click()
def make(self, i):
for x in self.recipes[i]:
self.click(x)
autopy.mouse.move(L + 315, T + 363)
autopy.mouse.click()
这是本外挂中最没技术含量的一个类了:)请原谅我没有写注释和doc,因为都很简单,相信你懂得。实在不懂的话,推荐你去看一下&,这里有很详细的python知识}

我要回帖

更多关于 python 让用户输入 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信