-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGameEnv.py
158 lines (139 loc) · 4.72 KB
/
GameEnv.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
import struct
import pyMeow
import win32api, win32con, win32gui
from PIL import Image, ImageGrab
import torchvision
import pyautogui as pg
def get_window(window_name):
handle = win32gui.FindWindow(0, window_name)
# 获取窗口句柄
if handle == 0:
return None
else:
# 返回坐标值和handle
return win32gui.GetWindowRect(handle), handle
def fetch_image(window_name):
(x1, y1, x2, y2), handle = get_window(window_name)
# 发送还原最小化窗口的信息
win32gui.SendMessage(handle, win32con.WM_SYSCOMMAND, win32con.SC_RESTORE, 0)
# 设为高亮
win32gui.SetForegroundWindow(handle)
# 截图
grab_image = ImageGrab.grab((x1, y1, x2, y2))
return grab_image
def bytes2float(byte):
if byte == 0x0:
return 0.
temp = hex(byte)
ba = bytearray()
ba.append(int(temp[2:4], 16))
ba.append(int(temp[4:6], 16))
ba.append(int(temp[6:8], 16))
ba.append(int(temp[8:10], 16))
return struct.unpack("!f", ba)[0]
class VSEnv:
def __init__(self):
self.__last_exp = 0.
self.__last_hp = 100.
self.__img2tensor = torchvision.transforms.ToTensor()
self.__process = pyMeow.open_process("VampireSurvivors.exe")
self.__module = pyMeow.get_module(self.__process, "GameAssembly.dll")
addr_character_controller = self.__module["base"] + 0x042BE128
offset = [0xC0, 0x1D8, 0x98, 0x0, 0x18, 0x28, 0x168]
self.__addr_hp = pyMeow.pointer_chain(self.__process, addr_character_controller, offset)
offset = [0xC0, 0x1D8, 0x98, 0x0, 0x18, 0x28, 0x17C]
self.__addr_exp = pyMeow.pointer_chain(self.__process, addr_character_controller, offset)
offset = [0x70, 0x58, 0x64]
self.__addr_coins = pyMeow.pointer_chain(self.__process, addr_character_controller, offset)
addr_timer = self.__module["base"] + 0x0429FC28
offset = [0xB8, 0x0, 0x10, 0x28, 0x100, 0x28, 0x2A0]
self.__addr_time = pyMeow.pointer_chain(self.__process, addr_timer, offset)
def __get_screen(self, name="Vampire Survivors"):
img = fetch_image(name)
ret = self.__img2tensor(img)
return ret
def __get_state(self):
state = screen = self.__get_screen()
# hp = self.read_hp()
# exp = self.read_exp()
# state = [screen, hp, exp]
return state
def __get_reward(self):
# Rewards in stage 1, only calculate the difference of hp
# get minus rewards when lose hp and positive rewards when get heal
if self.__last_hp == 0.:
return 0
temp = self.read_hp()
reward = temp - self.__last_hp
self.__last_hp = temp
return reward
def read_hp(self):
return bytes2float(pyMeow.r_int(self.__process, self.__addr_hp))
def read_exp(self):
return bytes2float(pyMeow.r_int(self.__process, self.__addr_exp))
def read_coins(self):
return bytes2float(pyMeow.r_int(self.__process, self.__addr_coins))
def read_time(self):
return bytes2float(pyMeow.r_int(self.__process, self.__addr_time))
def reset(self):
self.__last_exp = 0.
self.__last_hp = 0.
pg.PAUSE = 1.5
pg.press('esc')
pg.press('esc')
pg.press('esc')
pg.press('space')
pg.press('space')
pg.press('space')
pg.press('d')
pg.press('space')
state = self.__get_state()
pg.PAUSE = .01
pg.press('esc')
return state
def step(self, action, step_time):
pg.PAUSE = .01
pg.press('esc')
pg.PAUSE = step_time
if action == 0:
pg.keyDown('w')
pg.PAUSE = .01
pg.press('w')
elif action == 1:
pg.keyDown('w', 'd')
pg.PAUSE = .01
pg.press('w', 'd')
elif action == 2:
pg.keyDown('d')
pg.PAUSE = .01
pg.press('d')
elif action == 3:
pg.keyDown('s', 'd')
pg.PAUSE = .01
pg.press('s', 'd')
elif action == 4:
pg.keyDown('s')
pg.PAUSE = .01
pg.press('s')
elif action == 5:
pg.keyDown('s', 'a')
pg.PAUSE = .01
pg.press('s', 'a')
elif action == 6:
pg.keyDown('a')
pg.PAUSE = .01
pg.press('a')
elif action == 7:
pg.keyDown('a', 'w')
pg.PAUSE = .01
pg.press('a', 'w')
elif action == 8:
pg.PAUSE = .01
pg.press('space')
state = self.__get_state()
pg.press('esc')
reward = self.__get_reward()
done = False
if self.read_hp() <= 0:
done = True
return state, reward, done