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.
168 lines
5.1 KiB
168 lines
5.1 KiB
#!/usr/bin/env python3 |
|
""" |
|
User Profile Manager for Games |
|
A PySDL2-based profile management system with gamepad-only controls |
|
Refactored with separated UI and business logic components |
|
|
|
Features: |
|
- Create new user profiles |
|
- Edit existing profiles |
|
- Delete profiles |
|
- Select active profile |
|
- JSON-based storage |
|
- Gamepad navigation only |
|
- Modular UI components |
|
""" |
|
|
|
import time |
|
from typing import Dict, Optional |
|
|
|
import sdl2 |
|
import sdl2.ext |
|
|
|
# Import separated components |
|
from ui_components import UIRenderer, GamepadInputHandler |
|
from profile_data import ProfileDataManager, SettingsManager |
|
from screens import ModularScreenManager |
|
|
|
|
|
class ProfileManager: |
|
"""Main profile management system with separated UI and business logic""" |
|
|
|
def __init__(self, profiles_file: str = "user_profiles.json"): |
|
# Business logic components |
|
self.data_manager = ProfileDataManager(profiles_file) |
|
|
|
# Input handling |
|
self.input_handler = GamepadInputHandler() |
|
|
|
# SDL2 components |
|
self.window = None |
|
self.renderer = None |
|
self.ui_renderer = None |
|
self.running = True |
|
|
|
# NEW: Modular screen manager (will be initialized after SDL setup) |
|
self.screen_manager = None |
|
|
|
def init_sdl(self): |
|
"""Initialize SDL2 components""" |
|
sdl2.ext.init(joystick=True) |
|
|
|
# Create window |
|
self.window = sdl2.ext.Window( |
|
title="Profile Manager", |
|
size=(640, 480) |
|
) |
|
self.window.show() |
|
|
|
# Create renderer |
|
self.renderer = sdl2.ext.Renderer( |
|
self.window, |
|
flags=sdl2.SDL_RENDERER_ACCELERATED | sdl2.SDL_RENDERER_PRESENTVSYNC |
|
) |
|
|
|
# Initialize UI renderer |
|
self.ui_renderer = UIRenderer(self.renderer, (640, 480)) |
|
|
|
# NEW: Initialize modular screen manager |
|
self.screen_manager = ModularScreenManager(self.data_manager, self.ui_renderer) |
|
|
|
def handle_input(self): |
|
"""Handle all input (simplified with screen delegation)""" |
|
# Handle SDL events for keyboard |
|
events = sdl2.ext.get_events() |
|
for event in events: |
|
if event.type == sdl2.SDL_QUIT: |
|
self.running = False |
|
elif event.type == sdl2.SDL_KEYDOWN: |
|
action = self._keyboard_to_action(event.key.keysym.sym) |
|
if action: |
|
result = self.screen_manager.handle_input(action) |
|
if not result: |
|
self.running = False |
|
|
|
# Handle gamepad input |
|
gamepad_input = self.input_handler.get_gamepad_input() |
|
for action, pressed in gamepad_input.items(): |
|
if pressed: |
|
gamepad_action = self._gamepad_to_action(action) |
|
if gamepad_action: |
|
result = self.screen_manager.handle_input(gamepad_action) |
|
if not result: |
|
self.running = False |
|
|
|
def _keyboard_to_action(self, key) -> str: |
|
"""Convert keyboard input to action""" |
|
key_map = { |
|
sdl2.SDLK_UP: 'up', |
|
sdl2.SDLK_DOWN: 'down', |
|
sdl2.SDLK_LEFT: 'left', |
|
sdl2.SDLK_RIGHT: 'right', |
|
sdl2.SDLK_RETURN: 'confirm', |
|
sdl2.SDLK_SPACE: 'confirm', |
|
sdl2.SDLK_ESCAPE: 'back', |
|
sdl2.SDLK_DELETE: 'delete', |
|
sdl2.SDLK_BACKSPACE: 'delete' |
|
} |
|
return key_map.get(key, '') |
|
|
|
def _gamepad_to_action(self, gamepad_action: str) -> str: |
|
"""Convert gamepad input to action""" |
|
gamepad_map = { |
|
'up': 'up', |
|
'down': 'down', |
|
'left': 'left', |
|
'right': 'right', |
|
'button_3': 'confirm', # A/X button |
|
'button_4': 'back', # B/Circle button |
|
'button_9': 'delete' # X/Square button |
|
} |
|
return gamepad_map.get(gamepad_action, '') |
|
|
|
def render(self): |
|
"""Simplified rendering (delegated to screen manager)""" |
|
# Clear and draw background |
|
self.ui_renderer.clear_screen('black') |
|
self.ui_renderer.draw_background_pattern('gradient') |
|
|
|
# Delegate all screen rendering to screen manager |
|
self.screen_manager.render() |
|
|
|
self.ui_renderer.present() |
|
|
|
def run(self): |
|
"""Main application loop (unchanged)""" |
|
self.init_sdl() |
|
|
|
target_fps = 30 |
|
frame_time = 1000 // target_fps |
|
|
|
while self.running: |
|
frame_start = sdl2.SDL_GetTicks() |
|
|
|
# Handle input |
|
self.handle_input() |
|
|
|
# Render |
|
self.render() |
|
|
|
# Frame timing |
|
frame_elapsed = sdl2.SDL_GetTicks() - frame_start |
|
if frame_elapsed < frame_time: |
|
sdl2.SDL_Delay(frame_time - frame_elapsed) |
|
|
|
# Cleanup |
|
self.input_handler.cleanup() |
|
sdl2.ext.quit() |
|
|
|
|
|
# Entry point |
|
def main(): |
|
"""Main entry point""" |
|
manager = ProfileManager() |
|
manager.run() |
|
|
|
|
|
if __name__ == "__main__": |
|
main()
|
|
|