Code cleanup, added more functionality. Floating coffins that spawn items, graves can spawn zombies, etc.
This commit is contained in:
		
							
								
								
									
										92
									
								
								src/level.py
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								src/level.py
									
									
									
									
									
								
							| @@ -1,14 +1,20 @@ | ||||
| import pygame | ||||
| import random | ||||
| from libstormgames import * | ||||
| from src.enemy import Enemy | ||||
| from src.object import Object | ||||
| from src.player import Player | ||||
| from src.projectile import Projectile | ||||
| from src.coffin import CoffinObject | ||||
| from src.powerup import PowerUp | ||||
|  | ||||
| class Level: | ||||
|     def __init__(self, levelData, sounds): | ||||
|         self.sounds = sounds | ||||
|         self.objects = [] | ||||
|         self.enemies = [] | ||||
|         self.bouncing_items = [] | ||||
|         self.projectiles = []  # Track active projectiles | ||||
|         self.player = Player(levelData["player_start"]["x"], levelData["player_start"]["y"]) | ||||
|          | ||||
|         # Load objects and enemies from level data | ||||
| @@ -39,18 +45,45 @@ class Level: | ||||
|                     obj["sound"], | ||||
|                     isStatic=obj.get("static", True), | ||||
|                     isCollectible=obj.get("collectible", False), | ||||
|                     isHazard=obj.get("hazard", False) | ||||
|                     isHazard=obj.get("hazard", False), | ||||
|                     zombie_spawn_chance=obj.get("zombie_spawn_chance", 0) | ||||
|                 ) | ||||
|                 self.objects.append(gameObject) | ||||
|  | ||||
|     def update_audio(self): | ||||
|         currentTime = pygame.time.get_ticks() | ||||
|          | ||||
|         # Update regular objects | ||||
|         # Update regular objects and check for zombie spawning | ||||
|         for obj in self.objects: | ||||
|             if not obj.isActive: | ||||
|                 continue | ||||
|                  | ||||
|             # Check for potential zombie spawn from graves | ||||
|             if (obj.soundName == "grave" and  | ||||
|                 obj.zombie_spawn_chance > 0 and  | ||||
|                 not obj.has_spawned): | ||||
|                  | ||||
|                 distance = abs(self.player.xPos - obj.xPos) | ||||
|                 if distance < 6:  # Within 6 tiles | ||||
|                     # Mark as checked before doing anything else to prevent multiple checks | ||||
|                     obj.has_spawned = True | ||||
|                      | ||||
|                     roll = random.randint(1, 100) | ||||
|                     speak(f"Near grave, chance to spawn zombie") | ||||
|                     if roll <= obj.zombie_spawn_chance: | ||||
|                         zombie = Enemy( | ||||
|                             [obj.xPos, obj.xPos], | ||||
|                             obj.yPos, | ||||
|                             "zombie", | ||||
|                             self.sounds, | ||||
|                             health=3, | ||||
|                             damage=10, | ||||
|                             attack_range=1 | ||||
|                         ) | ||||
|                         self.enemies.append(zombie) | ||||
|                         speak("A zombie emerges from the grave!") | ||||
|              | ||||
|             # Handle object audio | ||||
|             if not obj.isStatic: | ||||
|                 if obj.channel is None or not obj.channel.get_busy(): | ||||
|                     obj.channel = obj_play(self.sounds, obj.soundName, self.player.xPos, obj.xPos) | ||||
| @@ -72,15 +105,43 @@ class Level: | ||||
|                 enemy.channel = obj_play(self.sounds, enemy.enemyType, self.player.xPos, enemy.xPos) | ||||
|             if enemy.channel is not None: | ||||
|                 enemy.channel = obj_update(enemy.channel, self.player.xPos, enemy.xPos) | ||||
|                  | ||||
|         # Update bouncing items | ||||
|         for item in self.bouncing_items[:]:  # Copy list to allow removal | ||||
|             if not item.update(currentTime): | ||||
|                 self.bouncing_items.remove(item) | ||||
|                 if not item.isActive: | ||||
|                     speak(f"{item.soundName} got away!") | ||||
|                 continue | ||||
|                  | ||||
|             # Check for item collection | ||||
|             if abs(item.xPos - self.player.xPos) < 1 and self.player.isJumping: | ||||
|                 self.sounds[f'get_{item.soundName}'].play() | ||||
|                 item.apply_effect(self.player) | ||||
|                 item.isActive = False | ||||
|                 self.bouncing_items.remove(item) | ||||
|  | ||||
|     def handle_combat(self, currentTime): | ||||
|         """Handle combat interactions between player and enemies""" | ||||
|         attackRange = self.player.get_attack_range(currentTime) | ||||
|         if attackRange: | ||||
|             # Check for enemy hits | ||||
|             for enemy in self.enemies: | ||||
|                 if enemy.isActive and enemy.xPos >= attackRange[0] and enemy.xPos <= attackRange[1]: | ||||
|                     self.sounds[self.player.currentWeapon.hitSound].play() | ||||
|                     enemy.take_damage(self.player.currentWeapon.damage) | ||||
|                      | ||||
|             # Check for coffin hits - only if we have any coffins | ||||
|             for obj in self.objects: | ||||
|                 if hasattr(obj, 'is_broken'):  # Check if it's a coffin without using isinstance | ||||
|                     if (not obj.is_broken and  | ||||
|                         obj.xPos >= attackRange[0] and  | ||||
|                         obj.xPos <= attackRange[1] and | ||||
|                         self.player.isJumping):  # Must be jumping to hit floating coffins | ||||
|                      | ||||
|                         if obj.hit(self.player.xPos): | ||||
|                                 self.bouncing_items.append(obj.dropped_item) | ||||
|                                 speak(f"{obj.dropped_item.item_type} falls out!") | ||||
|  | ||||
|     def handle_collisions(self): | ||||
|         for obj in self.objects: | ||||
| @@ -99,3 +160,30 @@ class Level: | ||||
|                     self.sounds[obj.soundName].play() | ||||
|                     speak("You fell in an open grave!") | ||||
|                     self.player.set_health(0) | ||||
|                      | ||||
|     def handle_projectiles(self, currentTime): | ||||
|         """Update projectiles and check for collisions""" | ||||
|         for proj in self.projectiles[:]:  # Copy list to allow removal | ||||
|             if not proj.update(): | ||||
|                 self.projectiles.remove(proj) | ||||
|                 continue | ||||
|                  | ||||
|             # Check for enemy hits | ||||
|             for enemy in self.enemies: | ||||
|                 if enemy.isActive and abs(proj.x - enemy.xPos) < 1: | ||||
|                     proj.hit_enemy(enemy) | ||||
|                     self.projectiles.remove(proj) | ||||
|                     break | ||||
|                      | ||||
|     def throw_projectile(self): | ||||
|         """Have player throw a projectile""" | ||||
|         proj_info = self.player.throw_projectile() | ||||
|         if proj_info: | ||||
|             self.projectiles.append(Projectile( | ||||
|                 proj_info['type'], | ||||
|                 proj_info['start_x'], | ||||
|                 proj_info['direction'] | ||||
|             )) | ||||
|             # Play throw sound | ||||
|             if f"{proj_info['type']}_throw" in self.sounds: | ||||
|                 self.sounds[f"{proj_info['type']}_throw"].play() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user