Clay GameController Plugin

The Clay GameController plugin provides a unified game input system that supports multiple input sources including keyboard, physical gamepads, and touchscreen controls. It's designed with simplicity in mind, offering NES-style controller functionality with directional controls and two action buttons.

Getting Started

To use the Clay GameController plugin in your QML files:

import Clayground.GameController

Core Components

  • GameController - Main unified input component with axis and button states
  • GameControllerDV - Debug visualization showing current controller state
  • KeyboardGamepad - Internal keyboard-to-controller mapping
  • TouchscreenGamepad - Virtual on-screen gamepad for touch devices
  • GamepadWrapper - Qt Gamepad API wrapper (currently disabled in Qt6)
  • Usage Examples

    Basic Controller Setup

    
    import QtQuick
    import Clayground.GameController
    
    Item {
        GameController {
            id: controller
    
            // Enable debug visualization
            showDebugOverlay: true
    
            Component.onCompleted: {
                // Try gamepad first, fallback to keyboard
                if (numConnectedGamepads > 0)
                    selectGamepad(0, true)  // Use analog sticks
                else
                    selectKeyboard(
                        Qt.Key_W,      // Up
                        Qt.Key_S,      // Down
                        Qt.Key_A,      // Left
                        Qt.Key_D,      // Right
                        Qt.Key_Space,  // Button A
                        Qt.Key_Return  // Button B
                    )
            }
        }
    }
    

    Player Movement

    
    Rectangle {
        id: player
        width: 50
        height: 50
        color: "blue"
    
        GameController {
            id: controller
            anchors.fill: parent
        }
    
        // Move player based on controller input
        x: x + controller.axisX * 5
        y: y - controller.axisY * 5  // Invert Y for screen coordinates
    
        // Change color when buttons pressed
        color: controller.buttonAPressed ? "red" :
               controller.buttonBPressed ? "green" : "blue"
    }
    

    Multi-Controller Support

    
    Row {
        GameController {
            id: player1Controller
            Component.onCompleted: {
                if (numConnectedGamepads > 0)
                    selectGamepad(0, false)  // Use D-pad
                else
                    selectKeyboard(
                        Qt.Key_Up, Qt.Key_Down,
                        Qt.Key_Left, Qt.Key_Right,
                        Qt.Key_M, Qt.Key_N
                    )
            }
        }
    
        GameController {
            id: player2Controller
            Component.onCompleted: {
                if (numConnectedGamepads > 1)
                    selectGamepad(1, false)
                else
                    selectTouchscreenGamepad()
            }
        }
    }
    

    Touch Controls for Mobile

    
    GameController {
        id: mobileController
        anchors.fill: parent
    
        Component.onCompleted: {
            // Auto-select input based on platform
            if (Qt.platform.os === "android" || Qt.platform.os === "ios") {
                selectTouchscreenGamepad()
            } else {
                selectKeyboard(
                    Qt.Key_Up, Qt.Key_Down,
                    Qt.Key_Left, Qt.Key_Right,
                    Qt.Key_X, Qt.Key_Z
                )
            }
        }
    }
    

    Custom Input Handling

    
    GameController {
        id: controller
    
        // React to input changes
        onAxisXChanged: {
            if (axisX > 0.5)
                console.log("Moving right")
            else if (axisX < -0.5)
                console.log("Moving left")
        }
    
        onButtonAPressedChanged: {
            if (buttonAPressed)
                console.log("Jump!")
        }
    }
    

    Best Practices

    1. Input Priority: Always check for gamepads first, then fall back to keyboard or touch controls. 2. Dead Zones: The gamepad implementation includes a 0.2 dead zone for analog sticks to prevent drift. 3. Platform Detection: Use Qt.platform.os to automatically select appropriate input methods. 4. Key Forwarding: Use Keys.forwardTo to ensure the controller receives keyboard input. 5. Debug Mode: Enable showDebugOverlay during development to visualize input states.

    Technical Implementation

    The GameController plugin implements:
  • Unified API: Single interface for all input types
  • Auto-switching: Seamless switching between input sources
  • Visual Feedback: Built-in debug visualization
  • Touch Adaptation: Virtual joystick with visual feedback for touch screens
  • Simple Design: NES-inspired two-button controller for broad compatibility
  • Note: Physical gamepad support is currently disabled due to Qt6 compatibility issues but the architecture supports it for future versions.