本人写的一个关于欢乐跳瓶的作弊程序,在夜神模拟器上运行的,主要拿canny写的。
如果是跳一跳其实就更容易了,因为欢乐跳瓶的界面较跳一跳来说噪声相对要多不少。
完整可运行代码下载请移步 https://download.csdn.net/download/kuroyukineko/10494650
下面贴一下大致PPT的内容和代码。
下面是纯代码,如果需要上机运行的话还需要几个匹配的模版,在下载里都打了包,这里就不贴了。
# bottle_flip_cheat
# by Kuroyukineko 2018.03.09
# Noxplayer(1280*720)_BottleFlip
import sys
import time
import math
import win32gui
import win32ui
import win32api
import win32con
import numpy as np
import cv2
import matplotlib.pyplot as plt
def beginDetect(hwnd, window_hw_para):
filename = "begindetect.jpg"
pic_capture(hwnd, filename)
#read image
img_origin = cv2.imread(filename)
img_cut_gray = cv2.cvtColor(img_origin, cv2.COLOR_BGR2GRAY)
#template
template = cv2.imread("beginTemplate.jpg", 0)
template1 = cv2.imread("beginTemplate.jpg", 0)
#w, h = template.shape[::-1]
res = cv2.matchTemplate(img_cut_gray,template,cv2.TM_CCOEFF_NORMED)
res1 = cv2.matchTemplate(img_cut_gray,template1,cv2.TM_CCOEFF_NORMED)
threshold = 0.6
loc = np.where( res >= threshold)
loc1 = np.where( res1 >= threshold)
if len(loc[0]) != 0 or len(loc1[0]) != 0:
mouse_move(window_hw_para['left'] + 280,
window_hw_para['top'] + 500)
mouse_click(0.5) #jump
time.sleep(1)
cv2.destroyAllWindows()
def ready_game():
#player locate the game window
print ("Please move the cursor on game window and press 'Y'.")
#decide to start or not
ready_confirm = input(">> ")
if ready_confirm == 'Y':
start_game()
else:
end_gmae()
def start_game():
print ("Enjoy the game!")
def end_game():
print ("ByeBye!")
sys.exit()
def restart_detect(hwnd, window_hw_para, timeRecord):
filename = "restartdetect.jpg"
pic_capture(hwnd, filename)
#read image
img_origin = cv2.imread(filename)
img_cut_gray = cv2.cvtColor(img_origin, cv2.COLOR_BGR2GRAY)
#template
template = cv2.imread("restartTemplate.jpg", 0)
template1 = cv2.imread("skipTemplate.jpg", 0)
#w, h = template.shape[::-1]
res = cv2.matchTemplate(img_cut_gray,template,cv2.TM_CCOEFF_NORMED)
res1 = cv2.matchTemplate(img_cut_gray,template1,cv2.TM_CCOEFF_NORMED)
threshold = 0.6
loc = np.where( res >= threshold)
loc1 = np.where( res1 >= threshold)
cv2.destroyAllWindows()
if len(loc[0]) != 0 or len(loc1[0]) != 0:
end_game()
def mouse_move(position_x, position_y):
win32api.SetCursorPos([position_x, position_y])
#click the mouse (position_x, position_y, click_time/s)
def mouse_click(click_time):
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
time.sleep(click_time)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
def distance_calculate(hwnd, window_hw_para):
filename = "tmp.jpg"
error_set = 15
pic_capture(hwnd, filename)
start_position, close_flag = jump_from_position(window_hw_para,error_set)
final_position = jump_to_position(window_hw_para, error_set, start_position)
print ("from", start_position)
print ("to", final_position)
if close_flag == True:
distance = 25
else:
distance = (((start_position[0] - final_position[0]) ** 2 +
(start_position[1] - final_position[1]) ** 2) ** 0.5)
print ('distance = ', distance)
#if distance < 70:
#distance = distance * 0.85
return distance
def pic_capture(hwnd, filename):
hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
MoniterDev = win32api.EnumDisplayMonitors(None, None)
w = MoniterDev[0][2][2]
h = MoniterDev[0][2][3]
saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
saveDC.SelectObject(saveBitMap)
saveDC.BitBlt((0, 0), (w, h), mfcDC, (0, 0), win32con.SRCCOPY)
saveBitMap.SaveBitmapFile(saveDC, filename)
def jump_from_position(window_hw_para,error):
#read image
img_origin = cv2.imread('tmp.jpg')
#cv2.imshow('tmp.jpg', img_origin)
window_h = int((window_hw_para['bottom'] - window_hw_para['top']) / 2)
window_w = window_hw_para['right'] - window_hw_para['left']
img_gray = cv2.cvtColor(img_origin, cv2.COLOR_BGR2GRAY)
template = cv2.imread('Template.jpg',0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.6
loc = np.where(res >= threshold) #matrix (j, i)
if len(loc[0]) == 0:
print ("zero array occurs.")
#Template color: [255 151 122]
blue = img_origin[loc[0] + 54, loc[1] + 19, 0].astype(np.int64) - 255 #40,10
green = img_origin[loc[0] + 54, loc[1] + 19, 1].astype(np.int64) - 151
red = img_origin[loc[0] + 54, loc[1] + 19, 2].astype(np.int64) - 122
#print(blue, green, red)
error_blue_square = blue.astype(np.int64) ** 2
error_green_square = green.astype(np.int64) ** 2
error_red_square = red.astype(np.int64) ** 2
#print (error_blue_square, error_green_square, error_red_square)
error_cal = np.sqrt(error_blue_square + error_green_square + error_red_square)
#print (error_cal)
result_loc = np.where(error_cal < error)
mid = int(len(result_loc[0])/2)
result = result_loc[0][0]
final_loc = [loc[0][result] + 80, loc[1][result] + 19] #62,10
flag = False
cv2.destroyAllWindows()
return final_loc, flag
#incase that bootle is too close to the middle line
def left_or_right(corner_position_x, window_w):
flag = np.zeros(2)
t1 = corner_position_x <= window_w / 2 + 25
t2 = corner_position_x >= window_w / 2 - 25
if t1 and t2:
#too close to middle line
flag[0] = True
else:
flag[0] = False
if corner_position_x < window_w / 2:
flag[1] = True
else:
flag[1] = False
return flag
def jump_to_position(window_hw_para, error_set, from_loc):
finalposition = np.zeros(2)
#now = time.time()
img_origin = cv2.imread('tmp.jpg')
#cv2.imshow('tmp.jpg', img_origin)
window_h = int((window_hw_para['bottom'] - window_hw_para['top']) / 3)
window_w = window_hw_para['right'] - window_hw_para['left']
#print("The size of window is [%d, %d]" % (window_h, window_w))
flag_bottle = left_or_right(from_loc[1], window_w)
flag, crystalposition = crystal_detect(hwnd, error_set)
#estimate
middle_x = 276.5
middle_y = 491.5
absy = abs(from_loc[0] - middle_y)
absx = abs(from_loc[1] - middle_x)
if middle_y > from_loc[0]:
final_loc_est_y = middle_y + absy
else:
final_loc_est_y = middle_y - absy
if middle_x > from_loc[1]:
final_loc_est_x = middle_x + absx
else:
final_loc_est_x = middle_x - absx
loc_estimate = [int(final_loc_est_y), int(final_loc_est_x)]
blue = img_origin[int(final_loc_est_y), int(final_loc_est_x), 0].astype(np.int64) - 162
green = img_origin[int(final_loc_est_y), int(final_loc_est_x), 1].astype(np.int64) - 162
red = img_origin[int(final_loc_est_y), int(final_loc_est_x), 2].astype(np.int64) - 162
error_blue_square = blue.astype(np.int64) ** 2
error_green_square = green.astype(np.int64) ** 2
error_red_square = red.astype(np.int64) ** 2
#print (error_blue_square, error_green_square, error_red_square)
error_cal = np.sqrt(error_blue_square + error_green_square + error_red_square)
#print (error_cal)
#detect gray
if error_cal <= 15:
print("Use estimate location!!!")
return loc_estimate
if flag == False:
# calculate estimated zone
j_min = int(final_loc_est_y - 45) if (final_loc_est_y - 45) > window_h else window_h
j_max = int(final_loc_est_y + 45) if (final_loc_est_y + 45) < 2*window_h else 2*window_h
i_min = int(final_loc_est_x - 45) if (final_loc_est_x - 45) > 0 else 0
i_max = int(final_loc_est_x + 45) if (final_loc_est_x + 45) < window_w else 2*window_w
#too close to bottle(line)
if flag_bottle[1] == True:
#bottle left
if from_loc[1]+30 >= i_min:
i_min = from_loc[1]+30
else:
if from_loc[1]-30 <= i_max:
i_max = from_loc[1]-30
img_cut = img_origin[j_min:j_max, i_min:i_max]
#canny
img_canny = cv2.Canny(img_cut, 120, 165)
#cv2.imshow('Canny', img_canny)
#pick corner which decides x
corner_position_y, corner_position_x = get_top_corner(window_h,
window_w, img_canny, img_cut, flag_bottle, from_loc[1])
flag_lor = left_or_right(corner_position_x+i_min, window_w)
corner2 = get_conrner2(window_h, window_w, img_canny,
img_cut, corner_position_y, corner_position_x, error_set, flag_lor[1]) #get the color
finalposition = [corner2[0]+j_min, corner_position_x+i_min] #img_origin
else:
finalposition = crystalposition
return finalposition
cv2.destroyAllWindows()
return finalposition
def get_top_corner(window_h, window_w, img_canny, img_cut, flag, from_loc_x):
result = np.where(img_canny == 255)
ans = np.where(result[0] == result[0][0])
mid = int(len(ans[0]) / 2)
#sort by line
j = result[0][mid]
i = result[1][mid]
return j, i #img_cut[j,i]
def get_conrner2(h, w, img_canny,
img_cut, y, x, error, flag):
corner2 = np.zeros(2)
result_asort = np.where(img_canny == 255)
if flag == True:
corner2 = leftsort(result_asort)
else:
corner2 = rightsort(result_asort)
return corner2
def leftsort(input):
#input matrix is [2, n] [j, i]
#print(input)
#np.savetxt('i.txt',input[1])
min_i = np.min(input, axis = 1)
#print (input[1])
min_loc_i = np.where(input[1] == min_i[1]) #location of min
i_sorted = [input[0][min_loc_i], input[1][min_loc_i]] #sorted by i
#print (i_sorted)
min_j = np.min(i_sorted, axis = 1)
#print (i_sorted[0])
min_loc_j = np.where(i_sorted[0] == min_j[0]) #location of min
#min_loc_j = np.where(i_sorted[1] == min_j[1]) #location of min
j_sorted = [i_sorted[0][min_loc_j], i_sorted[1][min_loc_j]] #sorted by j
#print (j_sorted)
output = [j_sorted[0][0], j_sorted[1][0]]
#print (output)
return output #matrix (j, i)
def rightsort(input):
#input matrix is [2, n] [j, i]
max_i = np.max(input, axis = 1)
#print (input[1])
max_loc_i = np.where(input[1] == max_i[1]) #location of min
i_sorted = [input[0][max_loc_i], input[1][max_loc_i]] #sorted by i
#print (i_sorted)
min_j = np.min(i_sorted, axis = 1)
#print (i_sorted[0])
min_loc_j = np.where(i_sorted[0] == min_j[0]) #location of min
#min_loc_j = np.where(i_sorted[1] == min_j[1]) #location of min
j_sorted = [i_sorted[0][min_loc_j], i_sorted[1][min_loc_j]] #sorted by j
#print (j_sorted)
output = [j_sorted[0][0], j_sorted[1][0]]
#print (output)
return output #matrix (j, i)
def crystal_detect(hwnd,error):
filename = "crystaldetect.jpg"
flag = False
pic_capture(hwnd, filename)
#read image
img_origin = cv2.imread(filename)
img_gray = cv2.cvtColor(img_origin, cv2.COLOR_BGR2GRAY)
#template
error = 10
template = cv2.imread("crystalTemplate.jpg", 0)
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.7
loc = np.where( res >= threshold)
blue = img_origin[loc[0] + 6, loc[1] + 4, 0].astype(np.int64) - 255
green = img_origin[loc[0] + 6, loc[1] + 4, 1].astype(np.int64) - 194
red = img_origin[loc[0] + 6, loc[1] + 4, 2].astype(np.int64) - 4
error_blue_square = blue.astype(np.int64) ** 2
error_green_square = green.astype(np.int64) ** 2
error_red_square = red.astype(np.int64) ** 2
error_cal = np.sqrt(error_blue_square + error_green_square + error_red_square)
result_loc = np.where(error_cal < error)
if len(result_loc[0]) != 0:
###########print ("crystal detected")
flag = True
result = result_loc[0][0]
final_loc = [loc[0][result] + 43, loc[1][result] + 8] # in coordinates [img_origin]
else:
final_loc = np.array([0, 0])
final_position = [final_loc[0], final_loc[1]]
cv2.destroyAllWindows()
return flag, final_position
def distance2click_time(distance):
click_time = distance / 355 #355
return click_time
def if_game_over():
return game_over
#def game_restart():
game_over = False
ready_game()
#MAIN
autoFlag = True
timeRecord = []
#initial the window
pos = win32api.GetCursorPos()
hwnd = win32gui.WindowFromPoint(pos)
win32gui.EnableWindow(hwnd, True)
win32gui.SetForegroundWindow(hwnd)
win32gui.ShowWindow(hwnd, win32con.SW_SHOWNORMAL)
#get coordinates of window
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
#print (left, top, right, bottom)
window_hw_para = {"left": left, "top":top,
"right":right, "bottom":bottom}
if autoFlag == True:
beginDetect(hwnd, window_hw_para)
mouse_move(right - 50, bottom - 50)
while True:
#now = time.time()
distance = distance_calculate(hwnd, window_hw_para)
##########print (distance)
T = distance2click_time(distance)
#now = time.time() - now
#print("Algorithm takes " + str(now*1000)+"ms")
mouse_click(T) #jump
#timeRecord.append(now*1000)
time.sleep(1.5)
restart_detect(hwnd, window_hw_para, timeRecord)
print ("Game over.")