python钢琴块自动脚本


前言
     人在美国,刚下飞机,在等行李的时候写下这篇博客,纪念一下我长达两天的踩坑史,以及一种新的思维,面向百度编程,本文介绍的是如何用python做钢琴块脚本,用到模块有

  • PIL模块
  • numpy模块
  • ctypes模块(使用动态链接库)

正文
    好,接下来就开始漫长的踩坑史了,Are you ready?
ADB坑
    一开始,我想的是在手机上进行触屏操作,还别说,真有这东西

工具包我打包了,点击此处下载 密码:xsx3

放在你的工作目录下(其实可以不用全放的,但是全放肯定没问题) ,手机打开usb 调试,
然后打开ADBDriverInstaller.exe:

图片点击之后就可以关闭了

进入工作目录,cmd,输入命令:

adb shell

出现一大串参数就代表没问题,

介绍几个会用到的adb命令:

//(保存到SDCard)
adb shell /system/bin/screencap -p /sdcard/screenshot.png
// 从SD卡导出到电脑,注意 F:\\mvp 为电脑路径,必须存在
adb pull /sdcard/screenshot.png F:\\mvp(保存到电脑)
//在(x,y)处模拟点击
adb shell input tap x y

然后在介绍下 PIL模块:

from PIL import Image
import numpy as np

path=""	#path为图片路径
img=np.array(Image.open(path))#img为这张图片的三维矩阵[y][x][r,g,b]

如果在某一点的rgb相加小于100,那么它就是可以点击的地方,即为黑色方块。纵坐标固定,横坐标检查四个点对应四列,要不是因为我测试了一下截一张图传到电脑上要两秒,点击一下要一秒,我差点就兴奋了,怎么玩,一次要三秒,开什么玩笑,还不如手玩,果断认同放弃ADB

     于是我苦思冥想,痛定思痛,终于灵光一现,有没有一种方法,是可以直接在电脑上操作手机,而不需要向ADB这么慢的呢,很庆幸,答案是有的!!!傲软投屏,满足你的一切需求,支持逆向操作!! 界面如图:
在这里插入图片描述

利用鼠标可以模拟手机点击,果断百度python 如何操作鼠标,有一个库是pyhook,刚好满足这种需求,结果我编译器安装失败,百度一看
在这里插入图片描述
原文链接https://www.cnblogs.com/nymrli/p/9557023.html
哈哈哈,如果一个钩子算邪恶,那windows API岂不是罪大恶极?该放弃时就要放弃,稍加思索,决定写一个动态链接库来操作鼠标点击,新建一个文件夹命名为Pro1,新建一个文件命名为Click.c放在Pro1文件夹下。Click.c内容如下

#include<windows.h>
#include<stdio.h>

void click(int x,int y){//定义一个方法,传坐标参数
	SetCursorPos(x, y);//移动鼠标到(x,y)
	mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);//鼠标左键点击

}

这里稍微介绍一下mouse_even,原文链接https://blog.csdn.net/THmen/article/details/78249422

然后用gcc 把它编译成动态链接库,步骤如下:

  1. 打开cmd,进入Pro1目录下
  2. 输入命令
  3. gcc -m64 -shared Click.c -o Click.dll//如果python是32位的就用-m32
  4. 回车

然后就发现在你的Pro1目录下有一个Click.dll文件了

如何用这个动态库呢

安装ctypes模块,pycharm界面如下:
在这里插入图片描述
来测试一下这个点击的速度吧,在Pro文件夹下新建test.py

from ctypes import  *
import  _thread	#这个模块需要安装
import time

test=CDLL("./Click.dll")
class date:
	Count=0	#存储点击次数

def t(name,n):#至少要两个参数,随便填
	while True:
		test.click(500,500)
		date.Count+=1
_thread.start_new_thread(t,("ll",1))
time.sleep(1)#过一秒
print("在一秒钟之内点击了{n}下".format(n=date.Count))

这里是引用

除去加载图片的时间,也绰绰有余了木有,哈哈,很好的开端,为了少走弯路,使数据计算的更简单,我们要耍点聪明,把傲软录屏拖到左上角,如图:
在这里插入图片描述
在这里插入图片描述
尽量保持手机左上角和电脑屏幕左上角对齐,此时坐标为(0,0),经过测验,右下角坐标为(450,805),数据出来直接上整代码

import numpy as np
from PIL import ImageGrab
from ctypes import *

