使用yolov5目标检测算法对游戏界面进行监控,通过设计算法来控制角色玩dnf
超级详细的视频讲解链接:https://www.bilibili.com/video/BV18r4y1A7BF
github源码链接:https://github.com/c925777075/yolov5-dnf
1. 屏幕画面抓取
使用win32对屏幕进行实时抓取
import cv2
import numpy as np
import win32gui, win32ui, win32con, win32api
def grab_screen(region=None):
hwin = win32gui.GetDesktopWindow()
if region:
left,top,x2,y2 = region
width = x2 - left + 1
height = y2 - top + 1
else:
width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
hwindc = win32gui.GetWindowDC(hwin)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, width, height)
memdc.SelectObject(bmp)
memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)
signedIntsArray = bmp.GetBitmapBits(True)
img = np.fromstring(signedIntsArray, dtype='uint8')
img.shape = (height,width,4)
srcdc.DeleteDC()
memdc.DeleteDC()
win32gui.ReleaseDC(hwin, hwindc)
win32gui.DeleteObject(bmp.GetHandle())
return img
将抓取好的游戏画面存入到指定的文件夹下。
然后是按键,按键可以通过win32和ctype同时协作(一开始我完全使用的是win32,后来发现dnf反外挂屏蔽虚拟按键,所以我又引入了ctype做虚拟按键)。
# coding=utf-8
import win32con
import win32api
import time
key_map = {
"0": 49, "1": 50, "2": 51, "3": 52, "4": 53, "5": 54, "6": 55, "7": 56, "8": 57, "9": 58,
"A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74,
"K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84,
"U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90, "LEFT": 37, "UP": 38, "RIGHT": 39,
"DOWN": 40, "CTRL": 17, "ALT": 18, "F2": 113, "ESC": 27, "SPACE": 32, "NUM0": 96
}
def key_down(key):
"""
函数功能:按下按键
参 数:key:按键值
"""
key = key.upper()
vk_code = key_map[key]
win32api.keybd_event(vk_code, win32api.MapVirtualKey(vk_code, 0), 0, 0)
def key_up(key):
"""
函数功能:抬起按键
参 数:key:按键值
"""
key = key.upper()
vk_code = key_map[key]
win32api.keybd_event(vk_code, win32api.MapVirtualKey(vk_code, 0), win32con.KEYEVENTF_KEYUP, 0)
def key_press(key):
"""
函数功能:点击按键(按下并抬起)
参 数:key:按键值
"""
key_down(key)
time.sleep(0.02)
key_up(key)
time.sleep(0.01)
####################################
import ctypes
import time
SendInput = ctypes.windll.user32.SendInput
W = 0x11
A = 0x1E
S = 0x1F
D = 0x20
M = 0x32
J = 0x24
K = 0x25
LSHIFT = 0x2A
R = 0x13 # 用R代替识破
V = 0x2F
Q = 0x10
I = 0x17
O = 0x18
P = 0x19
C = 0x2E
F = 0x21
up = 0xC8
down = 0xD0
left = 0xCB
right = 0xCD
direct_dic = {"UP": 0xC8, "DOWN": 0xD0, "LEFT": 0xCB, "RIGHT": 0xCD}
esc = 0x01
# C struct redefinitions
PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
_fields_ = [("wVk", ctypes.c_ushort),
("wScan", ctypes.c_ushort),
("dwFlags", ctypes.c_ulong),
("time", ctypes.c_ulong),
("dwExtraInfo", PUL)]
class HardwareInput(ctypes.Structure):
_fields_ = [("uMsg", ctypes.c_ulong),
("wParamL", ctypes.c_short),
("wParamH", ctypes.c_ushort)]
class MouseInput(ctypes.Structure):
_fields_ = [("dx", ctypes.c_long),
("dy", ctypes.c_long),
("mouseData", ctypes.c_ulong),
("dwFlags", ctypes.c_ulong),
("time", ctypes.c_ulong),
("dwExtraInfo", PUL)]
class Input_I(ctypes.Union):
_fields_ = [("ki", KeyBdInput),
("mi", MouseInput),
("hi", HardwareInput)]
class Input(ctypes.Structure):
_fields_ = [("type", ctypes.c_ulong),
("ii", Input_I)]
# Actuals Functions
def PressKey(hexKeyCode):
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput(0, hexKeyCode, 0x0008, 0, ctypes.pointer(extra))
x = Input(ctypes.c_ulong(1), ii_)
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))
def ReleaseKey(hexKeyCode):
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput(0, hexKeyCode, 0x0008 | 0x0002, 0, ctypes.pointer(extra))
x = Input(ctypes.c_ulong(1), ii_)
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))
def defense():
PressKey(M)
time.sleep(0.05)
ReleaseKey(M)
# time.sleep(0.1)
def attack():
PressKey(J)
time.sleep(0.05)
ReleaseKey(J)
# time.sleep(0.1)
def go_forward():
PressKey(W)
time.sleep(0.4)
ReleaseKey(W)
def go_back():
PressKey(S)
time.sleep(0.4)
ReleaseKey(S)
def go_left():
PressKey(A)
time.sleep(0.4)
ReleaseKey(A)
def go_right():
PressKey(D)
time.sleep(0.4)
ReleaseKey(D)
def jump():
PressKey(K)
time.sleep(0.1)
ReleaseKey(K)
# time.sleep(0.1)
def dodge(): # 闪避
PressKey(R)
time.sleep(0.1)
ReleaseKey(R)
# time.sleep(0.1)
def lock_vision():
PressKey(V)
time.sleep(0.3)
ReleaseKey(V)
time.sleep(0.1)
def go_forward_QL(t):
PressKey(W)
time.sleep(t)
ReleaseKey(W)
def turn_left(t):
PressKey(left)
time.sleep(t)
ReleaseKey(left)
def turn_up(t):
PressKey(up)
time.sleep(t)
ReleaseKey(up)
def turn_right(t):
PressKey(right)
time.sleep(t)
ReleaseKey(right)
def F_go():
PressKey(F)
time.sleep(0.5)
ReleaseKey(F)
def forward_jump(t):
PressKey(W)
time.sleep(t)
PressKey(K)
ReleaseKey(W)
ReleaseKey(K)
def press_esc():
PressKey(esc)
time.sleep(0.3)
ReleaseKey(esc)
def dead():
PressKey(M)
time.sleep(0.5)
ReleaseKey(M)
if __name__ == "__main__":
time1 = time.time()
k = "LEFT"
s = "D"
while True:
if abs(time.time() - time1) > 10:
break
else:
# if k not in ["LEFT", "RIGHT", "UP", "DOWN"]:
# key_press(k)
# else:
# PressKey(direct_dic[k])
# time.sleep(0.1)
# ReleaseKey(direct_dic[k])
# time.sleep(0.2)
PressKey(direct_dic[k])
key_down(s)
time.sleep(0.02)
key_up(s)
ReleaseKey(direct_dic[k])
time.sleep(0.02)
2. yolov5数据及制作。
安装插件labelme:pip install labelme
安装好之后直接在prompt中输入labelme即可打开标注工具,labelme的使用十分简单,我们需要对游戏内所控制的角色,怪物,掉地上的材料,传送门,以及boss做矩形框标注,给给与他们一些标签。标注后的文件被保存为json格式,但是yolo系列算法所需要的标注信息是txt格式,因此我们需要一个脚本给数据做转换,代码如下:
import json
import os
name2id = {'hero': 0, 'small_map': 1, "monster": 2, 'money': 3, 'material': 4, 'door': 5, 'BOSS': 6, 'box': 7, 'options': 8}
def convert(img_size, box):
dw = 1./(img_size[0])
dh = 1./(img_size[1])
x = (box[0] + box[2])/2.0 - 1
y = (box[1] + box[3])/2.0 - 1
w = box[2] - box[0]
h = box[3] - box[1]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
def decode_json(json_floder_path,json_name):
txt_name = 'E:\\Computer_vision\\object_DNF\\datasets\\guiqi\\yolo5_datasets\\labels\\' + json_name[0:-5] + '.txt'
txt_file = open(txt_name, 'w')
json_path = os.path.join(json_floder_path, json_name)
data = json.load(open(json_path, 'r', encoding='gb2312'))
img_w = data['imageWidth']
img_h = data['imageHeight']
for i in data['shapes']:
label_name = i['label']
if (i['shape_type'] == 'rectangle'):
print(txt_name)
x1 = int(i['points'][0][0])
y1 = int(i['points'][0][1])
x2 = int(i['points'][1][0])
y2 = int(i['points'][1][1])
bb = (x1,y1,x2,y2)
bbox = convert((img_w,img_h),bb)
txt_file.write(str(name2id[label_name]) + " " + " ".join([str(a) for a in bbox]) + '\n')
if __name__ == "__main__":
json_floder_path = r'E:\Computer_vision\object_DNF\datasets\guiqi\yolo5_datasets\labels_json'
json_names = os.listdir(json_floder_path)
for json_name in json_names:
decode_json(json_floder_path,json_name)
3. 训练yolov5s模型
在这里我们使用的是yolov5s,因为5s作为最小的yolo系列模型可以实现高效的实时监测,yolov5可通过在github源码中找到,因此这里我给出一些我训练的参数:
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', type=str, default=r'E:\Computer_vision\yolov5\YOLO5\yolov5-master\weights\yolov5s.pt', help='initial weights path')
parser.add_argument('--cfg', type=str, default=r'E:\Computer_vision\yolov5\YOLO5\yolov5-master\models\yolov5s_rga.yaml', help='model.yaml path')#网络配置
parser.add_argument('--data', type=str, default=r'E:\Computer_vision\yolov5\YOLO5\DNF\data.yaml', help='data.yaml path')#数据
parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='hyperparameters path')
parser.add_argument('--epochs', type=int, default=200)
parser.add_argument('--batch-size', type=int, default=8, help='total batch size for all GPUs')
parser.add_argument('--img-size', nargs='+', type=int, default=[608, 608], help='[train, test] image sizes')
parser.add_argument('--rect', action='store_true', default=False, help='rectangular training')#矩形训练
parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')#接着之前的训练
parser.add_argument('--nosave', action='store_true', help=' only save final checkpoint')#不保存
parser.add_argument('--notest', action='store_true', help='only test final epoch')#不测试
parser.add_argument('--noautoanchor', action='store_true', default=False, help='disable autoanchor check')#是否调整候选框
parser.add_argument('--evolve', action='store_true', default=False, help='evolve hyperparameters')#超参数更新
parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
parser.add_argument('--cache-images', action='store_true', default=True, help='cache images for faster training')#缓存图片
parser.add_argument('--image-weights', action='store_true', default=True, help='use weighted image selection for training')
parser.add_argument('--name', default='', help='renames experiment folder exp{N} to exp{N}_{name} if supplied')
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--multi-scale', action='store_true', default=False, help='vary img-size +/- 50%%')#是否多尺度训练
parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset')#是否一个类别
parser.add_argument('--adam', action='store_true', default=False, help='use torch.optim.Adam() optimizer')#优化器选择
parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')#跨GPU的BN
parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')#GPU ID
parser.add_argument('--logdir', type=str, default='DNF_runs/', help='logging directory')
parser.add_argument('--workers', type=int, default=0, help='maximum number of dataloader workers')#windows的同学别改
opt = parser.parse_args()
print(opt)
```python
在这里插入代码片
4. 开始玩游戏了
我们将训练好的yolov5模型加载,然后通过实时的屏幕抓取对每一帧图像做目标检测,如果检测到图片中有怪物和自身角色,那么记录自己的坐标和怪物的坐标,通过虚拟按键向怪物所在位置移动;如果怪物没清空了并且地上有掉落的材料,那么控制角色靠近材料所在的坐标;如果怪物和材料都不存在,那么控制角色走向传送门的位置,即走向下一个房间,具体细节和原理在b站视频中有详细的介绍,这里给出部分代码:
main:
import numpy as np
from grabscreen import grab_screen
import cv2
import time
import directkeys
import torch
from torch.autograd import Variable
from directkeys import PressKey, ReleaseKey, key_down, key_up
from getkeys import key_check
from utils.torch_utils import select_device, load_classifier, time_synchronized
from utils.general import (
check_img_size, non_max_suppression, apply_classifier, scale_coords,
xyxy2xywh, xywh2xyxy, plot_one_box, strip_optimizer, set_logging)
from models.experimental import attempt_load
from direction_move import move
from small_recgonize import current_door, next_door
from skill_recgnize import skill_rec
import random
def letterbox(img, new_shape=(640, 640), color=(114, 114, 114), auto=False, scaleFill=False, scaleup=True):
# Resize image to a 32-pixel-multiple rectangle https://github.com/ultralytics/yolov3/issues/232
shape = img.shape[:2] # current shape [height, width]
if isinstance(new_shape, int):
new_shape = (new_shape, new_shape)
# Scale ratio (new / old)
r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
if not scaleup: # only scale down, do not scale up (for better test mAP)
r = min(r, 1.0)
# Compute padding
ratio = r, r # width, height ratios
new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
if auto: # minimum rectangle
dw, dh = np.mod(dw, 64), np.mod(dh, 64) # wh padding
elif scaleFill: # stretch
dw, dh = 0.0, 0.0
new_unpad = (new_shape[1], new_shape[0])
ratio = new_shape[1] / shape[1], new_shape[0] / shape[0] # width, height ratios
dw /= 2 # divide padding into 2 sides
dh /= 2
if shape[::-1] != new_unpad: # resize
img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)
top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
return img, ratio, (dw, dh)
# 设置所有用到的参数
weights = r'E:\Computer_vision\yolov5\YOLO5\yolov5-master\DNF_runs\4s\weights\best.pt' #yolo5 模型存放的位置
# weights = r'F:\Computer_vision\yolov5\YOLO5\yolov5-master\runs\exp0\weights\best.pt'
device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")
# device = torch.device("cpu")
model = attempt_load(weights, map_location=device) # load FP32 model
window_size = (0,0,1280,800) # 截屏的位置
img_size = 608 # 输入到yolo5中的模型尺寸
paused = False
half = device.type != 'cpu'
view_img = True # 是否观看目标检测结果
save_txt = False
conf_thres = 0.3 # NMS的置信度过滤
iou_thres = 0.2 # NMS的IOU阈值
classes = None
agnostic_nms = False # 不同类别的NMS时也参数过滤
skill_char = "XYHGXFAXDSWXETX" # 技能按键,使用均匀分布随机抽取
direct_dic = {"UP": 0xC8, "DOWN": 0xD0, "LEFT": 0xCB, "RIGHT": 0xCD} # 上下左右的键码
names = ['hero', 'small_map', "monster", 'money', 'material', 'door', 'BOSS', 'box', 'options'] # 所有类别名
colors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(names))]
if half:
model.half() # to FP16
action_cache = None # 动作标记
press_delay = 0.1 # 按压时间
release_delay = 0.1 # 释放时间
# last_time = time.time()
frame = 0 # 帧
door1_time_start = -20
next_door_time = -20
fs = 1 # 每四帧处理一次
# 倒计时
for i in list(range(5))[::-1]:
print(i + 1)
time.sleep(1)
# 捕捉画面+目标检测+玩游戏
while True:
if not paused:
t_start = time.time()
img0 = grab_screen(window_size)
frame += 1
if frame % fs == 0:
# img0 = cv2.imread("datasets/guiqi/yolo5_datasets/imgs/1004_14.jpg")
img0 = cv2.cvtColor(img0, cv2.COLOR_BGRA2BGR)
# Padded resize
img = letterbox(img0, new_shape=img_size)[0]
# Convert
img = img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).to(device).unsqueeze(0)
img = img.half() if half else img.float() # uint8 to fp16/32
img /= 255.0 # 0 - 255 to 0.0 - 1.0
pred = model(img, augment=False)[0]
# Apply NMS
det = non_max_suppression(pred, conf_thres, iou_thres, classes=classes, agnostic=agnostic_nms)
gn = torch.tensor(img0.shape)[[1, 0, 1, 0]]
det = det[0]
if det is not None and len(det):
# Rescale boxes from img_size to im0 size
det[:, :4] = scale_coords(img.shape[2:], det[:, :4], img0.shape).round()
# Print results
for c in det[:, -1].unique():
n = (det[:, -1] == c).sum() # detections per class
img_object = []
cls_object = []
# Write results
hero_conf = 0
hero_index = 0
for idx, (*xyxy, conf, cls) in enumerate(reversed(det)):
# if save_txt: # Write to file
# xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
# with open(txt_path + '.txt', 'a') as f:
# f.write(('%g ' * 5 + '\n') % (cls, *xywh)) # label format
xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4))).view(-1).tolist()
cls = int(cls)
img_object.append(xywh)
cls_object.append(names[cls])
if names[cls] == "hero" and conf > hero_conf:
hero_conf = conf
hero_index = idx
if view_img: # Add bbox to image
label = '%s %.2f' % (names[int(cls)], conf)
plot_one_box(xyxy, img0, label=label, color=colors[int(cls)], line_thickness=2)
# 游戏
thx = 30 # 捡东西时,x方向的阈值
thy = 30 # 捡东西时,y方向的阈值
attx = 150 # 攻击时,x方向的阈值
atty = 50 # 攻击时,y方向的阈值
if current_door(img0) == 1 and time.time() - door1_time_start > 10:
door1_time_start = time.time()
# move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
# release_delay=release_delay)
# ReleaseKey(direct_dic["RIGHT"])
# directkeys.key_press("SPACE")
directkeys.key_press("CTRL")
time.sleep(1)
directkeys.key_press("ALT")
time.sleep(0.5)
action_cache = None
# 扫描英雄
if "hero" in cls_object:
# hero_xywh = img_object[cls_object.index("hero")]
hero_xywh = img_object[hero_index]
cv2.circle(img0, (int(hero_xywh[0]), int(hero_xywh[1])), 1, (0,0,255), 10)
# print(hero_index)
# print(cls_object.index("hero"))
else:
continue
# 打怪
if "monster" in cls_object or "BOSS" in cls_object:
min_distance = float("inf")
for idx, (c, box) in enumerate(zip(cls_object, img_object)):
if c == 'monster' or c == "BOSS":
dis = ((hero_xywh[0] - box[0])**2 + (hero_xywh[1] - box[1])**2)**0.5
if dis < min_distance:
monster_box = box
monster_index = idx
min_distance = dis
if abs(hero_xywh[0] - monster_box[0]) < attx and abs(hero_xywh[1] - monster_box[1]) < atty:
if "BOSS" in cls_object:
directkeys.key_press("R")
directkeys.key_press("Q")
# time.sleep(0.5)
skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]
while True:
if skill_rec(skill_name, img0):
directkeys.key_press(skill_name)
directkeys.key_press(skill_name)
directkeys.key_press(skill_name)
break
else:
skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]
else:
skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]
while True:
if skill_rec(skill_name, img0):
directkeys.key_press(skill_name)
directkeys.key_press(skill_name)
directkeys.key_press(skill_name)
break
else:
skill_name = skill_char[int(np.random.randint(len(skill_char), size=1)[0])]
print("释放技能攻击")
if not action_cache:
pass
elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
action_cache = None
elif action_cache:
ReleaseKey(direct_dic[action_cache])
action_cache = None
# break
elif monster_box[1] - hero_xywh[1] < 0 and monster_box[0] - hero_xywh[0] > 0:
if abs(monster_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - monster_box[1] < monster_box[0] - hero_xywh[0]:
action_cache = move(direct="RIGHT_UP", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - monster_box[1] >= monster_box[0] - hero_xywh[0]:
action_cache = move(direct="UP", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
elif monster_box[1] - hero_xywh[1] < 0 and monster_box[0] - hero_xywh[0] < 0:
if abs(monster_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - monster_box[1] < hero_xywh[0] - monster_box[0]:
action_cache = move(direct="LEFT_UP", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - monster_box[1] >= hero_xywh[0] - monster_box[0]:
action_cache = move(direct="UP", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
elif monster_box[1] - hero_xywh[1] > 0 and monster_box[0] - hero_xywh[0] < 0:
if abs(monster_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif monster_box[1] - hero_xywh[1] < hero_xywh[0] - monster_box[0]:
action_cache = move(direct="LEFT_DOWN", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
elif monster_box[1] - hero_xywh[1] >= hero_xywh[0] - monster_box[0]:
action_cache = move(direct="DOWN", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
elif monster_box[1] - hero_xywh[1] > 0 and monster_box[0] - hero_xywh[0] > 0:
if abs(monster_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif monster_box[1] - hero_xywh[1] < monster_box[0] - hero_xywh[0]:
action_cache = move(direct="RIGHT_DOWN", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
elif monster_box[1] - hero_xywh[1] >= monster_box[0] - hero_xywh[0]:
action_cache = move(direct="DOWN", material=True, action_cache=action_cache,
press_delay=press_delay,
release_delay=release_delay)
# break
# 移动到下一个地图
if "door" in cls_object and "monster" not in cls_object and "BOSS" not in cls_object and "material" not in cls_object and "money" not in cls_object:
for idx, (c, box) in enumerate(zip(cls_object, img_object)):
if c == 'door':
door_box = box
door_index = idx
if door_box[0] < img0.shape[0] // 2:
action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] < 0 and door_box[0] - hero_xywh[0] > 0:
if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
action_cache = None
print("进入下一地图")
# break
elif abs(door_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - door_box[1] < door_box[0] - hero_xywh[0]:
action_cache = move(direct="RIGHT_UP", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - door_box[1] >= door_box[0] - hero_xywh[0]:
action_cache = move(direct="UP", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] < 0 and door_box[0] - hero_xywh[0] < 0:
if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
action_cache = None
print("进入下一地图")
# break
elif abs(door_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="LEFT", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - door_box[1] < hero_xywh[0] - door_box[0]:
action_cache = move(direct="LEFT_UP", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - door_box[1] >= hero_xywh[0] - door_box[0]:
action_cache = move(direct="UP", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] > 0 and door_box[0] - hero_xywh[0] < 0:
if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
action_cache = None
print("进入下一地图")
# break
elif abs(door_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="LEFT", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] < hero_xywh[0] - door_box[0]:
action_cache = move(direct="LEFT_DOWN", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] >= hero_xywh[0] - door_box[0]:
action_cache = move(direct="DOWN", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] > 0 and door_box[0] - hero_xywh[0] > 0:
if abs(door_box[1] - hero_xywh[1]) < thy and abs(door_box[0] - hero_xywh[0]) < thx:
action_cache = None
print("进入下一地图")
# break
elif abs(door_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] < door_box[0] - hero_xywh[0]:
action_cache = move(direct="RIGHT_DOWN", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif door_box[1] - hero_xywh[1] >= door_box[0] - hero_xywh[0]:
action_cache = move(direct="DOWN", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
if "money" not in cls_object and "material" not in cls_object and "monster" not in cls_object \
and "BOSS" not in cls_object and "door" not in cls_object and 'box' not in cls_object \
and 'options' not in cls_object:
# if next_door(img0) == 0 and abs(time.time()) - next_door_time > 10:
# next_door_time = time.time()
# action_cache = move(direct="LEFT", action_cache=action_cache, press_delay=press_delay,
# release_delay=release_delay)
# # time.sleep(3)
# else:
# action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
# release_delay=release_delay)
action_cache = move(direct="RIGHT", action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
# 捡材料
if "monster" not in cls_object and "hero" in cls_object and ("material" in cls_object or "money" in cls_object):
min_distance = float("inf")
hero_xywh[1] = hero_xywh[1] + (hero_xywh[3] // 2) * 0.7
thx = thx / 2
thy = thy / 2
for idx, (c, box) in enumerate(zip(cls_object, img_object)):
if c == 'material' or c == "money":
dis = ((hero_xywh[0] - box[0]) ** 2 + (hero_xywh[1] - box[1]) ** 2) ** 0.5
if dis < min_distance:
material_box = box
material_index = idx
min_distance = dis
if abs(material_box[1] - hero_xywh[1]) < thy and abs(material_box[0] - hero_xywh[0]) < thx:
if not action_cache:
pass
elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
action_cache = None
else:
ReleaseKey(direct_dic[action_cache])
action_cache = None
time.sleep(1)
directkeys.key_press("X")
print("捡东西")
# break
elif material_box[1] - hero_xywh[1] < 0 and material_box[0] - hero_xywh[0] > 0:
if abs(material_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - material_box[1] < material_box[0] - hero_xywh[0]:
action_cache = move(direct="RIGHT_UP", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - material_box[1] >= material_box[0] - hero_xywh[0]:
action_cache = move(direct="UP", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif material_box[1] - hero_xywh[1] < 0 and material_box[0] - hero_xywh[0] < 0:
if abs(material_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - material_box[1] < hero_xywh[0] - material_box[0]:
action_cache = move(direct="LEFT_UP", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif hero_xywh[1] - material_box[1] >= hero_xywh[0] - material_box[0]:
action_cache = move(direct="UP", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif material_box[1] - hero_xywh[1] > 0 and material_box[0] - hero_xywh[0] < 0:
if abs(material_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="LEFT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif material_box[1] - hero_xywh[1] < hero_xywh[0] - material_box[0]:
action_cache = move(direct="LEFT_DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif material_box[1] - hero_xywh[1] >= hero_xywh[0] - material_box[0]:
action_cache = move(direct="DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif material_box[1] - hero_xywh[1] > 0 and material_box[0] - hero_xywh[0] > 0:
if abs(material_box[1] - hero_xywh[1]) < thy:
action_cache = move(direct="RIGHT", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif material_box[1] - hero_xywh[1] < material_box[0] - hero_xywh[0]:
action_cache = move(direct="RIGHT_DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
elif material_box[1] - hero_xywh[1] >= material_box[0] - hero_xywh[0]:
action_cache = move(direct="DOWN", material=True, action_cache=action_cache, press_delay=press_delay,
release_delay=release_delay)
# break
# 开箱子
if "box" in cls_object:
box_num = 0
for b in cls_object:
if b == "box":
box_num += 1
if box_num >= 4:
directkeys.key_press("ESC")
print("打开箱子ESC")
# break62
# 重新开始
time_option = -20
if "options" in cls_object:
if not action_cache:
pass
elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
action_cache = None
else:
ReleaseKey(direct_dic[action_cache])
action_cache = None
if time.time() - time_option > 10:
directkeys.key_press("NUM0")
print("移动物品到脚下")
directkeys.key_press("X")
time_option = time.time()
directkeys.key_press("F2")
print("重新开始F2")
# break
t_end = time.time()
print("一帧游戏操作所用时间:", (t_end - t_start)/fs)
img0 = cv2.resize(img0, (600, 375))
# Stream results
if view_img:
cv2.imshow('window', img0)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
if cv2.waitKey(5) & 0xFF == ord('q'):
raise StopIteration
# Setting pause and unpause
keys = key_check()
if 'P' in keys:
if not action_cache:
pass
elif action_cache not in ["LEFT", "RIGHT", "UP", "DOWN"]:
ReleaseKey(direct_dic[action_cache.strip().split("_")[0]])
ReleaseKey(direct_dic[action_cache.strip().split("_")[1]])
action_cache = None
else:
ReleaseKey(direct_dic[action_cache])
action_cache = None
if paused:
paused = False
time.sleep(1)
else:
paused = True
time.sleep(1)