You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

11 KiB

Game Profile Manager

A PySDL2-based user profile management system designed for gamepad-only control with virtual keyboard input. This system allows players to create, edit, delete, and select user profiles for games using only gamepad inputs or directional keys, with no need for physical keyboard text input.

Features

  • 640x480 Resolution: Optimized for retro gaming systems and handheld devices
  • Create New Profiles: Add new user profiles with custom names using virtual keyboard
  • Profile Selection: Browse and select active profiles
  • Edit Settings: Modify profile settings including difficulty, volume levels, and preferences
  • Delete Profiles: Remove unwanted profiles
  • Gamepad/Directional Navigation: Full control using only gamepad/joystick inputs or arrow keys
  • Virtual Keyboard: Text input using directional controls - no physical keyboard typing required
  • JSON Storage: Profiles stored in human-readable JSON format
  • Persistent Settings: All changes automatically saved

Installation

Requirements

  • Python 3.6+
  • PySDL2
  • SDL2 library

Setup

# Install required Python packages
pip install pysdl2

# For Ubuntu/Debian users, you may also need:
sudo apt-get install libsdl2-dev libsdl2-ttf-dev

# Make launcher executable
chmod +x launch_profile_manager.sh

Usage

Running the Profile Manager

# Method 1: Use the launcher script
./launch_profile_manager.sh

# Method 2: Run directly with Python
python3 profile_manager.py

Gamepad Controls

Standard Gamepad Layout (Xbox/PlayStation compatible)

  • D-Pad/Hat: Navigate menus up/down/left/right, control virtual keyboard cursor
  • Button 0 (A/X): Confirm selection, enter menus, select virtual keyboard characters
  • Button 1 (B/Circle): Go back, cancel action
  • Button 2 (X/Square): Delete profile, backspace in virtual keyboard
  • Button 3 (Y/Triangle): Reserved for future features

Keyboard Controls (Alternative)

  • Arrow Keys: Navigate menus and virtual keyboard cursor
  • Enter/Space: Confirm selection, select virtual keyboard characters
  • Escape: Go back, cancel action
  • Delete/Backspace: Delete profile, backspace in virtual keyboard
  • Tab: Reserved for future features

Virtual Keyboard Text Input

When creating or editing profile names:

  1. Navigate: Use D-Pad/Arrow Keys to move cursor over virtual keyboard
  2. Select Character: Press A/Enter to add character to profile name
  3. Backspace: Press X/Delete to remove last character
  4. Complete: Navigate to "DONE" and press A/Enter to finish input
  5. Cancel: Navigate to "CANCEL" and press A/Enter to abort

Navigation Flow

  1. Main Menu: Create Profile → Select Profile → Edit Settings → Exit
  2. Profile List: Choose from existing profiles, or go back
  3. Create Profile: Use virtual keyboard to enter name, confirm with directional controls
  4. Edit Profile: Adjust settings using left/right navigation

Display Specifications

  • Resolution: 640x480 pixels (4:3 aspect ratio)
  • Optimized for: Retro gaming systems, handheld devices, embedded systems
  • Font Scaling: Adaptive font sizes for optimal readability at low resolution

Profile Structure

Profiles are stored in user_profiles.json with the following structure:

{
  "profiles": {
    "PlayerName": {
      "name": "PlayerName",
      "created_date": "2024-01-15T10:30:00",
      "last_played": "2024-01-20T14:45:00", 
      "games_played": 25,
      "total_score": 15420,
      "best_score": 980,
      "settings": {
        "difficulty": "normal",
        "sound_volume": 75,
        "music_volume": 60,
        "screen_shake": true,
        "auto_save": true
      },
      "achievements": [
        "first_win",
        "score_500"
      ]
    }
  },
  "active_profile": "PlayerName"
}

Integration with Games

Loading Active Profile

import json

def load_active_profile():
    try:
        with open('user_profiles.json', 'r') as f:
            data = json.load(f)
            active_name = data.get('active_profile')
            if active_name and active_name in data['profiles']:
                return data['profiles'][active_name]
    except (FileNotFoundError, json.JSONDecodeError):
        pass
    return None

# Usage in your game
profile = load_active_profile()
if profile:
    difficulty = profile['settings']['difficulty']
    sound_volume = profile['settings']['sound_volume']

Updating Profile Stats

def update_profile_stats(score, game_completed=True):
    try:
        with open('user_profiles.json', 'r') as f:
            data = json.load(f)
        
        active_name = data.get('active_profile')
        if active_name and active_name in data['profiles']:
            profile = data['profiles'][active_name]
            
            if game_completed:
                profile['games_played'] += 1
            profile['total_score'] += score
            profile['best_score'] = max(profile['best_score'], score)
            profile['last_played'] = datetime.now().isoformat()
            
            with open('user_profiles.json', 'w') as f:
                json.dump(data, f, indent=2)
    except Exception as e:
        print(f"Error updating profile: {e}")

Customization

Adding New Settings

