Skip to content

Commit

Permalink
Add android support
Browse files Browse the repository at this point in the history
And refactory
  • Loading branch information
DawningW committed Feb 2, 2023
1 parent 11555c4 commit 90ef5ac
Show file tree
Hide file tree
Showing 28 changed files with 1,089 additions and 967 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ dmypy.json
# Visual Studio
.vs

# Visual Studio Code
.vscode

# swy-bot
saved
constant.py
65 changes: 44 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
# 食物语自动挂机脚本

## 简介
食物语自动挂机脚本, 主要用于客潮~~和活动小游戏~~(太难做砍掉了绝对不是因为我懒啊啊啊啊啊啊)
食物语自动挂机脚本, 主要用于客潮和活动小游戏(目前仅包括千人千面自动消除)

现已加入千人千面自动挂机, 但由于某些原因仅提供算法, 不提供配置, 请在task.py中自行修改配置
由于某些原因小游戏自动挂机仅提供算法, 不提供配置, 请在tasks/minigame.py中自行修改配置

目前已支持Android系统原生运行脚本, 但有一些性能问题, 详情请见android分支, 若想体验可到releases中下载

现已加入食物语线性规划做菜计算器, 但处于早期测试阶段, 如遇bug请提交issue

Expand All @@ -17,24 +19,31 @@
## 食用方式
详见程序内指引

**注意:** 若使用ADB(Scrcpy模式), 请确保系统环境变量中有ADB, 并且ADB已连接至手机
**注意:** 若使用ADB和Scrcpy模式, 请确保系统环境变量中有ADB, 并且ADB已连接至手机

---
## 食材
- Python3
必需依赖:
- Python 3.8+
- numpy
- opencv-python
- PyAV
- pywin32(仅Windows上需要)
- PyAutoGUI(仅Windows以外的系统需要)
- pure-python-adb
- PuLP
- pyinstaller(如需要打包)

详见requirements.txt
平台特定(现已引入动态加载模式, 未安装库仅会禁用对应模式, 脚本仍可正常运行):
- Windows原生模式:
- pywin32
- linux和mac原生模式:
- PyAutoGUI
- 任意系统ADB模式:
- pure-python-adb
- 任意系统Scrcpy模式:
- av

线性规划做菜计算器:
- PuLP

---
## 菜谱&改良
本项目可在Windows, Linux和MacOS上运行, 但目前仅在Windows上测试过
本项目可在Windows, Linux,MacOS和Android系统上运行, Android系统需要专用的用于加载脚本的APP才能运行, 详见android分支

