forked from Shu-Ji/wechat_micro_jump_game_hero
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
167 lines (129 loc) · 5.1 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# coding: u8
from __future__ import print_function, unicode_literals
import colorsys
import commands
import itertools
import math
import time
import traceback
from PIL import Image, ImageDraw
class Otsu(object):
def __init__(self, path, debug=False):
self.im = Image.open(path)
self.w, self.h = self.im.size
self.pixels = self.im.load()
self.draw = ImageDraw.Draw(self.im)
self.hero_pos = self.find_hero()
print('hero pos:', self.hero_pos)
is_hero_on_left = self.hero_pos[0] < self. w / 2
bg_hsv = self.get_background_hsv()
print('background hsv:', bg_hsv)
top_most, lr_most = self.find_most(is_hero_on_left, bg_hsv)
print('top most pos:', top_most)
print('left/right most pos', lr_most)
self.center_pos = top_most[0], lr_most[1]
print('center pos', self.center_pos)
if debug:
#self.erase_background(bg_hsv)
self.draw_pos(self.hero_pos)
self.draw_pos(top_most)
self.draw_pos(lr_most)
self.draw_pos(self.center_pos)
cx, cy = self.center_pos
hx, hy = self.hero_pos
self.draw.line((cx, cy, hx, hy), fill=(0, 255, 0), width=8)
self.im.show()
def find_hero(self):
hero_poses = []
for y in xrange(self.h / 3, self.h * 2 / 3):
for x in xrange(self.w):
# is purple
if self.pixels[x, y] == (56, 56, 97, 255):
hero_poses.append((x, y))
# calc the avg pos
return map(lambda i: sum(i) / len(i), itertools.izip(*hero_poses))
def rgb_to_hsv(self, r, g, b, a=255):
h, s, v = colorsys.rgb_to_hsv(r / 255., g / 255., b / 255.)
return int(h * 255.), int(s * 255.), int(v * 255.)
def get_background_hsv(self):
# use the (10, 800) as the background color
bg_color = self.pixels[10, 800]
return self.rgb_to_hsv(*bg_color)
def erase_background(self, bg_hsv):
for y in xrange(self.h / 4, self.h * 2 / 3):
for x in xrange(self.w):
h, s, v = self.rgb_to_hsv(*self.pixels[x, y])
if self.is_same_color(h, s, v, bg_hsv):
self.im.putpixel((x, y), (0, 0, 0))
else:
self.im.putpixel((x, y), (255, 255, 255))
def find_most(self, is_hero_on_left, bg_hsv):
hero_r = 15
if is_hero_on_left:
# top most is on the right, scan from right
from_x = self.w - 1
to_x = self.hero_pos[0] + hero_r
step = -1
else:
# top most is on the left, scan from left
from_x = 0
to_x = self.hero_pos[0] - hero_r
step = 1
from_y, to_y = self.h / 4, self.hero_pos[1]
top_most = self.find_top_most(bg_hsv, from_x, to_x, from_y, to_y, step)
lr_most = self.find_lr_most(bg_hsv, from_x, to_x, from_y, to_y, step)
return top_most, lr_most
def find_top_most(self, bg_hsv, from_x, to_x, from_y, to_y, step):
for y in xrange(from_y, to_y):
for x in xrange(from_x, to_x, step):
h, s, v = self.rgb_to_hsv(*self.pixels[x, y])
if not self.is_same_color(h, s, v, bg_hsv):
return x, y
def find_lr_most(self, bg_hsv, from_x, to_x, from_y, to_y, step):
for x in xrange(from_x, to_x, step):
for y in xrange(from_y, to_y):
h, s, v = self.rgb_to_hsv(*self.pixels[x, y])
if not self.is_same_color(h, s, v, bg_hsv):
return x, y
def is_same_color(self, h, s, v, bg_hsv):
bg_h, bg_s, bg_v = bg_hsv
return (abs(h - bg_h) < 15) and (abs(s - bg_s) < 20)
def draw_pos(self, pos, color=(0, 255, 0)):
x, y = pos
r = 25
self.draw.ellipse((x, y, x + r, y + r), fill=color, outline=color)
def get_holding(self):
line_length = int(math.sqrt(
pow(self.center_pos[0] - self.hero_pos[0], 2) + \
pow(self.center_pos[1] - self.hero_pos[1], 2)
))
length_time = line_length * 1.5
holding = min(950, max(length_time, 300))
print('length, duration, holding: ', line_length, length_time, holding)
print()
return int(holding)
def run_cmd(cmd):
return commands.getstatusoutput(cmd)
jump_times = itertools.count(0)
while True:
try:
debug = False
if debug:
fn = 's'
else:
fn = str(next(jump_times))
run_cmd('adb shell screencap -p /sdcard/s.png')
run_cmd('adb pull /sdcard/s.png /tmp/{}.png'.format(fn))
run_cmd('cp /tmp/{}.png /tmp/s.png'.format(fn))
print(fn)
holding = Otsu('/tmp/{}.png'.format(fn), debug=debug).get_holding()
if debug:
raise KeyboardInterrupt
else:
run_cmd('adb shell input swipe 255 255 0 0 {}'.format(holding))
time.sleep(2)
except KeyboardInterrupt:
raise KeyboardInterrupt
except Exception as e:
traceback.print_exc()
time.sleep(2)