Edit the UserProfile dataclass and the settings adjustment methods:

# In profile_manager.py, modify the UserProfile.__post_init__ method
def __post_init__(self):
    if self.settings is None:
        self.settings = {
            "difficulty": "normal",
            "sound_volume": 50,
            "music_volume": 50,
            "screen_shake": True,
            "auto_save": True,
            "your_new_setting": "default_value"  # Add here
        }

Custom Font

Place your font file in the assets/ directory and update the font path:

font_path = "assets/your_font.ttf"

Screen Resolution

The application is optimized for 640x480 resolution. To change resolution, modify the window size in the init_sdl method:

self.window = sdl2.ext.Window(
    title="Profile Manager",
    size=(your_width, your_height)  # Change from (640, 480)
)

Virtual Keyboard Layout

Customize the virtual keyboard characters by modifying the keyboard_chars list:

self.keyboard_chars = [
    ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'],
    ['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'],
    ['U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4'],
    ['5', '6', '7', '8', '9', '0', '_', '-', ' ', '<'],
    ['DONE', 'CANCEL', '', '', '', '', '', '', '', '']
]

Troubleshooting

No Gamepad Detected

  • Ensure your gamepad is connected before starting the application
  • Try different USB ports
  • Check if your gamepad is recognized by your system
  • The application will show "No gamepad detected - using keyboard fallback"
  • Virtual keyboard works with both gamepad and keyboard controls

Font Issues

  • Ensure the font file exists in the assets directory
  • The system will fall back to default font if custom font is not found
  • Supported font formats: TTF, OTF
  • Font sizes are automatically scaled for 640x480 resolution

Virtual Keyboard Not Responding

  • Ensure you're in text input mode (creating/editing profile names)
  • Use arrow keys or D-Pad to navigate the virtual keyboard cursor
  • Press Enter/A button to select characters
  • The virtual keyboard cursor should be visible as a highlighted character

Profile Not Saving

  • Check file permissions in the application directory
  • Ensure sufficient disk space
  • Verify JSON format is not corrupted

Resolution Issues

  • The application is designed for 640x480 resolution
  • On higher resolution displays, the window may appear small
  • This is intentional for compatibility with retro gaming systems
  • Content is optimized and readable at this resolution

File Structure

project_directory/
├── profile_manager.py          # Main application (640x480, virtual keyboard)
├── launch_profile_manager.sh   # Launcher script
├── user_profiles.json         # Profile data storage
├── test_profile_manager.py    # Test suite for core functions
├── game_profile_integration.py # Example game integration
├── assets/
│   └── decterm.ttf           # Font file (optional)
└── README_PROFILE_MANAGER.md # This documentation

Development Notes

Virtual Keyboard Implementation

The virtual keyboard is implemented as a 2D grid of characters:

  • Cursor position tracked with (keyboard_cursor_x, keyboard_cursor_y)
  • Character selection adds to input_text string
  • Special functions: DONE (confirm), CANCEL (abort), < (backspace)
  • Fully navigable with directional controls only

Screen Layout for 640x480

  • Header area: 0-80px (titles, status)
  • Content area: 80-400px (main UI elements)
  • Controls area: 400-480px (help text, instructions)
  • All elements scaled and positioned for optimal readability

Adding New Screens

  1. Add screen name to current_screen handling
  2. Create render method (e.g., render_new_screen())
  3. Add navigation logic in input handlers
  4. Update screen transitions in confirm/back handlers

Gamepad Button Mapping

The application uses SDL2's joystick interface. Button numbers may vary by controller:

  • Most modern controllers follow the Xbox layout
  • PlayStation controllers map similarly but may have different button numbers
  • Test with your specific controller and adjust mappings if needed

Performance Considerations

  • Rendering is capped at 60 FPS for smooth operation
  • Input debouncing prevents accidental rapid inputs
  • JSON operations are minimized and occur only when necessary
  • Virtual keyboard rendering optimized for 640x480 resolution
  • Font scaling automatically adjusted for readability

Adding Support for Different Resolutions

To support different screen resolutions, modify these key areas:

  1. Window initialization in init_sdl()
  2. Panel and button positioning in render methods
  3. Font size scaling factors
  4. Virtual keyboard grid positioning

Gamepad Integration Notes

  • Uses SDL2's joystick interface for maximum compatibility
  • Button mapping follows standard Xbox controller layout
  • Hat/D-Pad input prioritized over analog sticks for precision
  • Input timing designed for responsive but not accidental activation

Target Platforms

This profile manager is specifically designed for:

  • Handheld Gaming Devices: Steam Deck, ROG Ally, etc.
  • Retro Gaming Systems: RetroPie, Batocera, etc.
  • Embedded Gaming Systems: Custom arcade cabinets, portable devices
  • Low-Resolution Displays: 640x480, 800x600, and similar resolutions
  • Gamepad-Only Environments: Systems without keyboard access

License

This profile manager is provided as-is for educational and personal use. Designed for integration with retro and handheld gaming systems.