BOX=(0,699,450,701)
screen=np.array(ImageGrab.grab(BOX)#截取纵坐标从699到701,横坐标为0到450的屏幕区域
click=CDLL("./Click.dll")
def click(x,y):#自定义鼠标点击方法,引用Click动态链接库
	click.click(x,y)

def judge(x,y):#判断(x,y)是不是深色像素
	sum=int(screen[y][x][0])+int(screen[y][x][1])+int(screen[y][x][2])	#要强转型为int 原型为0~255的类型,这里对(x,y)这个像素点的rgb求和,纯黑为(0,0,0)
	if(sum<=100):#如果为深色

        return True
    return False
while True:
	screen=np.array(ImageGrab.grab(BOX)#不断更新选屏区
	for n in range(0,4):
		if(judge(int(56.25+N*113),1)):#经过不断计算,发现横坐标取这四个点最为合适,纵坐标实际上为699+1
			click(45 + 90 * n, 565)#此处进行了单位转换,上面的单位是像素点,这里的我也不知道是什么,数据是经过计算得出的,我用着没事

至此,只能说大概完成了,但是还有bug,当我按下一个黑色方块后,下一帧的时候,我又会接着去按那个按过了的方块,所以要杜绝这种情况的发生,代码修改如下:

import numpy as np
from PIL import ImageGrab
from ctypes import *

BOX=(0,699,450,701)
screen=np.array(ImageGrab.grab(BOX)#截取纵坐标从699到701,横坐标为0到450的屏幕区域
click=CDLL("./Click.dll")
def click(x,y):#自定义鼠标点击方法,引用Click动态链接库
	click.click(x,y)

def judge(x,y):#判断(x,y)是不是深色像素
	sum=int(screen[y][x][0])+int(screen[y][x][1])+int(screen[y][x][2])	#要强转型为int 原型为0~255的类型,这里对(x,y)这个像素点的rgb求和,纯黑为(0,0,0)
	if(sum<=100):#如果为深色

        return True
    return False
N=-1#上一帧点击了哪一列的方块,初始值为-1
while True:
	screen=np.array(ImageGrab.grab(BOX)#不断更新选屏区
	for n in range(0,4):
		if(judge(int(56.25+N*113),1)):#经过不断计算,发现横坐标取这四个点最为合适,纵坐标实际上为699+1
			if(n!=N):#如果上一帧的所在列和现在的不同
				N=n#更改N
				click(45 + 90 * n, 565)#此处进行了单位转换,上面的单位是像素点,这里的我也不知道是什么,数据是经过计算得出的,我用着没事

到这里,已经差不多了,但是如果万的分数多了,就会出现一个问题,
比如,这一次我点击了第三列,但是我领了金币之后,下一个方块又从第三列下来,那么照它的逻辑,就game over!!了,所以得杜绝,更改如下

import numpy as np
from PIL import ImageGrab
from ctypes import *

BOX=(0,699,450,701)
screen=np.array(ImageGrab.grab(BOX)#截取纵坐标从699到701,横坐标为0到450的屏幕区域
click=CDLL("./Click.dll")
def click(x,y):#自定义鼠标点击方法,引用Click动态链接库
	click.click(x,y)

def judge(x,y):#判断(x,y)是不是深色像素
	sum=int(screen[y][x][0])+int(screen[y][x][1])+int(screen[y][x][2])	#要强转型为int 原型为0~255的类型,这里对(x,y)这个像素点的rgb求和,纯黑为(0,0,0)
	if(sum<=100):#如果为深色

        return True
    return False
N=-1#上一帧点击了哪一列的方块,初始值为-1
canC=False#是否可以点击
while True:
	screen=np.array(ImageGrab.grab(BOX)#不断更新选屏区
	for n in range(0,4):
		if(judge(int(56.25+N*113),1)):#经过不断计算,发现横坐标取这四个点最为合适,纵坐标实际上为699+1
			if(n!=N):#如果上一帧的所在列和现在的不同
				N=n#更改N
				canC=True
				click(45 + 90 * n, 565)#此处进行了单位转换,上面的单位是像素点,这里的我也不知道是什么,数据是经过计算得出的,我用着没事
		if (canC):
            if(judge(int(56.25+N*113),1)==False ):
                N=-1
                canC=False

至此,就没什么太大了的问题了,建议运行的时候电脑保持流畅,我最高跑了小星星 1073分




来闲扯两句,其实我不怎么用python的,搭建神经网络的时候用了下python,然后大一下学期的时候左字符串动画用了下,现在快大二了,小专科一个,能活到现在,多亏了度娘,这两天左这个东西,完全就是突发奇想,百度了两天,跑到1000多分的时候我已经兴奋了,本来是想着插上USB,再最后垂死挣扎一下,然后洗洗睡的,结果稍微改了下还跑成功了,差点喜极而泣,谢谢谢谢,已经语无伦次了,如果我这篇博客能帮到你,我会更开心


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM