Skip to content

Commit

Permalink
更改收货方式 为先按下探测绿光位置在挪货物
Browse files Browse the repository at this point in the history
  • Loading branch information
TsingWei committed Oct 6, 2019
1 parent 0e2f95b commit c4d6939
Show file tree
Hide file tree
Showing 8 changed files with 330 additions and 180 deletions.
44 changes: 26 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# JGM Automator

* 基于 https://github.com/Jiahonzheng/JGM-Automator 改进
* 基于opencv的特征值匹配 [CSDN博客](https://blog.csdn.net/github_39611196/article/details/81164752)
* 更改搜索逻辑,大幅提高了搜索速度
* 货物不再要求原分辨率图片,理论上对手机或模拟器分辨率只要求16:9
* ~~基于opencv的特征值匹配 [CSDN博客](https://blog.csdn.net/github_39611196/article/details/81164752)~~
* ~~更改搜索逻辑,大幅提高了搜索速度 ~~
* ~~货物不再要求原分辨率图片,理论上对手机或模拟器分辨率只要求16:9~~
* 收货方式改为先按下货物寻找绿光位置再把货物挪过去,简单方便,准确更高

## 安装与运行
运行前的准备:

[uiautomator2](https://github.com/openatx/uiautomator2)是python封装的安卓自动化测试库,比原生adb shell命令强大得多,方便得多。

如果cv库安装太慢可以用清华大学的tuna源
```bash
# 安装依赖
python -m pip install uiautomator2 opencv-python opencv-contrib-python==3.4.2.16

# adb 连接
# 使用 MuMu 模拟器,确保屏幕大小为 1920(长) * 1080(宽)
# 如果使用 MuMu 模拟器,请先在shell中adb连接mumu
adb connect 127.0.0.1:7555

# 获取 device 名称,并填写至 main.py
Expand All @@ -22,10 +27,19 @@ adb devices
python -m uiautomator2 init

# 打开 ATX ,点击“启动 UIAutomator”选项,确保 UIAutomator 是运行的。
```

# 进入游戏页面,启动自动脚本。
如何运行:
``` bash
python main.py
```
因为火车识别还不是很准确,这里用了个折中的方法:

在main.py中,注释两者其一可以选择是只收金币还是收火车一起
```py
instance.start()
# instance.start_without_train()
```

## 说明

Expand All @@ -34,18 +48,6 @@ python main.py
<img src="./assets/Screenshot.png" style="zoom:40%" />


```bash
# 安装依赖
python -m pip install --pre weditor

# 启动 Weditor
python -m weditor
```

+ 货物素材

我们可以自行制作货物的素材:先生成屏幕快照,~~随后在**实际大小**~~,截取货物图片,保存至 `targets/` 目录下,并在 `target.py` 声明对应的货物种类及其图片路径。

+ 升级列表和收货列表
`main.py`里,定义这两个列表,即可指定要升级的建筑和要收货的建筑
```py
Expand All @@ -56,6 +58,12 @@ python -m weditor
```

## 实现细节
+ 截图后,分割右下角,并打上遮罩,提高特征值匹配速度,减少错误:
* 收火车时,先点按货物,然后检测绿光获取货物目的地:
<img src="./targets/test/Diff2.png" style="zoom:40%" />
* 实现这一功能时,若使用原生adb shell实现的话需要多线程或者多进程才行(分别执行按住和截图命令)
在这里由于uiautomator的强大轮子使得我可以很方便的实现这一功能。

### 以下功能已废弃:
+ ~~截图后,分割右下角,并打上遮罩,提高特征值匹配速度,减少错误:~~
+ <img src="./targets/test/Figure_1.png" style="zoom:40%" />
+ <img src="./targets/test/Figure_2.png" style="zoom:40%" />
86 changes: 86 additions & 0 deletions adb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import subprocess
import time
import multiprocessing
from utility import randomize_offset, randomize_scale


class Adb():
def __init__(self):
assert self.is_correctly_connected(
), 'Make sure ADB is correctly configured and only one device is connected.'

def is_correctly_connected(self):
'''
Return True if ADB enrivonment is correctly configured and only one divice is connected.
'''
output = subprocess.check_output(
"adb devices", shell=True).decode('utf-8')
if output.startswith('List of devices attached') and output.count('device') == 2:
return True
else:
return False

def get_screenshot(self, filename):
'''
Get screenshot and save as 'filename'
'''
subprocess.check_output(
'adb shell screencap -p /sdcard/{}'.format(filename), shell=True)
subprocess.check_output(
'adb pull /sdcard/{}'.format(filename), shell=True)
# print('Get screenshot {}'.format(filename))

def get_screenshot_while_touching(self, filename, location, pressed_time=6):
'''
Get screenshot with screen touched.
Multiprocess or Multithread is needed.
'''
p = multiprocessing.Process(
target=self.tap_continuously, args=[location, pressed_time])
p.start()
time.sleep(2)
self.get_screenshot(filename)
time.sleep(0.5)
p.join()

def tap(self, location, with_bias=True):
'''
slightly tap.
location: (x, y)
'''
if with_bias:
location = map(randomize_offset, location)

subprocess.check_output(
'adb shell input touchscreen tap {} {}'.format(*location), shell=True)

def tap_continuously(self, location, duration):
'''
Seems there is no direct ADB command to do this.
So just swipe from a location to the same location.
'''
self.swipe(location, location, duration * 1000)

def tap_periodically(self, location, times, interval=0.2):
for _ in range(times):
self.tap(location)
time.sleep(interval)

def swipe(self, start, end, duration=400, with_bias=True):
'''
swipe from start point to end point,
duration is the total time consumed, used to control speed.
'''
if with_bias:
start = map(randomize_offset, start)
end = map(randomize_offset, end)
duration = int(randomize_scale(duration))

subprocess.check_output('adb shell input touchscreen swipe {} {} {} {} {}'.format(
*start, *end, duration), shell=True)


if __name__ == '__main__':
adb = Adb()
# time.sleep(5)
# adb.get_screenshot('eee.png')
Loading

0 comments on commit c4d6939

Please sign in to comment.