python3小项目2-基于autopy的游戏脚本

 

说明:

这里笔者用的PC端的安卓模拟器为雷电模拟器,因为发现这个兼容性好

这里笔者在雷电模拟器上安装了一款心动女友app游戏

 

本次项目的目的:

创建一个通用库。暂时实现功能为自动打开雷电模拟器,并且自动实现心动女友游戏的恋爱功能

 

本次项目的原理:

用autopy的模拟鼠标点击,模拟鼠标长按,移动拖住鼠标等操作,实现自动玩游戏。并通过time的sleep函数控制时间

 

源码如下。本源码定义了多个类,理论可以很好的适用于其他游戏的简易自动化操作

#!/usr/bin/env python3
# _*_ coding: utf-8 _*_
# File  : gamehelper.py
# Author: DaShenHan&道长-----先苦后甜,任凭晚风拂柳颜------
# Date  : 2019/3/22

import win32gui, win32con,win32api
import re, traceback
from time import sleep
import autopy
from win32gui import *

class cWindow:
    def __init__(self):
        self._hwnd = None
    def SetAsForegroundWindow(self):
        # First, make sure all (other) always-on-top windows are hidden.
        self.hide_always_on_top_windows()
        win32gui.SetForegroundWindow(self._hwnd)
    def Maximize(self):
        win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE)
    def _window_enum_callback(self, hwnd, regex):
        '''Pass to win32gui.EnumWindows() to check all open windows'''
        if self._hwnd is None and re.match(regex, str(win32gui.GetWindowText(hwnd))) is not None:
            self._hwnd = hwnd
    def find_window_regex(self, regex):
        self._hwnd = None
        win32gui.EnumWindows(self._window_enum_callback, regex)
        return self._hwnd
    def hide_always_on_top_windows(self):
        win32gui.EnumWindows(self._window_enum_callback_hide, None)
    def _window_enum_callback_hide(self, hwnd, unused):
        if hwnd != self._hwnd: # ignore self
            # Is the window visible and marked as an always-on-top (topmost) window?
            if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) & win32con.WS_EX_TOPMOST:
                # Ignore windows of class 'Button' (the Start button overlay) and
                # 'Shell_TrayWnd' (the Task Bar).
                className = win32gui.GetClassName(hwnd)
                if not (className == 'Button' or className == 'Shell_TrayWnd'):
                    # Force-minimize the window.
                    # Fortunately, this seems to work even with windows that
                    # have no Minimize button.
                    # Note that if we tried to hide the window with SW_HIDE,
                    # it would disappear from the Task Bar as well.
                    win32gui.ShowWindow(hwnd, win32con.SW_FORCEMINIMIZE)
    def getallwindows(self):
        """
        本方法实现获取当前所有进程列表并打印
        :return: type:list() 返回当前所有进程列表
        """
        titles=set()
        def foo(hwnd, mouse):
            if IsWindow(hwnd) and IsWindowEnabled(hwnd) and IsWindowVisible(hwnd):
                titles.add(GetWindowText(hwnd))
        EnumWindows(foo, 0)
        list = []
        for title in titles:
            if title:
                list.append(title)
        print(list)
        return  list
    def openapp(self,appname):
        """
        本方法实现打开一个包含指定名字的窗口
        :param appname: type: str('可以不是全名') 进程模糊名字
        :return: 返回窗口句柄
        """
        try:
            regex = ".*{}.*".format(appname)
            self.find_window_regex(regex)
            self.Maximize()
            self.SetAsForegroundWindow()
        except:
            f = open("log.txt", "w")
            f.write(traceback.format_exc())
            print(traceback.format_exc())
        return self.find_window_regex(regex)

class Mouse:
    def move(self, x, y,size=1):
        """
        本方法实现鼠标移动到指定的坐标
        :param x: type:float(0~设备最大分辨率的宽) 待移动到的x坐标
        :param y: type:float(0~设备最大分辨率的高) 待移动到的y坐标
        :param size: type:float(0~1)  整体应用大小设置 win10下默认应用程序是125%大小,所以这里缩放后得到0.8.默认不缩放
        :return: 无返回值
        """
        autopy.mouse.move(x*size, y*size)
    def click(self,mode=0):
        """
        本方法实现鼠标在当前位置单次点击
        :param mode:  type:int(0,1,2) 鼠标点击模式 0表示用左键 1表示用中键 2表示用右键 默认用鼠标左键点击
        :return: 无返回值
        """
        if mode == 1:
            autopy.mouse.click(autopy.mouse.Button.MIDDLE)
        elif mode == 2:
            autopy.mouse.click(autopy.mouse.Button.RIGHT)
        else:
            autopy.mouse.click(autopy.mouse.Button.LEFT)

    def move_click(self, x, y,size=1,mode=0):
        """
        本方法实现鼠标瞬间移动到指定绝对坐标并且单次点击某个键
        :param x: type:float(0~设备最大分辨率的宽) 待移动到的x坐标
        :param y: type:float(0~设备最大分辨率的高) 待移动到的y坐标
        :param size: type:float(0~1) 整体应用大小设置 win10下默认应用程序是125%大小,所以这里缩放后得到0.8.默认不缩放
        :param mode: type:int(0,1,2) 鼠标点击模式 0表示用左键 1表示用中键 2表示用右键 默认用鼠标左键点击
        :return:
        """
        self.move(x*size, y*size)
        self.click(mode)
    def hold(self,mode=0,down=True):
        """
        本方法实现长按鼠标的键与放开常按
        :param mode: type:int(0,1,2) 鼠标点击模式 0表示用左键 1表示用中键 2表示用右键 默认用鼠标左键点击
        :param down: type:bool(True,False) 是否按下,默认是按下。松开请用False
        :return: 无返回值
        """
        if mode == 1:
            autopy.mouse.toggle(autopy.mouse.Button.MIDDLE,down)
        elif mode == 2:
            autopy.mouse.toggle(autopy.mouse.Button.RIGHT,down)
        else:
            autopy.mouse.toggle(autopy.mouse.Button.LEFT,down)
    def location(self):
        return autopy.mouse.location()

class Key:
    key_zm = {chr(i): i for i in range(65, 91)}
    key_num = {chr(i): i for i in range(48, 58)}
    key_F = {'F%d' % (i - 111): i for i in range(112, 124)}
    key_ts = {
        'Backspace': 8,
        'Tab': 9,
        'Clear': 12,
        'Enter': 13,
        'Shift': 16,
        'Ctrl': 17,
        'Alt': 18,
        'Caps Lock': 20,
        'Esc': 27,
        'Spacebar': 32,
        'Page Up': 33,
        'Page Down': 34,
        'End': 35,
        'Home': 36,
        'Left Arrow': 37,
        'Up Arrow': 38,
        'Right Arrow': 39,
        'Down Arrow': 40,
        'Insert': 45,
        'Delete': 46,
        'Help': 47,
        'Num Lock': 144,
        '+': 107,
        '-': 109,
        '*': 106,
        '/': 111,
        '.': 110}
    keycode = dict(key_zm, **key_num, **key_F, **key_ts)

    def push(self, key, mode=True):
        """
        :param key: type:str 按键名称 如Tab
        :param mode: type:bool 按键操作 False松开 True按下 默认是按下
        """
        if mode:
            win32api.keybd_event(self.keycode[key], 0, 0, 0)
        else:
            win32api.keybd_event( self.keycode[key], 0, win32con.KEYEVENTF_KEYUP, 0)
    def input(self,string,wpm=None):
        autopy.key.type_string(string,wpm=wpm)
    def getcode(self, key):
        return self.keycode[key]

class Screen:
    def getcolor(self,x,y):
        return  autopy.screen.get_color(x,y)
    def fenbianlv(self):
        width, height = autopy.screen.size()
        return (width,height)
class Message:
    def alert(self,info):
        autopy.alert.alert(info,title='提示框')
    def confirm(self,info):
        a=autopy.alert.alert(info, '选择框', default_button='确定', cancel_button='取消')
        return a
class XinDong:
      love={'遛狗':1,'运动':2,'看电影':3,'唱歌':4,'游乐园':5,'风景区':6,'国内游':7,'境外游':8}
      def qd(self):
          m.move_click(823,126,0.8)
          sleep(2)
          m.move_click(959, 822, 0.8)
          sleep(1)
          m.move_click(1487, 283, 0.8)
      def lianai_open(self):
          m.move_click(848, 928, 0.8)
          sleep(4)
          m.move_click(1471, 298, 0.8)
          sleep(1)
      def lianai_close(self):
          m.move_click(1728, 124, 0.8)
      def lianai_start(self):
          m.move(911, 265, 0.8)
          m.hold()
          m.move(1429, 262, 0.8)
          m.hold(down=False)
          sleep(0.5)
      def lianai_do(self,thing):
          thingnum=self.love[thing]
          self.lianai_start()
          for i in range(thingnum):
              m.move(1429, 262, 0.8)
              m.hold()
              sleep(0.5)
              m.move(911, 265, 0.8)
              m.hold(down=False)
          sleep(0.5)
          m.move_click(825,925,0.8)
          if thingnum>1:
            sleep(3)
            m.move_click(1146, 716, 0.8)
            sleep(2)
            m.move_click(825,925,0.8)
          sleep(27)
          m.move_click(960, 707, 0.8)
          sleep(3)
      def work(self):
          m.move_click(1078,922,0.8)
          sleep(3)
          m.move_click(1471, 298, 0.8, 0)
          sleep(0.5)

def where_is_the_rubbish():
    '''查找回收站在屏幕中的位置'''
    m.move_click(1772,16,0.8)
    sleep(2)
    rubbish=autopy.bitmap.Bitmap.open('resave.png')
    print(rubbish)
    screen=autopy.bitmap.capture_screen()
    screen.save('jietu.png')
    print(screen)
    pos=screen.find_bitmap(rubbish)
    if pos:
        print ('找到了,他的位置在:%s' % str(pos))
    else:
        print ('没有找到')

if __name__ == '__main__':
    cW = cWindow()
    m = Mouse()
    k = Key()
    s= Screen()
    ms=Message()
    cW.getallwindows()
    if ms.confirm('是否开始自动游戏?'):
        jubing=cW.openapp('雷电模拟器')
        print('应用程序窗口句柄为%s' % jubing)
        sleep(2)
        wg = XinDong()
        wg.lianai_open()
        wg.lianai_do('唱歌')
        wg.lianai_close()
    else:
        print('pass')