Fix menu navigation: - Add proper item highlighting - Improve keyboard and mouse controls - Fix settings menu interaction - Update menu items continuously
This commit is contained in:
parent
be7b7caf28
commit
d1fb3a58b4
77
src/game.py
77
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
|
||||
|
67
src/menu.py
67
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))
|
||||
|
Loading…
Reference in New Issue
Block a user