Updates to libstormgames submodule. Updated the game to use the menu improvements. Started work on survival mode.

This commit is contained in:
Storm Dragon
2025-09-07 03:13:25 -04:00
parent 76a49baa15
commit ce353d0ed9
6 changed files with 399 additions and 119 deletions

View File

@@ -10,6 +10,7 @@ from src.object import Object
from src.player import Player
from src.game_selection import select_game, get_level_path
from src.save_manager import SaveManager
from src.survival_generator import SurvivalGenerator
class WickedQuest:
@@ -24,6 +25,9 @@ class WickedQuest:
self.currentGame = None
self.runLock = False # Toggle behavior of the run keys
self.saveManager = SaveManager()
self.survivalGenerator = None
self.survivalWave = 1
self.survivalScore = 0
def load_level(self, levelNumber):
"""Load a level from its JSON file."""
@@ -87,7 +91,7 @@ class WickedQuest:
return errors
def load_game_menu(self):
"""Display load game menu with available saves"""
"""Display load game menu with available saves using instruction_menu"""
save_files = self.saveManager.get_save_files()
if not save_files:
@@ -101,45 +105,17 @@ class WickedQuest:
options.append("Cancel")
# Show menu
currentIndex = 0
lastSpoken = -1
# Use instruction_menu for consistent behavior
choice = instruction_menu(self.sounds, "Select a save file to load:", *options)
messagebox("Select a save file to load:")
while True:
if currentIndex != lastSpoken:
speak(options[currentIndex])
lastSpoken = currentIndex
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
return None
elif event.key in [pygame.K_DOWN, pygame.K_s] and currentIndex < len(options) - 1:
currentIndex += 1
try:
self.sounds['menu-move'].play()
except:
pass
elif event.key in [pygame.K_UP, pygame.K_w] and currentIndex > 0:
currentIndex -= 1
try:
self.sounds['menu-move'].play()
except:
pass
elif event.key == pygame.K_RETURN:
try:
self.sounds['menu-select'].play()
except:
pass
if currentIndex == len(options) - 1: # Cancel
return None
else:
return save_files[currentIndex]
pygame.event.clear()
if choice == "Cancel" or choice is None:
return None
else:
# Find the corresponding save file
for save_file in save_files:
if save_file['display_name'] == choice:
return save_file
return None
def auto_save(self):
"""Automatically save the game if player has enough bone dust"""
@@ -448,10 +424,15 @@ class WickedQuest:
display_text(errorLines)
continue
if self.currentGame:
self.player = None # Reset player for new game
self.gameStartTime = pygame.time.get_ticks()
if self.load_level(1):
self.game_loop()
# Ask player to choose game mode
mode_choice = game_mode_menu(self.sounds)
if mode_choice == "campaign":
self.player = None # Reset player for new game
self.gameStartTime = pygame.time.get_ticks()
if self.load_level(1):
self.game_loop()
elif mode_choice == "survival":
self.start_survival_mode()
elif choice == "high_scores":
board = Scoreboard()
scores = board.get_high_scores()
@@ -465,6 +446,119 @@ class WickedQuest:
elif choice == "learn_sounds":
choice = learn_sounds(self.sounds)
def start_survival_mode(self):
"""Initialize and start survival mode."""
self.survivalGenerator = SurvivalGenerator(self.currentGame)
self.survivalWave = 1
self.survivalScore = 0
self.player = Player(0, 0, self.sounds)
self.gameStartTime = pygame.time.get_ticks()
# Generate first survival segment
levelData = self.survivalGenerator.generate_survival_level(self.survivalWave, 300)
self.currentLevel = Level(levelData, self.sounds, self.player)
messagebox(f"Survival Mode - Wave {self.survivalWave}! Survive as long as you can!")
self.survival_loop()
def survival_loop(self):
"""Main survival mode game loop with endless level generation."""
clock = pygame.time.Clock()
while True:
currentTime = pygame.time.get_ticks()
pygame.event.pump()
# Handle events
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
messagebox(f"Survival ended! Final score: {self.survivalScore}")
return
elif event.key in [pygame.K_CAPSLOCK, pygame.K_TAB]:
self.runLock = not self.runLock
speak("Run lock " + ("enabled." if self.runLock else "disabled."))
elif event.key == pygame.K_BACKSPACE:
pause_game()
elif event.type == pygame.QUIT:
exit_game()
# Update game state (following main game_loop pattern)
self.currentLevel.player.update(currentTime)
self.handle_input()
self.currentLevel.update_audio()
# Handle combat and projectiles
self.currentLevel.handle_combat(currentTime)
self.currentLevel.handle_projectiles(currentTime)
# Handle collisions (including collecting items)
self.currentLevel.handle_collisions()
# Check if player reached end of segment - generate new one
if self.player.xPos >= self.currentLevel.rightBoundary - 20:
self.advance_survival_wave()
# Check for death first (following main game loop pattern)
if self.currentLevel.player.get_health() <= 0:
if self.currentLevel.player.get_lives() <= 0:
# Game over - stop all sounds
pygame.mixer.stop()
messagebox(f"Game Over! Final wave: {self.survivalWave}, Final score: {self.survivalScore}")
return
else:
# Player died but has lives left - respawn
pygame.mixer.stop()
self.currentLevel.player._health = self.currentLevel.player._maxHealth
# Reset player position to beginning of current segment
self.player.xPos = 10
# Update score based on survival time
self.survivalScore += 1
clock.tick(60) # 60 FPS
def advance_survival_wave(self):
"""Generate next wave/segment for survival mode."""
self.survivalWave += 1
# Clear any lingering projectiles/sounds from previous wave
if hasattr(self, 'currentLevel') and self.currentLevel:
self.currentLevel.projectiles.clear()
pygame.mixer.stop() # Stop any ongoing catapult/enemy sounds
# Generate new segment
segmentLength = min(500, 300 + (self.survivalWave * 20)) # Longer segments over time
levelData = self.survivalGenerator.generate_survival_level(self.survivalWave, segmentLength)
# Preserve player position but shift to start of new segment
playerX = 10
self.player.xPos = playerX
# Create new level
self.currentLevel = Level(levelData, self.sounds, self.player)
speak(f"Wave {self.survivalWave}! Difficulty increased!")
def game_mode_menu(sounds):
"""Display game mode selection menu using instruction_menu.
Args:
sounds (dict): Dictionary of loaded sound effects
Returns:
str: Selected game mode or None if cancelled
"""
choice = instruction_menu(sounds, "Select game mode:", "Campaign", "Survival Mode")
if choice == "Campaign":
return "campaign"
elif choice == "Survival Mode":
return "survival"
else:
return None
if __name__ == "__main__":
game = WickedQuest()