Extra life added, fixed sounds to use the new functions for volume control Other various improvements.
This commit is contained in:
		 Submodule libstormgames updated: 80fe2caff3...68e72f5d81
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/extra_life.ogg
									 (Stored with Git LFS)
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/extra_life.ogg
									 (Stored with Git LFS)
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -37,9 +37,7 @@ class Pumpkin: | ||||
|             # Calculate volume and pan for splat sound based on final position | ||||
|             volume, left, right = calculate_volume_and_pan(playerX, self.x) | ||||
|             if volume > 0:  # Only play if within audible range | ||||
|                 channel = sounds["pumpkin_splat"].play() | ||||
|                 if channel: | ||||
|                     channel.set_volume(volume * left, volume * right) | ||||
|                 obj_play(sounds, 'pumpkin_splat', playerX, self.x, loop=False) | ||||
|  | ||||
|     def check_collision(self, player): | ||||
|         """Check if pumpkin hits player""" | ||||
| @@ -78,7 +76,7 @@ class Catapult(Object): | ||||
|         self.lastFireTime = currentTime | ||||
|          | ||||
|         # Play launch sound | ||||
|         self.sounds['catapult_launch'].play() | ||||
|         play_sound(self.sounds['catapult_launch']) | ||||
|          | ||||
|         # Set up pending pumpkin | ||||
|         isHigh = random.choice([True, False]) | ||||
|   | ||||
| @@ -21,7 +21,7 @@ class CoffinObject(Object): | ||||
|         """Handle being hit by the player's weapon""" | ||||
|         if not self.is_broken: | ||||
|             self.is_broken = True | ||||
|             self.sounds['coffin_shatter'].play() | ||||
|             play_sound(self.sounds['coffin_shatter']) | ||||
|             self.level.player.stats.update_stat('Coffins broken', 1) | ||||
|             self.level.player.stats.update_stat('Coffins remaining', -1) | ||||
|          | ||||
|   | ||||
							
								
								
									
										38
									
								
								src/level.py
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/level.py
									
									
									
									
									
								
							| @@ -181,20 +181,23 @@ class Level: | ||||
