Skip to content

Human Benchmarking Macro

This example demonstrates how to build a reactive bot by splitting logic into two specialized tasks: a Scanner and a Bot. This "Producer-Consumer" pattern is the most efficient way to handle high-speed pixel monitoring without blocking the UI or engine.

Key Concepts

1. Decoupled State Management

Instead of having one massive function that scans and clicks, we separate the concerns into two classes:

  • BenchmarkScanner: Responsible only for visual input. It updates a boolean flag, is_target_color, as fast as the engine allows.
  • ReactionBot: Watches that flag and executes the click the millisecond it turns true.

2. Using Global Variables with addVar

To make the macro flexible, we use the engine's built-in variable system. This allows the user to pick the target point and color through the UI rather than hardcoding coordinates:

  • CaptureMode.POINT: Opens a crosshair for the user to select the click location.
  • CaptureMode.COLOR: Opens a color picker to define exactly what shade of "Green" the bot is looking for.

3. High-Frequency Polling (repeat=True)

By setting repeat=True when calling addBasicTask, these functions act as high-speed loops. The engine automatically handles the re-execution, allowing the scanner to poll the screen colors continuously.

4. Edge Triggering and Debouncing

To prevent the bot from clicking a thousand times while the screen is green, we implement a simple state check:

  • State Locking: We use clicked_already to ensure only one click occurs per color change.
  • The Reset: The flag is only reset when the is_target_color returns to false (when the screen turns red or blue again), preparing the bot for the next round.

The Implementation

This setup uses pydirectinput to click once the color is detected.

examples/human_benchmark_macro.py
class BenchmarkScanner:
    """Constantly polls the screen to see if the target color has appeared."""
    is_target_color = False

    def __init__(self, studio: MacroStudio):
        # Register the scanning task
        studio.addBasicTask(self.scanColor, repeat=True, display_name="Scan Target Color")

        # Register variables.
        studio.addVar(CLICK_PT_ID, CaptureMode.POINT, pick_hint="Click the center of the benchmark area")
        studio.addVar(TARGET_COLOR_ID, CaptureMode.COLOR, default_val=QColor("#4bdb6a"), pick_hint="Pick the green screen color")

    def scanColor(self, controller: Controller):
        target_pt = controller.getVar(CLICK_PT_ID)
        target_color = controller.getVar(TARGET_COLOR_ID)

        # Safety check in case the user hasn't set the point yet
        if not target_pt or not target_color:
            return

        screen_color = captureScreenColor(target_pt)

        # Using a very tight tolerance (5) because the website's green is perfectly consistent
        self.is_target_color = isColorSimilar(screen_color, target_color, tolerance=5)


class ReactionBot:
    """Fires a click the exact millisecond the scanner detects the color."""
    clicked_already = False

    def __init__(self, studio: MacroStudio, scanner: BenchmarkScanner):
        self.scanner = scanner
        # Register the clicking task
        studio.addBasicTask(self.clickWhenReady, repeat=True, display_name="Lightning Click")

    def clickWhenReady(self, controller: Controller):
        if self.scanner.is_target_color:
            if not self.clicked_already:
                click_pt = controller.getVar(CLICK_PT_ID)
                self.clicked_already = True

                # Execute the $O(1)$ click
                pydirectinput.leftClick(click_pt.x(), click_pt.y())

                # Yield briefly to prevent double-clicking while the screen transitions
                yield from taskSleep(0.1)
        else:
            # Reset the flag when the screen turns red or blue again
            self.clicked_already = False
View the complete runnable script
examples/human_benchmark_macro.py
import pydirectinput
from PySide6.QtGui import QColor
from macro_studio import MacroStudio, CaptureMode, Controller, taskSleep
from macro_studio.vision import captureScreenColor, isColorSimilar

CLICK_PT_ID = "click_pt"
TARGET_COLOR_ID = "target_color"

class BenchmarkScanner:
    """Constantly polls the screen to see if the target color has appeared."""
    is_target_color = False

    def __init__(self, studio: MacroStudio):
        # Register the scanning task
        studio.addBasicTask(self.scanColor, repeat=True, display_name="Scan Target Color")

        # Register variables.
        studio.addVar(CLICK_PT_ID, CaptureMode.POINT, pick_hint="Click the center of the benchmark area")
        studio.addVar(TARGET_COLOR_ID, CaptureMode.COLOR, default_val=QColor("#4bdb6a"), pick_hint="Pick the green screen color")

    def scanColor(self, controller: Controller):
        target_pt = controller.getVar(CLICK_PT_ID)
        target_color = controller.getVar(TARGET_COLOR_ID)

        # Safety check in case the user hasn't set the point yet
        if not target_pt or not target_color:
            return

        screen_color = captureScreenColor(target_pt)

        # Using a very tight tolerance (5) because the website's green is perfectly consistent
        self.is_target_color = isColorSimilar(screen_color, target_color, tolerance=5)


class ReactionBot:
    """Fires a click the exact millisecond the scanner detects the color."""
    clicked_already = False

    def __init__(self, studio: MacroStudio, scanner: BenchmarkScanner):
        self.scanner = scanner
        # Register the clicking task
        studio.addBasicTask(self.clickWhenReady, repeat=True, display_name="Lightning Click")

    def clickWhenReady(self, controller: Controller):
        if self.scanner.is_target_color:
            if not self.clicked_already:
                click_pt = controller.getVar(CLICK_PT_ID)
                self.clicked_already = True

                # Execute the $O(1)$ click
                pydirectinput.leftClick(click_pt.x(), click_pt.y())

                # Yield briefly to prevent double-clicking while the screen transitions
                yield from taskSleep(0.1)
        else:
            # Reset the flag when the screen turns red or blue again
            self.clicked_already = False

if __name__ == "__main__":
    # 1. Initialize the engine
    studio = MacroStudio("Human Benchmark Macro")

    # 2. Instantiate our classes, linking the bot to the scanner's state
    scanner = BenchmarkScanner(studio)
    ReactionBot(studio, scanner)

    # 3. Launch the UI!
    studio.launch()