Stats tracking updated. Work on skull storms. Enemy death sound added for goblins. Various updates and fixes.
This commit is contained in:
		
							
								
								
									
										131
									
								
								wicked_quest.py
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								wicked_quest.py
									
									
									
									
									
								
							| @@ -9,22 +9,42 @@ from src.player import Player | ||||
|  | ||||
| class WickedQuest: | ||||
|     def __init__(self): | ||||
|         """Initialize game and load sounds.""" | ||||
|         self.sounds = initialize_gui("Wicked Quest") | ||||
|         self.currentLevel = None | ||||
|         self.lastThrowTime = 0 | ||||
|         self.throwDelay = 250 | ||||
|         self.player = None  # Will be initialized when first level loads | ||||
|          | ||||
|     def load_level(self, levelNumber): | ||||
|         """Load a level from its JSON file.""" | ||||
|         levelFile = f"levels/{levelNumber}.json" | ||||
|         try: | ||||
|             with open(levelFile, 'r') as f: | ||||
|                 levelData = json.load(f) | ||||
|             self.currentLevel = Level(levelData, self.sounds) | ||||
|             speak(f"Level {levelNumber} loaded") | ||||
|                  | ||||
|             # Create player if this is the first level | ||||
|             if self.player is None: | ||||
|                 self.player = Player(levelData["player_start"]["x"], levelData["player_start"]["y"], self.sounds) | ||||
|             else: | ||||
|                 # Just update player position for new level | ||||
|                 self.player.xPos = levelData["player_start"]["x"] | ||||
|                 self.player.yPos = levelData["player_start"]["y"] | ||||
|                  | ||||
|             # Pass existing player to new level | ||||
|             self.currentLevel = Level(levelData, self.sounds, self.player) | ||||
|          | ||||
|             # Announce level details | ||||
|             levelIntro = f"Level {levelData['level_id']}, {levelData['name']}. {levelData['description']}" | ||||
|             messagebox(levelIntro) | ||||
|          | ||||
|             return True | ||||
|         except FileNotFoundError: | ||||
|             speak("Level not found") | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|     def handle_input(self): | ||||
|         """Process keyboard input for player actions.""" | ||||
|         keys = pygame.key.get_pressed() | ||||
|         player = self.currentLevel.player | ||||
|         currentTime = pygame.time.get_ticks() | ||||
| @@ -45,17 +65,20 @@ class WickedQuest: | ||||
|             player.xPos += currentSpeed | ||||
|             player.facingRight = True | ||||
|          | ||||
|         # Status queries | ||||
|         if keys[pygame.K_c]: | ||||
|             speak(f"{player.get_coins()} coins") | ||||
|              | ||||
|         if keys[pygame.K_h]: | ||||
|             speak(f"{player.get_health()} HP") | ||||
|              | ||||
|         if keys[pygame.K_l]: | ||||
|             speak(f"{player.get_lives()} lives") | ||||
|              | ||||
|         if keys[pygame.K_f]:  # Throw projectile | ||||
|             self.currentLevel.throw_projectile() | ||||
|         if keys[pygame.K_j]:  # Check jack o'lanterns | ||||
|             speak(f"{player.get_jack_o_lanterns()} jack o'lanterns") | ||||
|         if keys[pygame.K_f]: | ||||
|             currentTime = pygame.time.get_ticks() | ||||
|             if currentTime - self.lastThrowTime >= self.throwDelay: | ||||
|                 self.currentLevel.throw_projectile() | ||||
|                 self.lastThrowTime = currentTime | ||||
|  | ||||
|         # Handle attack with either CTRL key | ||||
|         if (keys[pygame.K_LCTRL] or keys[pygame.K_RCTRL]) and player.start_attack(currentTime): | ||||
| @@ -81,45 +104,103 @@ class WickedQuest: | ||||
|             # Reset step distance tracking after landing | ||||
|             player.distanceSinceLastStep = 0 | ||||
|  | ||||
|     def display_level_stats(self, timeTaken): | ||||
|         """Display level completion statistics.""" | ||||
|         # Convert time from milliseconds to minutes:seconds | ||||
|         minutes = timeTaken // 60000 | ||||
|         seconds = (timeTaken % 60000) // 1000 | ||||
|      | ||||
|         # Update time in stats | ||||
|         self.currentLevel.player.stats.update_stat('Total time', timeTaken, levelOnly=True) | ||||
|  | ||||
|         report = [f"Level {self.currentLevel.levelId} Complete!"] | ||||
|         report.append(f"Time taken: {minutes} minutes and {seconds} seconds") | ||||
|      | ||||
|         # Add all level stats | ||||
|         for key in self.currentLevel.player.stats.level: | ||||
|             if key != 'Total time':  # Skip time since we already displayed it | ||||
|                 report.append(f"{key}: {self.currentLevel.player.stats.get_level_stat(key)}") | ||||
|  | ||||
|         pygame.mixer.stop() | ||||
|         display_text(report) | ||||
|         self.currentLevel.player.stats.reset_level() | ||||
|  | ||||
|     def display_game_over(self, timeTaken): | ||||
|         """Display game over screen with statistics.""" | ||||
|         minutes = timeTaken // 60000 | ||||
|         seconds = (timeTaken % 60000) // 1000 | ||||
|      | ||||
|         report = ["Game Over!"] | ||||
|         report.append(f"Time taken: {minutes} minutes and {seconds} seconds") | ||||
|      | ||||
|         # Add all total stats | ||||
|         for key in self.currentLevel.player.stats.total: | ||||
|             if key not in ['Total time', 'levelsCompleted']:  # Skip these | ||||
|                 report.append(f"Total {key}: {self.currentLevel.player.stats.get_total_stat(key)}") | ||||
|  | ||||
|         display_text(report) | ||||
|  | ||||
|     def game_loop(self): | ||||
|         """Main game loop handling updates and state changes.""" | ||||
|         clock = pygame.time.Clock() | ||||
|          | ||||
|         while self.currentLevel.player.get_health() > 0 and self.currentLevel.player.get_lives() > 0: | ||||
|         startTime = pygame.time.get_ticks() | ||||
|         currentLevelNum = 1 | ||||
|  | ||||
|         while True: | ||||
|             currentTime = pygame.time.get_ticks() | ||||
|              | ||||
|      | ||||
|             if check_for_exit(): | ||||
|                 return | ||||
|                  | ||||
|             # Update player state (including power-ups) | ||||
|          | ||||
|             # Update game state | ||||
|             self.currentLevel.player.update(currentTime) | ||||
|                  | ||||
|             self.handle_input() | ||||
|              | ||||
|             # Update audio positioning and handle collisions | ||||
|             self.currentLevel.update_audio() | ||||
|             self.currentLevel.handle_collisions() | ||||
|              | ||||
|             # Handle combat interactions | ||||
|      | ||||
|             # Handle combat and projectiles | ||||
|             self.currentLevel.handle_combat(currentTime) | ||||
|              | ||||
|             # Update projectiles | ||||
|             self.currentLevel.handle_projectiles(currentTime) | ||||
|              | ||||
|      | ||||
|             # Check for death first | ||||
|             if self.currentLevel.player.get_health() <= 0: | ||||
|                 if self.currentLevel.player.get_lives() <= 0: | ||||
|                     # Game over | ||||
|                     pygame.mixer.stop() | ||||
|                     self.display_game_over(pygame.time.get_ticks() - startTime) | ||||
|                     return | ||||
|  | ||||
|             # Handle collisions and check level completion | ||||
|             if self.currentLevel.handle_collisions():  # Changed from elif to if | ||||
|                 # Level completed | ||||
|                 self.display_level_stats(pygame.time.get_ticks() - startTime) | ||||
|          | ||||
|                 # Try to load next level | ||||
|                 currentLevelNum += 1 | ||||
|                 if self.load_level(currentLevelNum): | ||||
|                     # Reset timer for new level | ||||
|                     startTime = pygame.time.get_ticks() | ||||
|                     continue | ||||
|                 else: | ||||
|                     # No more levels - game complete! | ||||
|                     messagebox("Congratulations! You've completed all available levels!") | ||||
|                     self.display_game_over(pygame.time.get_ticks() - startTime) | ||||
|                     return | ||||
|      | ||||
|             clock.tick(60)  # 60 FPS | ||||
|              | ||||
|         # Player died or ran out of lives | ||||
|         speak("Game Over") | ||||
|  | ||||
|     def run(self): | ||||
|         """Main game loop with menu system.""" | ||||
|         while True: | ||||
|             choice = game_menu(self.sounds, "play", "instructions", "learn_sounds", "credits", "donate", "exit") | ||||
|              | ||||
|             if choice == "exit": | ||||
|                 exit_game() | ||||
|             elif choice == "play": | ||||
|                 self.player = None  # Reset player for new game | ||||
|                 if self.load_level(1): | ||||
|                     self.game_loop() | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     game = WickedQuest() | ||||
|     game.run() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user