实现功能:
- 自动进入游戏(必须使用wegame登录,wegame在窗口最前,游戏是最新版本)
- 自动寻找冰火遗迹房间
- 识别房间内是否存在大哥 没有就会自动退出当前房间换下一个
- 可以即时向指定qq发送当前状况
- **切记要以管理员身份运行脚本**
#AutoReady.py
import sys
import pyautogui as pag
import time
import banner
import os
import keyboard
import ToQQ
from datetime import datetime
import RemoveAdvert
import random
'''
windous桌面分辨率 1920 * 1080
游戏窗口化 1024 * 768
手动把窗口放在桌面左上角
'''
class AutoReady:
gameCount = 0 #统计进入游戏次数
gameStatu = 0 #如果大于等于2则会结束然后重启游戏
toqq = ToQQ.ToQQ() # 向qq发送消息
ra = RemoveAdvert.RemoveAdvert()
# 废弃使用 gameReadyFlag = 0 #防止一轮循环中多次播报进入游戏次数
def __init__(self):
pag.FAILSAFE = True # 启用自动防故障功能,将鼠标移到屏幕的左上角(0,0),抛出failSafeException异常
pag.PAUSE = 0.5 #设置操作之间的延迟持续时间,默认为0.1 这里要设置慢一点 不然可能会极短时间内点击两处 导致出现问题
b = banner.Banner().printBanner() #调用logo
# print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
def moveAndClick(self,x,y):
'''
移动加点击 直接点击可能会无效果
'''
pag.moveTo(x, y) #移动
pag.click()
def selectReady(self):
'''
准备
'''
val = pag.locateOnScreen('CFimg\\zhunbei.png', region=(675,550, 400, 100), confidence=0.8)
if val is not None:
print("\n游戏已经准备! ")
return pag.center(val)
def selectGoing(self):
'''
加入游戏
'''
val = pag.locateOnScreen('CFimg\\jiaruyouxi.png', region=(675,550, 400, 100), confidence=0.8)
if val is not None:
print("\n直接加入游戏! ")
return pag.center(val)
def isInGaming(self):
'''
60s内判断是否进入游戏
'''
for i in range(0,15):
sys.stdout.flush() #缓冲区刷新 因为print会先存入缓冲区满再打印
iIG = pag.locateOnScreen('CFimg\\IsInGaming_bag.png', region=(400, 700, 200, 800), confidence=0.5)
if iIG is not None:
self.gameCount += 1
print(f"\n成功进入游戏! 第[{self.gameCount}]次进入游戏")
self.toqq.sendMsg(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n第[{self.gameCount}]次进入游戏",'0x6A')
# print("QQ消息发送失败,请保证备注设置正确并且已打开聊天窗口")
return True
else:
if(i == 0):
print("正在等待进入游戏",end="")
else:
if(i == 10): print("\n第30秒",end="")
print(".",end="")
time.sleep(3)
print("\n仍然然没有进入游戏 原因未知 程序即将开始下一轮检测")
# print("如果长时间没有进入游戏 则会主动结束游戏进程然后重新连接")
print("如果已经进入游戏 请忽略该提示")
def startGame(self,clickArea):
'''
clickArea 传入的进入游戏按钮位置
若不为空 则执行本函数
'''
#clickArea 即 传入的进入游戏按钮位置
if clickArea is not None:
self.moveAndClick(clickArea.x, clickArea.y)
self.isInGaming()
else:
return
def runGame(self):
'''
启动游戏
'''
#获取wegame的启动按钮
runGame = pag.locateOnScreen('CFimg\\runGame.png', region=(0, 0, 1920, 1080), confidence=0.4)
if runGame != None:
rgXY = pag.center(runGame)
self.moveAndClick(rgXY.x,rgXY.y)
#获取游戏窗口并拖动至左上角
gameWindow = None
while(gameWindow is None):
gameWindow = pag.locateOnScreen('CFimg\\isInHall.png', region=(0, 0, 1920, 1080), confidence=0.6)
print(".",end="")
time.sleep(1)
gwXY = pag.center(gameWindow)
pag.moveTo(gwXY.x, gwXY.y-30 , random.uniform(0.2, 0.5), pag.easeOutQuad)
# 在1~2秒内把窗口拖拽到左上角
pag.dragTo(100, 20, random.uniform(0.3, 0.6), button='left')
return True
return False
def screenAndStart(self):
'''
循环等待
'''
while(True):
time.sleep(2)
#关闭干扰项
#在大厅中或者是退出游戏后 才需要去除干扰或是进入游戏
if(self.ra.isInHall()):
#检测游戏是否在运行
if(self.ra.getGameStatu() != True):
#游戏没在运行
self.toqq.sendMsg("检测到游戏已掉线,正在准备重新登陆...","0x6A")
print("检测到游戏未在运行 请登陆WeGame,并置于前页 准备启动游戏")
if self.runGame() != True:
continue
print("\n游戏已启动!")
self.toqq.sendMsg("游戏重连成功!","0x6A")
#去除干扰项
adArea = self.ra.findAdvert()#获取干扰区域位置
if adArea is not None:
self.moveAndClick(adArea.x,adArea.y)
continue # 存在多个干扰的话 需要全部解决后再开始游戏
# 准备
self.startGame(self.selectReady())
# 加入游戏
self.startGame(self.selectGoing())
def cLickAll(self):
self.screenAndStart()
if __name__ == '__main__':
a = AutoReady()
a.cLickAll()
#RemoveAdvert.py
import pyautogui as pag
import ToQQ
from datetime import datetime
import time
import keyboard
import psutil
import os
'''
该类中包含点击客户端下的各种广告(例如确认、取消等)
以及自动判断房内有无大哥
掉线重连(待续)
'''
class RemoveAdvert:
toqq = ToQQ.ToQQ()
# start F:\WeGameApp\cf\cross" "fire\穿越火线\x64\crossfire.exe
# 引入psutil模块
# 判断某个程序是否在运行
# 原理:获取正在运行程序的pid,通过pid获取程序名,再按程序名进行判断
# def ifProcessRunning(process_name):
# pl = psutil.pids()
# result = "PROCESS_IS_NOT_RUNNING"
# for pid in pl:
# if (psutil.Process(pid).name() == process_name):
# if isinstance(pid, int):
# result = "PROCESS_IS_RUNNING"
# return result
def getGameStatu(self):
'''
获取当前穿越火线的运行状态
正在运行返回True 否则返回False
'''
if len(os.popen(f'tasklist | findstr crossfire.exe').readline()) > 0:
return True
return False
def moveAndClick(self,x,y):
'''
移动加点击 直接点击可能会无效果
'''
pag.moveTo(x, y) #移动
pag.click()
def isInHall(self):
'''
是否在大厅中 左上角穿越火线标志
'''
iIG = pag.locateOnScreen('CFimg\\IsInGaming_bag.png', region=(400, 700, 200, 800), confidence=0.5)
return iIG is None #Ture说明在大厅中
def exitRoom(self):
'''
退出当前房间
'''
e = pag.locateOnScreen("CFimg\exitRoom.png", region=(800, 10, 1024, 100), confidence=0.5)
if e is not None:
eXY = pag.center(e)
self.moveAndClick(eXY.x, eXY.y)
self.toqq.sendMsg(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} \n 检测到异常状况 退出房间", '0x6A')
time.sleep(2) #退出房间后稍等一下 不然可能会再点一次进入游戏 导致卡顿半分钟
def exitGame(self):
'''
角色死亡 可以引申到该退出游戏
'''
e = pag.locateOnScreen("CFimg\dead.png", region=(325, 480, 375, 120), confidence=0.5)
return e is not None
def findAdvert(self):
'''
寻找干扰截图 如果存在则返回它的x,y坐标 如果没有返回None
这里会很大的影响程序运行速度
'''
adverts = [
#写成数组方便后续补充
'guanbi.png',
'queding.png',
'quxiao.png',
'quxiao02.png',
'quxiao03.png',
'queren.png',
'dead.png',
'host.png', #注意检测房主要放在切换大厅之前 不然可能在选择房间时出现问题
'selectGame.png',
'guanbi02.png',
'queding02.png',
'switchHall.png', #注意切换大厅一定要在快速加入后面 不然会一直点击旧版大厅
'queren2.png',
'queren3.png', #与主机链接失败
]
for advert in adverts:
ad = pag.locateOnScreen("CFimg\\"+advert, region=(150,0, 900, 800), confidence=0.7,grayscale=True)
if ad is not None:
# 是房主了 换房
if advert == 'host.png':
self.exitRoom()
return
# 角色死亡 换房
if advert == 'dead.png':
keyboard.press_and_release('esc')
time.sleep(0.2)
keyboard.press_and_release('enter')
time.sleep(0.2)
keyboard.press_and_release('enter')
time.sleep(0.2)
while (self.isInHall() == False):
# 如果退出游戏后卡住 找不到大厅标志物就会一直在这里死循环
time.sleep(0.5)
self.exitRoom()
return
return pag.center(ad) #找到可点击的干扰物 返回它的坐标
#TestFunction.py
import os
import win32gui
import win32con
'''
本程序中限制只能操作穿越火线
'''
def isProcessRunning(process_name):
'''
isProcessRunning("*.exe"):
正在运行则返回True 否则返回False
'''
process_name = "crossfire"
if len( os.popen(f'tasklist | findstr {process_name}').readline() ) > 0:
return True
return False
def killProcess(process_name):
process_name = "crossfire.exe"
try:
os.system(f'taskkill /F /IM {process_name}')
except:
print(f"未检测到[{process_name}]正在运行")
def startProcess(process_name):
process_name = "crossfire.exe"
if isProcessRunning(process_name) == False:
os.system(f'start F:\WeGameApp\cf\cross" "fire\穿越火线\\x64\crossfire.exe')
return True
print("程序已经运行中!")
return False
def test():
hwnd = win32gui.FindWindow(None,"WeGame")
print(hwnd)
hChild = win32gui.FindWindowEx(hwnd, hwndChildAfter=0, lpszClass=None, lpszWindow=None) # 查找子窗口,返回值为0表示未找到子窗口
print(hChild)
# print(os.popen('tasklist | findstr *.exe').readlines()
# os.system('taskkill /F /IM *.exe')
if __name__ == '__main__':
test()
#ToQQ.py
import time
import win32gui
import win32con
import win32clipboard as w
class ToQQ:
def sendMsg(self,msg,name):
'''
(发送内容,备注)
需要打开聊天框 可以最小化
'''
# 将测试消息复制到剪切板中
# 窗口名字,就是备注名
# name = "0x6A"
# 将测试消息复制到剪切板中
w.OpenClipboard()
w.EmptyClipboard()
w.SetClipboardData(win32con.CF_UNICODETEXT, msg)
w.CloseClipboard()
# 获取窗口句柄
handle = win32gui.FindWindow(None, name)
# 点击输入框
if handle:
# 填充消息
win32gui.SendMessage(handle, 770, 0, 0)
# 回车发送消息
win32gui.SendMessage(handle, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
return True
print("QQ消息发送失败,请保证备注设置正确并且已打开聊天窗口")
if __name__ == '__main__':
s = ToQQ()
s.sendMsg("test45","0x6A")
# i = 1
# content2 = 99
# while i <= content2:
# i = i + 1
# win32gui.SendMessage(handle, 770, 0, 0)
# # 回车发送消息
# win32gui.SendMessage(handle, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
# win32gui.SendMessage(handle, win32con.WM_KEYUP, win32con.VK_RETURN, 0)
将下面文件下载后,创建新文件夹,文件夹名为"CFimg",将该文件夹与代码文件放至统一目录即可
提供已打包的.exe文件 记得使用管理员模式打开