Revise the screen capture method to continuous grabbing and extract the latest frame to address the issue of "DXCAM failed to capture frame, trying to use the latest screenshot"
This commit is contained in:
+19
-16
@@ -21,6 +21,7 @@ import win32gui
|
||||
import win32api
|
||||
import win32con
|
||||
|
||||
|
||||
def get_process_info(process_name):
|
||||
"""
|
||||
Get process information for a given process name on Windows.
|
||||
@@ -338,6 +339,7 @@ class GamepadEmulator:
|
||||
self.gamepad.reset()
|
||||
self.gamepad.update()
|
||||
|
||||
|
||||
class PyautoguiScreenshotBackend:
|
||||
|
||||
def __init__(self, bbox):
|
||||
@@ -346,15 +348,17 @@ class PyautoguiScreenshotBackend:
|
||||
def screenshot(self):
|
||||
return pyautogui.screenshot(region=self.bbox)
|
||||
|
||||
|
||||
class DxcamScreenshotBackend:
|
||||
def __init__(self, bbox):
|
||||
def __init__(self, bbox, fps):
|
||||
import dxcam
|
||||
self.camera = dxcam.create()
|
||||
self.bbox = bbox
|
||||
self.last_screenshot = None
|
||||
self.camera.start(region=self.bbox, target_fps=fps, video_mode=True)
|
||||
|
||||
def screenshot(self):
|
||||
screenshot = self.camera.grab(region=self.bbox)
|
||||
screenshot = self.camera.get_latest_frame()
|
||||
if screenshot is None:
|
||||
print("DXCAM failed to capture frame, trying to use the latest screenshot")
|
||||
if self.last_screenshot is not None:
|
||||
@@ -381,15 +385,15 @@ class GamepadEnv(Env):
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
game,
|
||||
image_height=1440,
|
||||
image_width=2560,
|
||||
controller_type="xbox",
|
||||
game_speed=1.0,
|
||||
env_fps=10,
|
||||
async_mode=True,
|
||||
screenshot_backend="dxcam",
|
||||
self,
|
||||
game,
|
||||
image_height=1440,
|
||||
image_width=2560,
|
||||
controller_type="xbox",
|
||||
game_speed=1.0,
|
||||
env_fps=10,
|
||||
async_mode=True,
|
||||
screenshot_backend="dxcam",
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
@@ -414,12 +418,12 @@ class GamepadEnv(Env):
|
||||
self.game_arch = proc_info["architecture"]
|
||||
self.game_window_name = proc_info["window_name"]
|
||||
|
||||
print(f"Game process found: {self.game} (PID: {self.game_pid}, Arch: {self.game_arch}, Window: {self.game_window_name})")
|
||||
print(
|
||||
f"Game process found: {self.game} (PID: {self.game_pid}, Arch: {self.game_arch}, Window: {self.game_window_name})")
|
||||
|
||||
if self.game_pid is None:
|
||||
raise Exception(f"Could not find PID for game: {game}")
|
||||
|
||||
|
||||
self.observation_space = Box(
|
||||
low=0, high=255, shape=(self.image_height, self.image_width, 3), dtype="uint8"
|
||||
)
|
||||
@@ -464,20 +468,19 @@ class GamepadEnv(Env):
|
||||
|
||||
self.game_window.activate()
|
||||
l, t, r, b = self.game_window.left, self.game_window.top, self.game_window.right, self.game_window.bottom
|
||||
self.bbox = (l, t, r-l, b-t)
|
||||
self.bbox = (l, t, r - l, b - t)
|
||||
|
||||
# Initialize speedhack client if using DLL injection
|
||||
self.speedhack_client = xsh.Client(process_id=self.game_pid, arch=self.game_arch)
|
||||
|
||||
# Get the screenshot backend
|
||||
if screenshot_backend == "dxcam":
|
||||
self.screenshot_backend = DxcamScreenshotBackend(self.bbox)
|
||||
self.screenshot_backend = DxcamScreenshotBackend(self.bbox, self.env_fps)
|
||||
elif screenshot_backend == "pyautogui":
|
||||
self.screenshot_backend = PyautoguiScreenshotBackend(self.bbox)
|
||||
else:
|
||||
raise ValueError("Unsupported screenshot backend. Use 'dxcam' or 'pyautogui'.")
|
||||
|
||||
|
||||
def calculate_step_duration(self):
|
||||
"""
|
||||
Calculate the step duration based on game speed and environment FPS.
|
||||
|
||||
Reference in New Issue
Block a user