From 442b376c6688e2a564e6ddc549da192406fe09f4 Mon Sep 17 00:00:00 2001 From: Zoltan Szabatin Date: Tue, 25 Feb 2025 15:46:11 -0800 Subject: feat: Add Pygame menu --- justfile | 4 +++ pyproject.toml | 4 ++- requirements-dev.lock | 2 ++ requirements.lock | 2 ++ shell.nix | 11 +++++++ src/splitscreen_duo/__init__.py | 15 ++++++++++ src/splitscreen_duo/input.py | 51 ++++++++++++++++++++++++++++++++ src/splitscreen_duo/menu.py | 64 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 shell.nix create mode 100644 src/splitscreen_duo/input.py create mode 100644 src/splitscreen_duo/menu.py diff --git a/justfile b/justfile index 37de4aa..621ae68 100644 --- a/justfile +++ b/justfile @@ -6,3 +6,7 @@ create_serial_port: kill_serial_port: pkill socat + +run: + DEVELOPMENT=1 INSTANCE=primary rye run splitscreen_duo & + DEVELOPMENT=1 INSTANCE=secondary rye run splitscreen_duo & diff --git a/pyproject.toml b/pyproject.toml index 1528345..f074f88 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,9 @@ authors = [ { name = "Musa Ahmed", email = "musa.ahmed@oit.edu" }, { name = "Zoltan Szabatin", email = "zoltan.szabatin@oit.edu" }, ] -dependencies = [] +dependencies = [ + "pygame>=2.6.1", +] readme = "README.md" requires-python = ">= 3.8" diff --git a/requirements-dev.lock b/requirements-dev.lock index 505fd45..5a0b09c 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -10,3 +10,5 @@ # universal: false -e file:. +pygame==2.6.1 + # via splitscreen-duo diff --git a/requirements.lock b/requirements.lock index 505fd45..5a0b09c 100644 --- a/requirements.lock +++ b/requirements.lock @@ -10,3 +10,5 @@ # universal: false -e file:. +pygame==2.6.1 + # via splitscreen-duo diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..df382b0 --- /dev/null +++ b/shell.nix @@ -0,0 +1,11 @@ +{ + pkgs ? import { }, +}: +pkgs.mkShell { + buildInputs = with pkgs; [ + (python312.withPackages (ps: with ps; [ pygame ])) + rye + just + black + ]; +} diff --git a/src/splitscreen_duo/__init__.py b/src/splitscreen_duo/__init__.py index eea3683..4be2b6f 100644 --- a/src/splitscreen_duo/__init__.py +++ b/src/splitscreen_duo/__init__.py @@ -1,4 +1,19 @@ +from . import menu +import os +import logging + + +logger = logging.getLogger(__name__) + + def main() -> int: + logging.basicConfig( + level=( + logging.DEBUG if os.environ.get("DEVELOPMENT", "").lower() else logging.INFO + ) + ) print("The Dual Screen Console") + logger.info(f"Running as {os.environ.get("INSTANCE", "unknown")}") + menu.main_loop() return 0 diff --git a/src/splitscreen_duo/input.py b/src/splitscreen_duo/input.py new file mode 100644 index 0000000..1a1e5d0 --- /dev/null +++ b/src/splitscreen_duo/input.py @@ -0,0 +1,51 @@ +import pygame + + +class Input: + def __init__(self, debug=True): + self.debug = debug + self.controller = None + + if not self.debug: + pygame.joystick.init() + + if pygame.joystick.get_count() > 0: + self.controller = pygame.joystick.Joystick(0) + self.controller.init() + + def get_input(self, event): + if self.debug: + return self.get_keyboard_input(event) + else: + return self.get_controller_input(event) + + def get_keyboard_input(self, event): + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_UP: + return "UP" + if event.key == pygame.K_DOWN: + return "DOWN" + if event.key == pygame.K_RETURN: + return "SELECT" + if event.key == pygame.K_ESCAPE: + return "QUIT" + + return None + + def get_controller_input(self, event): + if not self.controller: + return None + + if event.type == pygame.JOYAXISMOTION: + if event.axis == 1: # Y-axis + if event.value < -0.5: # Joystick up + return "UP" + if event.value > 0.5: # Joystick down + return "DOWN" + elif event.type == pygame.JOYBUTTONDOWN: + if event.button == 0: # Button A or select + return "SELECT" + if event.button == 1: # Button B + return "QUIT" + + return None diff --git a/src/splitscreen_duo/menu.py b/src/splitscreen_duo/menu.py new file mode 100644 index 0000000..489a75c --- /dev/null +++ b/src/splitscreen_duo/menu.py @@ -0,0 +1,64 @@ +import sys +import pygame +import os +from .input import Input + +pygame.init() +pygame.display.set_caption("SplitScreen Duo Menu") + +WIDTH, HEIGHT = ( + pygame.display.Info().current_w // 2, + pygame.display.Info().current_h // 2, +) +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +FONT = pygame.font.Font(None, 36) +IS_DEVELOPMENT_MODE = os.environ.get("DEVELOPMENT", "").lower() +OPTIONS = ["Breakout", "Pong v.s. Computer", "Snake", "Quit"] +selected_index = 0 +screen = pygame.display.set_mode( + (WIDTH, HEIGHT) if IS_DEVELOPMENT_MODE else (0, 0), + 0 if IS_DEVELOPMENT_MODE else pygame.FULLSCREEN, +) + + +def draw_menu(): + screen.fill(WHITE) + + for i, option in enumerate(OPTIONS): + text = FONT.render(option, True, BLACK if i != selected_index else (200, 0, 0)) + + screen.blit(text, (WIDTH // 2 - text.get_width() // 2, 150 + i * 50)) + + pygame.display.flip() + + +def main_loop(): + global selected_index + + is_running = True + input_handler = Input(debug=IS_DEVELOPMENT_MODE) + + while is_running: + draw_menu() + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + + action = input_handler.get_input(event) + + if action == "UP": + selected_index = (selected_index - 1) % len(OPTIONS) + elif action == "DOWN": + selected_index = (selected_index + 1) % len(OPTIONS) + elif action == "SELECT": + if OPTIONS[selected_index] == "Quit": + pygame.quit() + sys.exit() + else: + print(OPTIONS[selected_index]) + elif action == "QUIT": + pygame.quit() + sys.exit() -- cgit v1.2.3