diff --git a/src/game.py b/src/game.py index f044484..ca60d1c 100644 --- a/src/game.py +++ b/src/game.py @@ -62,10 +62,10 @@ class SettingsMenu: self.title_surface = self.title_font.render("Settings", True, (0, 255, 0)) self.title_rect = self.title_surface.get_rect(center=(width//2, height//4)) - # Initialize first item as hovered - if self.menu_items: - self.menu_items[0].hover = True - self.menu_items[0]._setup_font() + # Initialize first item as selected + self.selected_index = 0 + self.menu_items[0].hover = True + self.menu_items[0]._setup_font() def setup_menu_items(self): start_y = self.height // 2 @@ -85,15 +85,26 @@ class SettingsMenu: ] def update(self): + # Handle mouse hover mouse_pos = pygame.mouse.get_pos() - for item in self.menu_items: - item.update_hover(mouse_pos) + for i, item in enumerate(self.menu_items): + if item.rect.collidepoint(mouse_pos): + # Update selected index when mouse hovers + self.selected_index = i + item.hover = True + item._setup_font() + else: + # Keep keyboard selection visible + item.hover = (i == self.selected_index) + item._setup_font() def handle_input(self, event): if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: + # Handle mouse clicks mouse_pos = pygame.mouse.get_pos() - for item in self.menu_items: + for i, item in enumerate(self.menu_items): if item.rect.collidepoint(mouse_pos): + self.selected_index = i if item.action == 'toggle_wrap': self.rules.wrap_around = not self.rules.wrap_around item.text = f"Wrap Around: {'On' if self.rules.wrap_around else 'Off'}" @@ -104,42 +115,32 @@ class SettingsMenu: item._setup_font() elif item.action == 'back': return 'back' + elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: return 'back' elif event.key == pygame.K_RETURN: - for item in self.menu_items: - if item.hover: - if item.action == 'toggle_wrap': - self.rules.wrap_around = not self.rules.wrap_around - item.text = f"Wrap Around: {'On' if self.rules.wrap_around else 'Off'}" - item._setup_font() - elif item.action == 'toggle_speed': - self.rules.speed_increase = not self.rules.speed_increase - item.text = f"Speed Increase: {'On' if self.rules.speed_increase else 'Off'}" - item._setup_font() - elif item.action == 'back': - return 'back' + item = self.menu_items[self.selected_index] + if item.action == 'toggle_wrap': + self.rules.wrap_around = not self.rules.wrap_around + item.text = f"Wrap Around: {'On' if self.rules.wrap_around else 'Off'}" + item._setup_font() + elif item.action == 'toggle_speed': + self.rules.speed_increase = not self.rules.speed_increase + item.text = f"Speed Increase: {'On' if self.rules.speed_increase else 'Off'}" + item._setup_font() + elif item.action == 'back': + return 'back' elif event.key in (pygame.K_UP, pygame.K_DOWN): - # Find current hover index - current_hover = -1 - for i, item in enumerate(self.menu_items): - if item.hover: - current_hover = i - break - - # Move hover up or down - if current_hover == -1: - new_hover = 0 + # Update selected index + if event.key == pygame.K_UP: + self.selected_index = (self.selected_index - 1) % len(self.menu_items) else: - if event.key == pygame.K_UP: - new_hover = (current_hover - 1) % len(self.menu_items) - else: - new_hover = (current_hover + 1) % len(self.menu_items) + self.selected_index = (self.selected_index + 1) % len(self.menu_items) # Update hover states for i, item in enumerate(self.menu_items): - item.hover = (i == new_hover) + item.hover = (i == self.selected_index) item._setup_font() return None @@ -156,7 +157,7 @@ class SettingsMenu: item.draw(screen) # Draw controls - controls_text = "Arrow keys to navigate, Enter to select, Esc to go back" + controls_text = "Arrow keys or mouse to navigate, Enter to select, Esc to go back" font = pygame.font.Font(None, 24) controls_surface = font.render(controls_text, True, (100, 100, 100)) screen.blit(controls_surface, @@ -264,7 +265,11 @@ class Game: self.reset_game() def update(self): - if self.state == GameState.PLAYING: + if self.state == GameState.MENU: + self.menu.update() + elif self.state == GameState.SETTINGS: + self.settings_menu.update() + elif self.state == GameState.PLAYING: # Move snake if self.snake.move(pygame.time.get_ticks()): # Handle wrap-around diff --git a/src/menu.py b/src/menu.py index 54adce5..b5ef51f 100644 --- a/src/menu.py +++ b/src/menu.py @@ -22,22 +22,18 @@ class MenuItem: self._setup_font() def _setup_font(self): + """Update the font surface with current color""" self.font = pygame.font.Font(None, self.size) - self.surface = self.font.render(self.text, True, self.color) + color = (255, 255, 0) if self.hover else self.default_color # Yellow when hovered + self.surface = self.font.render(self.text, True, color) self.rect = self.surface.get_rect(center=self.position) def update_hover(self, mouse_pos): + """Update hover state based on mouse position""" old_hover = self.hover self.hover = self.rect.collidepoint(mouse_pos) - if self.hover: - self.color = (255, 255, 0) # Yellow on hover - else: - self.color = self.default_color if old_hover != self.hover: self._setup_font() - - def draw(self, screen): - screen.blit(self.surface, self.rect) class Menu: def __init__(self, width, height): @@ -54,10 +50,10 @@ class Menu: self.subtitle_surface = self.subtitle_font.render("Choose Game Mode", True, (200, 200, 200)) self.subtitle_rect = self.subtitle_surface.get_rect(center=(width//2, height//4 + 50)) - # Initialize first item as hovered - if self.menu_items: - self.menu_items[0].hover = True - self.menu_items[0]._setup_font() + # Initialize first item as selected + self.selected_index = 0 + self.menu_items[0].hover = True + self.menu_items[0]._setup_font() def setup_menu_items(self): # Calculate positions for menu items @@ -76,44 +72,45 @@ class Menu: def handle_input(self, event): if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: + # Handle mouse clicks mouse_pos = pygame.mouse.get_pos() - for item in self.menu_items: + for i, item in enumerate(self.menu_items): if item.rect.collidepoint(mouse_pos): + self.selected_index = i return item.action + elif event.type == pygame.KEYDOWN: if event.key == pygame.K_RETURN: - # Find the currently hovered item - for item in self.menu_items: - if item.hover: - return item.action + # Return the selected item's action + return self.menu_items[self.selected_index].action + elif event.key in (pygame.K_UP, pygame.K_DOWN): - # Find current hover index - current_hover = -1 - for i, item in enumerate(self.menu_items): - if item.hover: - current_hover = i - break - - # Move hover up or down - if current_hover == -1: - new_hover = 0 + # Update selected index + if event.key == pygame.K_UP: + self.selected_index = (self.selected_index - 1) % len(self.menu_items) else: - if event.key == pygame.K_UP: - new_hover = (current_hover - 1) % len(self.menu_items) - else: - new_hover = (current_hover + 1) % len(self.menu_items) + self.selected_index = (self.selected_index + 1) % len(self.menu_items) # Update hover states for i, item in enumerate(self.menu_items): - item.hover = (i == new_hover) + item.hover = (i == self.selected_index) item._setup_font() return None def update(self): + # Handle mouse hover mouse_pos = pygame.mouse.get_pos() - for item in self.menu_items: - item.update_hover(mouse_pos) + for i, item in enumerate(self.menu_items): + if item.rect.collidepoint(mouse_pos): + # Update selected index when mouse hovers + self.selected_index = i + item.hover = True + item._setup_font() + else: + # Keep keyboard selection visible + item.hover = (i == self.selected_index) + item._setup_font() def draw(self, screen): # Draw background @@ -129,7 +126,7 @@ class Menu: # Draw version and controls version_text = "v0.1.0" - controls_text = "Arrow keys to navigate, Enter to select" + controls_text = "Arrow keys or mouse to navigate, Enter to select" font = pygame.font.Font(None, 24) version_surface = font.render(version_text, True, (100, 100, 100))