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:
zaixia108
2025-12-23 09:44:29 +08:00
parent 3f467ff158
commit 223d446d9a
+9 -6
View File
@@ -21,6 +21,7 @@ import win32gui
import win32api import win32api
import win32con import win32con
def get_process_info(process_name): def get_process_info(process_name):
""" """
Get process information for a given process name on Windows. Get process information for a given process name on Windows.
@@ -338,6 +339,7 @@ class GamepadEmulator:
self.gamepad.reset() self.gamepad.reset()
self.gamepad.update() self.gamepad.update()
class PyautoguiScreenshotBackend: class PyautoguiScreenshotBackend:
def __init__(self, bbox): def __init__(self, bbox):
@@ -346,15 +348,17 @@ class PyautoguiScreenshotBackend:
def screenshot(self): def screenshot(self):
return pyautogui.screenshot(region=self.bbox) return pyautogui.screenshot(region=self.bbox)
class DxcamScreenshotBackend: class DxcamScreenshotBackend:
def __init__(self, bbox): def __init__(self, bbox, fps):
import dxcam import dxcam
self.camera = dxcam.create() self.camera = dxcam.create()
self.bbox = bbox self.bbox = bbox
self.last_screenshot = None self.last_screenshot = None
self.camera.start(region=self.bbox, target_fps=fps, video_mode=True)
def screenshot(self): def screenshot(self):
screenshot = self.camera.grab(region=self.bbox) screenshot = self.camera.get_latest_frame()
if screenshot is None: if screenshot is None:
print("DXCAM failed to capture frame, trying to use the latest screenshot") print("DXCAM failed to capture frame, trying to use the latest screenshot")
if self.last_screenshot is not None: if self.last_screenshot is not None:
@@ -414,12 +418,12 @@ class GamepadEnv(Env):
self.game_arch = proc_info["architecture"] self.game_arch = proc_info["architecture"]
self.game_window_name = proc_info["window_name"] 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: if self.game_pid is None:
raise Exception(f"Could not find PID for game: {game}") raise Exception(f"Could not find PID for game: {game}")
self.observation_space = Box( self.observation_space = Box(
low=0, high=255, shape=(self.image_height, self.image_width, 3), dtype="uint8" low=0, high=255, shape=(self.image_height, self.image_width, 3), dtype="uint8"
) )
@@ -471,13 +475,12 @@ class GamepadEnv(Env):
# Get the screenshot backend # Get the screenshot backend
if screenshot_backend == "dxcam": if screenshot_backend == "dxcam":
self.screenshot_backend = DxcamScreenshotBackend(self.bbox) self.screenshot_backend = DxcamScreenshotBackend(self.bbox, self.env_fps)
elif screenshot_backend == "pyautogui": elif screenshot_backend == "pyautogui":
self.screenshot_backend = PyautoguiScreenshotBackend(self.bbox) self.screenshot_backend = PyautoguiScreenshotBackend(self.bbox)
else: else:
raise ValueError("Unsupported screenshot backend. Use 'dxcam' or 'pyautogui'.") raise ValueError("Unsupported screenshot backend. Use 'dxcam' or 'pyautogui'.")
def calculate_step_duration(self): def calculate_step_duration(self):
""" """
Calculate the step duration based on game speed and environment FPS. Calculate the step duration based on game speed and environment FPS.