More content added, weapons, coin collecting, basic combat.
This commit is contained in:
		
							
								
								
									
										109
									
								
								src/level.py
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								src/level.py
									
									
									
									
									
								
							| @@ -1,76 +1,101 @@ | ||||
| import pygame | ||||
| from libstormgames import * | ||||
| from src.player import Player | ||||
| from src.enemy import Enemy | ||||
| from src.object import Object | ||||
| from src.player import Player | ||||
|  | ||||
| class Level: | ||||
|     def __init__(self, levelData, sounds): | ||||
|         self.sounds = sounds | ||||
|         self.objects = [] | ||||
|         self.enemies = [] | ||||
|         self.player = Player(levelData["player_start"]["x"], levelData["player_start"]["y"]) | ||||
|          | ||||
|         # Load objects from level data | ||||
|         # Load objects and enemies from level data | ||||
|         for obj in levelData["objects"]: | ||||
|             gameObject = Object( | ||||
|                 obj["x"], | ||||
|                 obj["y"], | ||||
|                 obj["sound"], | ||||
|                 isStatic=obj.get("static", True), | ||||
|                 isCollectible=obj.get("collectible", False), | ||||
|                 isHazard=obj.get("hazard", False) | ||||
|             ) | ||||
|             self.objects.append(gameObject) | ||||
|             # Handle x position or range | ||||
|             if "x_range" in obj: | ||||
|                 xPos = obj["x_range"] | ||||
|             else: | ||||
|                 xPos = [obj["x"], obj["x"]]  # Single position as range | ||||
|                  | ||||
|             # Check if this is an enemy | ||||
|             if "enemy_type" in obj: | ||||
|                 enemy = Enemy( | ||||
|                     xPos, | ||||
|                     obj["y"], | ||||
|                     obj["enemy_type"], | ||||
|                     self.sounds, | ||||
|                     health=obj.get("health", 5), | ||||
|                     damage=obj.get("damage", 1), | ||||
|                     attack_range=obj.get("attack_range", 1), | ||||
|                     movement_range=obj.get("movement_range", 5) | ||||
|                 ) | ||||
|                 self.enemies.append(enemy) | ||||
|             else: | ||||
|                 gameObject = Object( | ||||
|                     xPos, | ||||
|                     obj["y"], | ||||
|                     obj["sound"], | ||||
|                     isStatic=obj.get("static", True), | ||||
|                     isCollectible=obj.get("collectible", False), | ||||
|                     isHazard=obj.get("hazard", False) | ||||
|                 ) | ||||
|                 self.objects.append(gameObject) | ||||
|  | ||||
|     def update_audio(self): | ||||
|         # Update all object sounds based on player position | ||||
|         currentTime = pygame.time.get_ticks() | ||||
|          | ||||
|         # Update regular objects | ||||
|         for obj in self.objects: | ||||
|             if not obj.isActive: | ||||
|                 continue | ||||
|                  | ||||
|             # For non-static objects like goblins, ensure continuous sound | ||||
|             if not obj.isStatic: | ||||
|                 # If channel doesn't exist or sound stopped playing, restart it | ||||
|                 if obj.channel is None or not obj.channel.get_busy(): | ||||
|                     obj.channel = obj_play(self.sounds, obj.soundName, self.player.xPos, obj.xPos) | ||||
|             else: | ||||
|                 # Original logic for static objects | ||||
|                 if obj.channel is None: | ||||
|                     obj.channel = obj_play(self.sounds, obj.soundName, self.player.xPos, obj.xPos) | ||||
|                      | ||||
|             # Update position-based audio for all objects | ||||
|             if obj.channel is not None: | ||||
|                 obj.channel = obj_update(obj.channel, self.player.xPos, obj.xPos) | ||||
|                  | ||||
|         # Update enemies | ||||
|         for enemy in self.enemies: | ||||
|             if not enemy.isActive: | ||||
|                 continue | ||||
|                  | ||||
|             enemy.update(currentTime, self.player) | ||||
|              | ||||
|             if enemy.channel is None or not enemy.channel.get_busy(): | ||||
|                 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) | ||||
|  | ||||
|     def handle_combat(self, currentTime): | ||||
|         """Handle combat interactions between player and enemies""" | ||||
|         attackRange = self.player.get_attack_range(currentTime) | ||||
|         if attackRange: | ||||
|             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) | ||||
|  | ||||
|     def handle_collisions(self): | ||||
|         for obj in self.objects: | ||||
|             if not obj.isActive: | ||||
|                 continue | ||||
|              | ||||
|             # Single-tile collision detection (more precise) | ||||
|             collision_threshold = 0.5  # Half a tile width from center | ||||
|             distance = abs(self.player.xPos - obj.xPos) | ||||
|          | ||||
|             if distance <= collision_threshold: | ||||
|                 if obj.isCollectible: | ||||
|                     # Coins must be collected while jumping | ||||
|                     if self.player.isJumping: | ||||
|             if obj.is_in_range(self.player.xPos): | ||||
|                 if obj.isCollectible and self.player.isJumping: | ||||
|                     currentPos = round(self.player.xPos) | ||||
|                     if currentPos not in obj.collectedPositions: | ||||
|                         self.sounds[f'get_{obj.soundName}'].play() | ||||
|                         speak(f"Collected {obj.soundName}") | ||||
|                         obj.isActive = False | ||||
|                         obj_stop(obj.channel) | ||||
|                         obj.collect_at_position(currentPos) | ||||
|                         self.player.collectedItems.append(obj.soundName) | ||||
|                 elif obj.isHazard: | ||||
|                     # Only affect player if they're not jumping (for ground-based hazards) | ||||
|                     if not self.player.isJumping: | ||||
|                         if obj.soundName == "grave": | ||||
|                             self.sounds['grave'].play() | ||||
|                             speak("You fell into a pit!") | ||||
|                         elif obj.soundName == "goblin": | ||||
|                             self.sounds['goblin'].play() | ||||
|                             speak("A goblin got you!") | ||||
|                         else:  # Other hazards | ||||
|                             self.sounds[obj.soundName].play() | ||||
|                             speak(f"A {obj.soundName} got you!") | ||||
|                          | ||||
|                         # Apply knockback for any hazard hit | ||||
|                         knockback = 2 | ||||
|                         self.player.xPos = self.player.xPos - knockback if self.player.facingRight else self.player.xPos + knockback | ||||
|                 elif obj.isHazard and not self.player.isJumping: | ||||
|                     self.sounds[obj.soundName].play() | ||||
|                     speak("You fell in an open grave!") | ||||
|                     self.player.set_health(0) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user