|                  | ||||
|             # Check for item collection | ||||
|             if abs(item.xPos - self.player.xPos) < 1 and self.player.isJumping: | ||||
|                 self.sounds[f'get_{item.soundName}'].play() | ||||
|                 play_sound(self.sounds[f'get_{item.soundName}']) | ||||
|                 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: | ||||
|         # Only get attack range if attack is active | ||||
|         if self.player.currentWeapon and self.player.currentWeapon.is_attack_active(currentTime): | ||||
|             attackRange = self.player.currentWeapon.get_attack_range(self.player.xPos, self.player.facingRight) | ||||
|          | ||||
|             # Check for enemy hits | ||||
|             for enemy in self.enemies: | ||||
|                 if enemy.isActive and enemy.xPos >= attackRange[0] and enemy.xPos <= attackRange[1]: | ||||
|                     if self.weapon_hit_channel is None or not self.weapon_hit_channel.get_busy(): | ||||
|                         self.weapon_hit_channel = self.sounds[self.player.currentWeapon.hitSound].play() | ||||
|                         self.weapon_hit_channel = play_sound(self.sounds[self.player.currentWeapon.hitSound]) | ||||
|  | ||||
|                     enemy.take_damage(self.player.currentWeapon.damage) | ||||
|                 else: | ||||
| @@ -230,7 +233,7 @@ class Level: | ||||
|                 distance = abs(self.player.xPos - obj.xPos) | ||||
|                 if distance <= 2 and not self.player.isJumping: | ||||
|                     if self.edge_warning_channel is None or not self.edge_warning_channel.get_busy(): | ||||
|                         self.edge_warning_channel = self.sounds['edge'].play() | ||||
|                         self.edge_warning_channel = play_sound(self.sounds['edge']) | ||||
|             else: | ||||
|                 if self.edge_warning_channel is not None and not self.edge_warning_channel.get_busy(): | ||||
|                     self.edge_warning_channel = None | ||||
| @@ -239,16 +242,31 @@ class Level: | ||||
|                 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() | ||||
|                         play_sound(self.sounds[f'get_{obj.soundName}']) | ||||
|                         obj.collect_at_position(currentPos) | ||||
|                         self.player.collectedItems.append(obj.soundName) | ||||
|                         self.player.stats.update_stat('Items collected', 1) | ||||
|                         if obj.soundName == "coin": | ||||
|                             self.player._coins += 1 | ||||
|                             self.player.stats.update_stat('Bone dust', 1) | ||||
|                             if self.player._coins % 5 == 0: | ||||
|                                 # Only heal if below max health | ||||
|                                 if self.player.get_health() < self.player.get_max_health(): | ||||
|                                     self.player.set_health(min( | ||||
|                                     self.player.get_health() + 1, | ||||
|                                     self.player.get_max_health() | ||||
|                                     )) | ||||
|  | ||||
|                             if self.player._coins % 100 == 0: | ||||
|                                 # Extra life | ||||
|                                 speak("Extra life") | ||||
|                                 self.player._coins = 0 | ||||
|                                 self.player._lives += 1 | ||||
|                                 play_sound(self.sounds['extra_life']) | ||||
|  | ||||
|                 elif obj.isHazard and not self.player.isJumping: | ||||
|                     if not self.player.isInvincible: | ||||
|                         self.sounds[obj.soundName].play() | ||||
|                         play_sound(self.sounds[obj.soundName]) | ||||
|                         speak("You fell in an open grave!") | ||||
|                         self.player.set_health(0) | ||||
|                         return False | ||||
| @@ -269,7 +287,7 @@ class Level: | ||||
|                     if self.player.xPos >= obj.xPos: | ||||
|                         # Stop all current sounds and play end level sound | ||||
|                         pygame.mixer.stop() | ||||
|                         self.sounds["end_of_level"].play() | ||||
|                         play_sound(self.sounds['end_of_level']) | ||||
|                         return True | ||||
|  | ||||
|         return False | ||||
| @@ -289,9 +307,7 @@ class Level: | ||||
|                     # Calculate volume and pan for splat sound based on final position | ||||
|                     volume, left, right = calculate_volume_and_pan(self.player.xPos, proj.x) | ||||
|                     if volume > 0:  # Only play if within audible range | ||||
|                         channel = self.sounds["pumpkin_splat"].play() | ||||
|                         if channel: | ||||
|                             channel.set_volume(volume * left, volume * right) | ||||
|                         obj_play(self.sounds, 'pumpkin_splat', self.player.xPos, proj.x, loop=False) | ||||
|                     break | ||||
|                      | ||||
|     def throw_projectile(self): | ||||
| @@ -307,4 +323,4 @@ class Level: | ||||
|             proj_info['direction'] | ||||
|         )) | ||||
|         # Play throw sound | ||||
|         self.sounds['throw_jack_o_lantern'].play() | ||||
|         play_sound(self.sounds['throw_jack_o_lantern']) | ||||
|   | ||||
| @@ -39,7 +39,7 @@ class Player: | ||||
|         # Power-up states | ||||
|         self.isInvincible = False | ||||
|         self.invincibilityStartTime = 0 | ||||
|         self.invincibilityDuration = 5000  # 5 seconds of invincibility | ||||
|         self.invincibilityDuration = 10000  # 10 seconds of invincibility | ||||
|          | ||||
|         # Initialize starting weapon (rusty shovel) | ||||
|         self.add_weapon(Weapon( | ||||
|   | ||||
| @@ -44,10 +44,8 @@ class PowerUp(Object): | ||||
|         """Apply the item's effect when collected""" | ||||
|         if self.item_type == 'hand_of_glory': | ||||
|             player.start_invincibility() | ||||
|             speak("Hand of Glory makes you invincible!") | ||||
|         elif self.item_type == 'jack_o_lantern': | ||||
|             player.add_jack_o_lantern() | ||||
|             speak("Gained a Jack-o'-lantern!") | ||||
|          | ||||
|         # Stop movement sound when collected | ||||
|         if self.channel: | ||||
|   | ||||
| @@ -33,7 +33,7 @@ class SkullStorm(Object): | ||||
|         inRange = self.xRange[0] <= player.xPos <= self.xRange[1] | ||||
|         if inRange and not self.playerInRange: | ||||
|             # Player just entered range - play the warning sound | ||||
|             self.sounds['skull_storm'].play() | ||||
|             play_sound(self.sounds['skull_storm']) | ||||
|             self.playerInRange = True | ||||
|         elif not inRange and self.playerInRange:  # Only speak when actually leaving range | ||||
|             # Player just left range | ||||
| @@ -62,7 +62,7 @@ class SkullStorm(Object): | ||||
|                     skull['x'], | ||||
|                     self.yPos, | ||||
|                     currentY, | ||||
|                     existingChannel=skull['channel'] | ||||
|                     existing_channel=skull['channel'] | ||||
|                 ) | ||||
|          | ||||
|         # Check if we should spawn a new skull | ||||
| @@ -100,10 +100,7 @@ class SkullStorm(Object): | ||||
|         channel = pygame.mixer.find_channel(True)  # Find an available channel | ||||
|         if channel: | ||||
|             soundObj = self.sounds['skull_lands'] | ||||
|             channel.play(soundObj, 0)  # Play once (0 = no loops) | ||||
|             # Apply positional audio | ||||
|             volume, left, right = calculate_volume_and_pan(player.xPos, skull['x']) | ||||
|             channel.set_volume(volume * left, volume * right) | ||||
|             obj_play(self.sounds, 'skull_lands', player.xPos, skull['x'], loop=False) | ||||
|  | ||||
|         # Check if player was hit | ||||
|         if abs(player.xPos - skull['x']) < 1:  # Within 1 tile | ||||
|   | ||||
| @@ -67,7 +67,7 @@ class WickedQuest: | ||||
|          | ||||
|         # Status queries | ||||
|         if keys[pygame.K_c]: | ||||
|             speak(f"{player.get_coins()} coins") | ||||
|             speak(f"{player.get_coins()} gbone dust") | ||||
|         if keys[pygame.K_h]: | ||||
|             speak(f"{player.get_health()} HP") | ||||
|         if keys[pygame.K_l]: | ||||
| @@ -82,25 +82,25 @@ class WickedQuest: | ||||
|  | ||||
|         # Handle attack with either CTRL key | ||||
|         if (keys[pygame.K_LCTRL] or keys[pygame.K_RCTRL]) and player.start_attack(currentTime): | ||||
|             self.sounds[player.currentWeapon.attackSound].play() | ||||
|             play_sound(self.sounds[player.currentWeapon.attackSound]) | ||||
|              | ||||
|         # Play footstep sounds if moving and not jumping | ||||
|         if movementDistance > 0 and not player.isJumping: | ||||
|             player.distanceSinceLastStep += movementDistance | ||||
|             if player.distanceSinceLastStep >= player.stepDistance: | ||||
|                 self.sounds['footstep'].play() | ||||
|                 play_sound(self.sounds['footstep']) | ||||
|                 player.distanceSinceLastStep = 0 | ||||
|  | ||||
|         # Handle jumping | ||||
|         if keys[pygame.K_w] and not player.isJumping: | ||||
|             player.isJumping = True | ||||
|             player.jumpStartTime = currentTime | ||||
|             self.sounds['jump'].play() | ||||
|             play_sound(self.sounds['jump']) | ||||
|      | ||||
|         # Check if jump should end | ||||
|         if player.isJumping and currentTime - player.jumpStartTime >= player.jumpDuration: | ||||
|             player.isJumping = False | ||||
|             self.sounds['footstep'].play() | ||||
|             play_sound(self.sounds['footstep']) | ||||
|             # Reset step distance tracking after landing | ||||
|             player.distanceSinceLastStep = 0 | ||||
|  | ||||
| @@ -149,8 +149,23 @@ class WickedQuest: | ||||
|         while True: | ||||
|             currentTime = pygame.time.get_ticks() | ||||
|      | ||||
|             if check_for_exit(): | ||||
|             # Game volume controls | ||||
|             for event in pygame.event.get(): | ||||
|                 if event.type == pygame.KEYDOWN: | ||||
|                     if event.key == pygame.K_ESCAPE: | ||||
|                         return | ||||
|                     if event.key == pygame.K_PAGEUP: | ||||
|                         adjust_master_volume(0.1) | ||||
|                     elif event.key == pygame.K_PAGEDOWN: | ||||
|                         adjust_master_volume(-0.1) | ||||
|                     elif event.key == pygame.K_HOME: | ||||
|                         adjust_bgm_volume(0.1) | ||||
|                     elif event.key == pygame.K_END: | ||||
|                         adjust_bgm_volume(-0.1) | ||||
|                     elif event.key == pygame.K_INSERT: | ||||
|                         adjust_sfx_volume(0.1) | ||||
|                     elif event.key == pygame.K_DELETE: | ||||
|                         adjust_sfx_volume(-0.1) | ||||
|  | ||||
|             # Update game state | ||||
|             self.currentLevel.player.update(currentTime) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user