> For the complete documentation index, see [llms.txt](https://docs.acrome.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.acrome.net/smd-applications/interactive/play-chrome-dino-game-with-joystick.md).

# Play Chrome Dino Game With Joystick

This project allows users to control the Google Chrome Dino game using a [joystick](/electronics/add-on-modules/joystick-module.md) connected through the [ACROME SMD](/electronics/smd-red.md) platform. The [joystick ](/electronics/add-on-modules/joystick-module.md)is mapped to the jump and duck actions in the game. When the [joystick ](/electronics/add-on-modules/joystick-module.md)is pushed up, the game character jumps (using the spacebar key), and when the [joystick ](/electronics/add-on-modules/joystick-module.md)is pushed down, the character ducks (using the down arrow key).

**About Tools and Materials:**

[SMD Red](https://docs.acrome.net/electronics/smd-red) ([Purchase Here](https://www.robotshop.com/products/acrome-smd-red-smart-brushed-motor-driver-with-speed-position-and-current-control-modes))

[SMD USB Gateway](https://docs.acrome.net/electronics/gateway-modules/usb-gateway-module) ([Purchase Here](https://www.robotshop.com/products/acrome-usb-gateway-module-acrome-smd-products))

[Joystick Module](/electronics/add-on-modules/joystick-module.md) ([Purchase Here](https://www.robotshop.com/products/acrome-joystick-2-axis-add-on-module-acrome-smd-products))

### **Step 1: Hardware & Software Overview** <a href="#step-1-hardware-and-software-overview" id="step-1-hardware-and-software-overview"></a>

**Key Components:**

1. [ACROME SMD](/electronics/smd-red.md) \
   The [ACROME SMD](/electronics/smd-red.md) platform acts as the communication hub, reading [joystick ](/electronics/add-on-modules/joystick-module.md)inputs and transmitting them to control the game. It collects data from the [joystick ](/electronics/add-on-modules/joystick-module.md)and processes it in real-time to translate movements into actions.
2. [Joystick Module ](/electronics/add-on-modules/joystick-module.md)\
   The [joystick ](/electronics/add-on-modules/joystick-module.md)is used to control the actions in the Dino game. Vertical movements (up and down) control the character’s ability to jump and duck, with the [joystick ](/electronics/add-on-modules/joystick-module.md)acting as a physical input interface.
3. GUI (Tkinter)\
   The graphical user interface (GUI) provides real-time feedback to the user, showing the current state of the [joystick ](/electronics/add-on-modules/joystick-module.md)and the action being performed (jump or duck). This ensures transparency in how the [joystick ](/electronics/add-on-modules/joystick-module.md)movements are translated into game actions.

**Project Key Features:**

1. Real-Time [Joystick ](/electronics/add-on-modules/joystick-module.md)Control \
   The [joystick](/electronics/add-on-modules/joystick-module.md) allows the user to control the Dino character’s movements. Moving the [joystick ](/electronics/add-on-modules/joystick-module.md)up makes the Dino jump, while moving it down makes the Dino duck.
2. Smooth Action Interpolation \
   To make the [joystick ](/electronics/add-on-modules/joystick-module.md)movements smoother and more responsive, interpolation is applied to the [joystick ](/electronics/add-on-modules/joystick-module.md)values. This ensures the actions are triggered only when the [joystick ](/electronics/add-on-modules/joystick-module.md)movement crosses a certain threshold.
3. Key State Management \
   The system ensures that the keys (spacebar for jumping, down arrow for ducking) are held down or released at the appropriate times based on the [joystick ](/electronics/add-on-modules/joystick-module.md)input. This prevents unnecessary key presses and makes the actions more accurate.
4. Graphical Feedback \
   The GUI continuously displays the current X and Y values of the [joystick ](/electronics/add-on-modules/joystick-module.md)and the action being performed, providing visual feedback for the user to monitor their input.

## **Step 2: Assemble** <a href="#step-2-assemble" id="step-2-assemble"></a>

**Getting Started**

1. **Hardware Setup**
   * Connect the SMD to the PC or Arduino board using [USB Gateway Module](https://docs.acrome.net/electronics/gateway-modules/usb-gateway-module) or [Arduino Gateway Module](https://docs.acrome.net/electronics/gateway-modules/arduino-gateway-module).
   * Connect the [Joystick Module](/electronics/add-on-modules/joystick-module.md) to the SMD using an RJ-45 cable.
   * Make sure that the SMD is powered and all connections are correct

#### Project Wiring Diagram

<figure><img src="/files/jENstWcJBQzFM4hM7a8h" alt=""><figcaption></figcaption></figure>

## Step 3: Run & Test

1. Joystick Input Monitoring: The system continuously reads the [joystick's ](/electronics/add-on-modules/joystick-module.md)X and Y values. The Y-axis value is the primary input for controlling the jump and duck actions.
2. Jump and Duck Actions: When the [joystick ](/electronics/add-on-modules/joystick-module.md)is moved upward (beyond a threshold), the system simulates a key press of the spacebar to make the Dino jump. When moved downward, it presses the down arrow key to make the Dino duck.
3. Key Release Management: When the [joystick ](/electronics/add-on-modules/joystick-module.md)returns to its neutral position, the system releases any pressed keys (spacebar or down arrow) to reset the character’s action in the game.
4. GUI Updates: The GUI continuously updates with the latest [joystick ](/electronics/add-on-modules/joystick-module.md)values and the current action (jump, duck, or none), giving the user real-time feedback on their input and the corresponding actions in the game.

## Code

{% tabs %}
{% tab title="Python Code" %}
{% code lineNumbers="true" %}

```python
import pyautogui
import tkinter as tk
import serial
from smd.red import Master, Red
from threading import Thread
import time
from serial.tools.list_ports import comports
from platform import system


# Serial Communication Settings
baudrate = 115200           # Baud rate for communication
module_id = 0               # ID of the SMD module
joystick_module_id = 5      # ID of the joystick module


# Joystick Thresholds
threshold = 0.10            # Minimum movement threshold for joystick activation
max_val = 100               # Maximum joystick value for normalization


# Dictionary to track key states
keys_state = {
    'space': False,         # Space key (jump action)
    'down': False           # Down arrow key (duck action)
}


def USB_Port():
    """
    Scans and identifies a compatible USB port for the current operating system.

    Returns:
        str: The detected USB port or None if no suitable port is found.
    """
    ports = list(comports())

    usb_names = {
        "Windows": ["USB Serial Port"],
        "Linux": ["/dev/ttyUSB"],
        "Darwin": [
            "/dev/tty.usbserial", "/dev/tty.usbmodem",
            "/dev/tty.SLAB_USBtoUART", "/dev/tty.wchusbserial",
            "/dev/cu.usbserial", "/dev/cu.usbmodem",
            "/dev/cu.SLAB_USBtoUART", "/dev/cu.wchusbserial",
        ]
    }

    os_name = system()
    print(f"Operating System: {os_name}")

    if ports:
        for port in ports:
            if any(name in port.device or name in port.description for name in usb_names.get(os_name, [])):
                print(f"USB device detected on port: {port.device}")
                return port.device
        print("No suitable USB device found. Available ports:")
        for port in ports:
            print(f"Port: {port.device}, Description: {port.description}, HWID: {port.hwid}")
    else:
        print("No ports detected!")
    return None


# Initialize the USB port and SMD module
SerialPort = USB_Port()
if not SerialPort:
    raise Exception("No compatible USB port found. Please check your connection.")

master = Master(SerialPort, baudrate)
master.attach(Red(module_id))
print("Connected Modules:", master.scan_modules(module_id))


# GUI Setup
root = tk.Tk()
root.title("Dino Game Controller")


# GUI Labels
joystick_label = tk.Label(root, text="Joystick State: (0, 0)", font=("Helvetica", 14))
joystick_label.pack(pady=10)

action_label = tk.Label(root, text="Action: None", font=("Helvetica", 14))
action_label.pack(pady=10)


def update_gui(x_val, y_val, action):
    """
    Updates the GUI to display the current joystick state and action.

    Args:
        x_val (float): The current x-axis value of the joystick.
        y_val (float): The current y-axis value of the joystick.
        action (str): The current action being performed (e.g., "Jump", "Duck", "None").
    """
    joystick_label.config(text=f"Joystick State: ({x_val:.2f}, {y_val:.2f})")
    action_label.config(text=f"Action: {action}")


def interpolate_value(value):
    """
    Normalizes joystick values and smooths movement.

    Args:
        value (float): The joystick input value.

    Returns:
        float: The interpolated value with smooth acceleration effect.
    """
    return (value / max_val) ** 2 * (1 if value > 0 else -1)


def joystick_control():
    """
    Continuously reads joystick data and translates movements into key presses.

    - Moves up (jump) when pushing joystick forward (Y > threshold).
    - Moves down (duck) when pulling joystick backward (Y < -threshold).
    - Releases keys when joystick is neutral.
    """
    action = "None"

    while True:
        joystick = master.get_joystick(module_id, joystick_module_id)

        if joystick is not None:
            x_val, y_val = joystick[0], joystick[1]
            y_val_smooth = interpolate_value(y_val)

            if abs(y_val_smooth) > threshold:
                # Jump (Up movement - Space key)
                if y_val_smooth > threshold:
                    if not keys_state['space']:
                        pyautogui.keyDown('space')
                        keys_state['space'] = True
                        action = "Jump"
                        update_gui(x_val, y_val, action)
                
                # Duck (Down movement - Down arrow key)
                elif y_val_smooth < -threshold:
                    if not keys_state['down']:
                        pyautogui.keyDown('down')
                        keys_state['down'] = True
                        action = "Duck"
                        update_gui(x_val, y_val, action)
            else:
                # Release keys if joystick is in neutral position
                if keys_state['space']:
                    pyautogui.keyUp('space')
                    keys_state['space'] = False
                    action = "None"
                
                if keys_state['down']:
                    pyautogui.keyUp('down')
                    keys_state['down'] = False
                    action = "None"

            # Update GUI
            update_gui(x_val, y_val, action)

        # Short delay to prevent excessive loop execution
        time.sleep(0.01)


# Start Joystick Control Thread
joystick_thread = Thread(target=joystick_control, daemon=True)
joystick_thread.start()

# Start GUI Main Loop
root.mainloop()
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Conclusion:** \
This project demonstrates how the [ACROME SMD ](/electronics/smd-red.md)platform can be used to create a joystick-controlled system for playing the Dino game. By integrating real-time [joystick](/electronics/add-on-modules/joystick-module.md) input, smooth interpolation, and graphical feedback, the system offers a fun and interactive way to control the game.
