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