另外本挂机脚本实际上提供了一个框架, 经过简单修改应该也能用于其他游戏, 甚至是用于训练人工智能玩游戏(逃

Expand All @@ -44,19 +53,32 @@
- libs/ 脚本所需的库, 目前只有Scrcpy的服务端
- data/ 存储游戏数据和挂机所需资源的目录
- saved/ 截图会保存在这个目录
- main.py 主文件
- player.py 负责与游戏交互(通过原生窗口/ADB/Scrcpy)
- task.py 执行挂机任务
- algorithms/ 算法
- detect.py 图像识别相关算法
- matching.py 自动连连看算法(原作者TheThreeDog)
- players/ 模式
- player.py 模式基类
- native.py 通过原生窗口与游戏交互
- adb.py 通过ADB与游戏交互
- scrcpy.py 通过Scrcpy与游戏交互
- debug.py 调试用
- tasks/ 挂机任务
- task.py 挂机任务基类
- kechao.py 客潮挂机任务
- minigame.py 小游戏挂机任务
- platforms/ 工具模块的平台相关实现
- console.py 具有命令行的系统上的实现
- windows.py Windows系统相关实现
- linux.py Linux系统相关实现
- android.py Android系统相关实现
- main.py 主模块
- profit.py 线性规划做菜计算器(可单独运行)
- swy.py 食物语游戏数据(单独运行为输出游戏数据)
- scrcpy.py Python实现的Scrcpy客户端
- utils.py 工具模块
- swy.py 负责加载游戏数据
- profit.py 线性规划做菜计算器
- matching.py 自动连连看算法(原作者TheThreeDog)

### 自动挂机
详见player.py和task.py
详见players和tasks目录

### 线性规划做菜计算器
线性规划算法详见profit.py中的注释
Expand All @@ -68,15 +90,15 @@

另外烹饪时间出现小数的话只有入没有舍, 是ceil

### 自动连连看
### 自动小游戏
由于某些原因, 本项目仅提供用于学习的算法, 不包含配置, 如需使用请自行配置

---
## 如何烹饪
1. 拿走菜谱(克隆仓库到本地)
1. 准备好食材(安装第三方库)
1. 开始做菜(运行main.py)
1. 装盘(如需构建, 请使用pyinstaller)
1. 装盘(目前仍无法打包运行, 请考虑使用Android原生版本)
1. 随心所欲地修改菜谱(请随意修改代码)

---
Expand All @@ -96,6 +118,7 @@
2021/9/13 加入自动连连看算法, 初步支持Linux
2021/9/14 已加入对Linux和MacOS的支持, 但尚未测试, 更新版本号至V1.6
2021/9/17 已加入千人千面自动挂机功能, 更新版本号至V1.7
2023/2/2 代码重写, 用协程替代状态机, 实现动态加载模式, 移植到Android系统, 由于更新内容较多, 更新版本号为V2.0
</pre>
</details>

Expand Down
72 changes: 72 additions & 0 deletions algorithms/detect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import numpy
import cv2

sift = cv2.SIFT_create()

def siftcompute(image, draw=False):
# 转灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 计算关键点和描述符
# key_points: 关键点信息, 包括位置, 尺度, 方向信息
# descriptors: 关键点描述符, 每个关键点对应128个梯度信息的特征向量
kp, des = sift.detectAndCompute(gray, None)
if draw:
cv2.drawKeypoints(image, kp, image, (0, 255, 0),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
return des

def siftsimilarity(img1, img2, threshold=0.7):
# 计算两张图片的特征点
des1 = siftcompute(img1)
des2 = siftcompute(img2)
# 构建 FLANN
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 比较两张图片的特征点
matches = flann.knnMatch(des1, des2, k=2)
if len(matches) == 0:
return 0.0
# 计算匹配点数并计算相似度
good = [m for (m, n) in matches if m.distance < n.distance * threshold]
return len(good) / len(matches)

def isimagesame(img1, img2):
# return siftsimilarity(img1, img2, 0.7) > 0.8
result = cv2.matchTemplate(img1, img2, cv2.TM_CCOEFF_NORMED)
location = numpy.where(result >= 0.5)
for pt in zip(*location[::-1]):
return True
return False

def findtemplate(image, template, threshold=0.75, outline=False):
theight, twidth = template.shape[:2]
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
# result = cv2.normalize(result, None, 0, 1, cv2.NORM_MINMAX)
location = numpy.where(result >= threshold)
lx, ly = 0, 0
points = []
for pt in zip(*location[::-1]):
x, y = pt[0] + int(twidth / 2), pt[1] + int(theight / 2)
# 去掉重复点
if x - lx < twidth or y - ly < theight:
continue
points.append((x, y))
lx, ly = x, y
if outline:
cv2.rectangle(image, pt, (pt[0] + twidth, pt[1] + theight), (0, 255, 0), 1)
return points

def findcircle(image, r, outline=False):
gimg = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gimg = cv2.medianBlur(gimg, 5)
result = cv2.HoughCircles(gimg, cv2.HOUGH_GRADIENT, 1, int(r / 2), None, 100, 40, r - 10, r + 10)
points = []
if result is not None:
result = numpy.uint16(numpy.around(result))
for p in result[0, :]:
points.append((p[0], p[1]))
if outline:
cv2.circle(image, (p[0], p[1]), p[2], (0, 255, 0), 1)
return points
2 changes: 0 additions & 2 deletions matching.py → algorithms/matching.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# coding=utf-8

'''
Copyright 2018 TheThreeDog
Expand Down
Loading

0 comments on commit 90ef5ac

Please sign in to comment.